2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
11 * Includes _________________________________________________________________
18 #include <afsconfig.h>
19 #include <afs/param.h>
26 #include "volume_utils.h"
28 #include "partition_utils.h"
32 * Definitions _________________________________________________________________
35 static HWND m_hDriveList = 0;
37 //static const UINT MAX_DRIVES = 26;
38 static const UINT DISK_DRIVE_IMAGE = 0;
39 static const UINT DISABLED_DISK_DRIVE_IMAGE = 1;
40 static const UINT DISK_DRIVE_WITH_WARNING_IMAGE = 2;
41 static const UINT AFS_DISK_DRIVE_IMAGE = 3;
46 TCHAR szRootDir[4]; // Drive letter plus colon plus slash, ex: "c:\"
48 TCHAR szSize[32]; // Drive size in megabytes
50 BOOL bDisabled; // Disabled is TRUE if partition not suitable for AFS
51 UINT nImage; // Image to show in the FastList
56 * Prototypes ____________________________________________________________________
62 * Static Functions _________________________________________________________________
65 LPTSTR GetString(UINT nStrID)
67 static TCHAR szText[cchRESOURCE];
69 GetString(szText, nStrID);
74 static BOOL SetupImageLists()
76 HIMAGELIST hiList = ImageList_Create(16, 16, TRUE, 1, 1);
78 AfsAppLib_AddToImageList(hiList, IDI_DISK_DRIVE, FALSE);
79 AfsAppLib_AddToImageList(hiList, IDI_DISABLED_DISK_DRIVE, FALSE);
80 AfsAppLib_AddToImageList(hiList, IDI_DISK_DRIVE_WITH_WARNING, FALSE);
81 AfsAppLib_AddToImageList(hiList, IDI_AGGREGATE, FALSE);
83 FastList_SetImageLists(m_hDriveList, hiList, 0);
88 static void AddColumn(int nWidth, LPCTSTR pszTitle)
93 col.dwFlags = FLCF_JUSTIFY_LEFT;
95 lstrcpy(col.szText, pszTitle);
97 FastList_SetColumn(m_hDriveList, nCol++, &col);
100 static void SetupDriveListCols()
102 // Set width of cols based on width of the list
104 GetClientRect(m_hDriveList, &rect);
106 int nWidth = rect.right - rect.left;
108 // If the width of the list is too small to show all
109 // three cols in a reasonable size that will fit without
110 // scrolling, then set the width to the ideal size and
111 // make the user scroll.
112 if (nWidth < 150) // Minimum we will accept
113 nWidth = 370; // The ideal size
115 AddColumn(50, GetString(IDS_DRIVE));
116 AddColumn(nWidth - 100, GetString(IDS_NAME_OR_ERROR));
117 AddColumn(50, GetString(IDS_SIZE));
120 static LPCTSTR GetDriveSizeAsString(LPCTSTR pszRootDir)
122 _ASSERTE(pszRootDir != 0);
124 ULARGE_INTEGER liDummy;
125 ULARGE_INTEGER liSize;
126 static TCHAR szSize[64];
130 // Get partition size in bytes
131 if (GetDiskFreeSpaceEx(pszRootDir, &liDummy, &liSize, &liDummy)) {
132 // Covert to megabytes
133 ULONG nSize = (ULONG)(liSize.QuadPart / (1024 * 1024));
134 // Convert to a string
135 _ultot(nSize, szSize, 10);
136 lstrcat(szSize, TEXT(" MB"));
142 static BOOL DoesDriveContainData(LPCTSTR pszDriveRootDir)
144 TCHAR szSearchSpec[16];
145 WIN32_FIND_DATA findData;
147 _stprintf(szSearchSpec, TEXT("%s*.*"), pszDriveRootDir);
149 HANDLE hFind = FindFirstFile(szSearchSpec, &findData);
150 if (hFind == INVALID_HANDLE_VALUE)
158 static BOOL OnlyHasFolder(LPCTSTR pszRootDir, LPCTSTR pszFolder)
160 TCHAR szSearchSpec[MAX_PATH];
161 WIN32_FIND_DATA findData;
164 _stprintf(szSearchSpec, TEXT("%s*.*"), pszRootDir);
166 // If there is nothing in the root dir, then return FALSE
167 HANDLE hFind = FindFirstFile(szSearchSpec, &findData);
168 if (hFind == INVALID_HANDLE_VALUE)
171 // Is the first thing on the disk the recycle bin? If not
172 // the the recycle bin is not the only thing on the disk.
173 if (_tcsicmp(findData.cFileName, pszFolder) == 0) {
174 // Is anything else on the disk?
175 if (!FindNextFile(hFind, &findData))
184 static BOOL DriveHasRecycleBin(LPCTSTR pszDriveRootDir)
186 if (OnlyHasFolder(pszDriveRootDir, TEXT("Recycled")))
189 if (OnlyHasFolder(pszDriveRootDir, TEXT("Recycle Bin")))
192 if (OnlyHasFolder(pszDriveRootDir, TEXT("Recycler")))
198 static BOOL DoesDriveContainNT(LPCTSTR pszDriveRootDir)
200 UINT nBufSize = MAX_PATH;
201 LPTSTR pszWinDir = 0;
204 pszWinDir = new TCHAR[nBufSize];
206 UINT nWinDirLen = GetWindowsDirectory(pszWinDir, nBufSize);
208 if (nWinDirLen > nBufSize) {
209 nBufSize = nWinDirLen;
215 BOOL bNT = (_tcsncmp(pszDriveRootDir, pszWinDir, 3) == 0);
222 static BOOL ValidateDrive(BOOL bInvalid, UINT uiErrorMsgID, LPTSTR pszErrorStr)
228 lstrcat(pszErrorStr, GetString(IDS_ERROR_SEP));
229 lstrcat(pszErrorStr, GetString(uiErrorMsgID));
234 static BOOL GetDriveInfo(TCHAR chDrive, DRIVE_INFO& di)
240 _stprintf(di.szRootDir, TEXT("%c:\\"), chDrive);
242 if (GetDriveType(di.szRootDir) != DRIVE_FIXED)
245 if (!GetVolumeInformation(di.szRootDir, di.szVolName, sizeof(di.szVolName), 0, &dwDummy, &dwDriveFlags, szFileSys, sizeof(szFileSys)))
248 TCHAR szError[256] = TEXT("");
250 BOOL bInvalid = FALSE, bHasData = FALSE;
251 BOOL bIsAfs = ValidateDrive(IsAnAfsPartition(di.szRootDir), IDS_ERROR_DRIVE_ALREADY_HAS_AFS, szError);
253 bInvalid |= ValidateDrive(dwDriveFlags & FS_VOL_IS_COMPRESSED, IDS_ERROR_DRIVE_COMPRESSED, szError);
254 bInvalid |= ValidateDrive(lstrcmp(szFileSys, TEXT("NTFS")) != 0, IDS_ERROR_FS_IS_NOT_NTFS, szError);
257 * We are no longer going to require that afs drives be empty; we will give a warning instead.
259 * bInvalid |= ValidateDrive(DoesDriveContainNT(di.szRootDir), IDS_ERROR_DRIVE_CONTAINS_NT, szError);
260 * bRecycle = ValidateDrive(DriveHasRecycleBin(di.szRootDir), IDS_WARNING_DRIVE_HAS_RECYCLE_BIN, szError);
263 bHasData = ValidateDrive(DoesDriveContainData(di.szRootDir), IDS_ERROR_DRIVE_HAS_DATA, szError);
267 lstrcpy(di.szVolName, szError);
270 di.nImage = AFS_DISK_DRIVE_IMAGE;
272 di.nImage = DISK_DRIVE_WITH_WARNING_IMAGE; // Treat this as a warning
274 di.nImage = DISABLED_DISK_DRIVE_IMAGE;
276 if (bIsAfs || bInvalid) {
278 di.dwFlags |= FLIF_DISALLOW_SELECT;
281 di.nImage = DISK_DRIVE_IMAGE;
283 if (lstrlen(di.szVolName) == 0)
284 GetString(di.szVolName, IDS_VOLUME_HAS_NO_NAME);
287 lstrncpy(di.szSize, GetDriveSizeAsString(di.szRootDir), sizeof(di.szSize));
292 static BOOL FillDriveList()
296 TCHAR chDrive = TEXT('A');
297 DWORD dwDrives = GetLogicalDrives();
299 // This failing is not fatal to this function
300 // Make sure the partition table is up to date
301 afs_status_t nStatus;
302 int nResult = ReadPartitionTable(&nStatus);
307 memset(&di, 0, sizeof(di));
309 if (GetDriveInfo(chDrive, di)) {
310 FASTLISTADDITEM ai = { 0, di.nImage, IMAGE_NOIMAGE, di.szRootDir, di.bDisabled, di.dwFlags };
311 HLISTITEM hItem = FastList_AddItem(m_hDriveList, &ai);
312 FastList_SetItemText(m_hDriveList, hItem, 1, di.szVolName);
313 FastList_SetItemText(m_hDriveList, hItem, 2, di.szSize);
324 static int CALLBACK DriveListSortFunc(HWND hList, HLISTITEM hItem1, LPARAM lpItem1, HLISTITEM hItem2, LPARAM lpItem2)
326 _ASSERTE(hList == m_hDriveList);
328 // Ignore the first call which is only used to initialize static data
329 if (!hItem1 && !hItem2)
332 // The lpItem vars contain 1 if the item is disabled, 0 if not
333 // Show enabled items before disabled items
334 if (lpItem1 != lpItem2)
335 return lpItem1 - lpItem2;
337 LPCTSTR pszItem1 = FastList_GetItemText(m_hDriveList, hItem1, 0);
338 LPCTSTR pszItem2 = FastList_GetItemText(m_hDriveList, hItem2, 0);
340 return lstrcmp(pszItem1, pszItem2);
345 * Exported Functions _________________________________________________________________
348 void SetupDriveList(HWND driveList)
350 m_hDriveList = driveList;
354 SetupDriveListCols();
356 FastList_SetSortFunction(m_hDriveList, DriveListSortFunc);
359 BOOL UpdateDriveList()
361 FastList_RemoveAll(m_hDriveList);
363 return FillDriveList();