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 _________________________________________________________________
15 #include <afs/param.h>
21 #include "volume_utils.h"
23 #include "partition_utils.h"
27 * Definitions _________________________________________________________________
30 static HWND m_hDriveList = 0;
32 static const UINT MAX_DRIVES = 26;
33 static const UINT DISK_DRIVE_IMAGE = 0;
34 static const UINT DISABLED_DISK_DRIVE_IMAGE = 1;
35 static const UINT DISK_DRIVE_WITH_WARNING_IMAGE = 2;
36 static const UINT AFS_DISK_DRIVE_IMAGE = 3;
41 TCHAR szRootDir[4]; // Drive letter plus colon plus slash, ex: "c:\"
43 TCHAR szSize[32]; // Drive size in megabytes
45 BOOL bDisabled; // Disabled is TRUE if partition not suitable for AFS
46 UINT nImage; // Image to show in the FastList
51 * Prototypes ____________________________________________________________________
57 * Static Functions _________________________________________________________________
60 LPTSTR GetString(UINT nStrID)
62 static TCHAR szText[cchRESOURCE];
64 GetString(szText, nStrID);
69 static BOOL SetupImageLists()
71 HIMAGELIST hiList = ImageList_Create(16, 16, TRUE, 1, 1);
73 AfsAppLib_AddToImageList(hiList, IDI_DISK_DRIVE, FALSE);
74 AfsAppLib_AddToImageList(hiList, IDI_DISABLED_DISK_DRIVE, FALSE);
75 AfsAppLib_AddToImageList(hiList, IDI_DISK_DRIVE_WITH_WARNING, FALSE);
76 AfsAppLib_AddToImageList(hiList, IDI_AGGREGATE, FALSE);
78 FastList_SetImageLists(m_hDriveList, hiList, 0);
83 static void AddColumn(int nWidth, LPCTSTR pszTitle)
88 col.dwFlags = FLCF_JUSTIFY_LEFT;
90 lstrcpy(col.szText, pszTitle);
92 FastList_SetColumn(m_hDriveList, nCol++, &col);
95 static void SetupDriveListCols()
97 // Set width of cols based on width of the list
99 GetClientRect(m_hDriveList, &rect);
101 int nWidth = rect.right - rect.left;
103 // If the width of the list is too small to show all
104 // three cols in a reasonable size that will fit without
105 // scrolling, then set the width to the ideal size and
106 // make the user scroll.
107 if (nWidth < 150) // Minimum we will accept
108 nWidth = 370; // The ideal size
110 AddColumn(50, GetString(IDS_DRIVE));
111 AddColumn(nWidth - 100, GetString(IDS_NAME_OR_ERROR));
112 AddColumn(50, GetString(IDS_SIZE));
115 static LPCTSTR GetDriveSizeAsString(LPCTSTR pszRootDir)
117 _ASSERTE(pszRootDir != 0);
119 ULARGE_INTEGER liDummy;
120 ULARGE_INTEGER liSize;
121 static TCHAR szSize[64];
125 // Get partition size in bytes
126 if (GetDiskFreeSpaceEx(pszRootDir, &liDummy, &liSize, &liDummy)) {
127 // Covert to megabytes
128 ULONG nSize = (ULONG)(liSize.QuadPart / (1024 * 1024));
129 // Convert to a string
130 _ultot(nSize, szSize, 10);
131 lstrcat(szSize, TEXT(" MB"));
137 static BOOL DoesDriveContainData(LPCTSTR pszDriveRootDir)
139 TCHAR szSearchSpec[16];
140 WIN32_FIND_DATA findData;
142 _stprintf(szSearchSpec, TEXT("%s*.*"), pszDriveRootDir);
144 HANDLE hFind = FindFirstFile(szSearchSpec, &findData);
145 if (hFind == INVALID_HANDLE_VALUE)
153 static BOOL OnlyHasFolder(LPCTSTR pszRootDir, LPCTSTR pszFolder)
155 TCHAR szSearchSpec[MAX_PATH];
156 WIN32_FIND_DATA findData;
159 _stprintf(szSearchSpec, TEXT("%s*.*"), pszRootDir);
161 // If there is nothing in the root dir, then return FALSE
162 HANDLE hFind = FindFirstFile(szSearchSpec, &findData);
163 if (hFind == INVALID_HANDLE_VALUE)
166 // Is the first thing on the disk the recycle bin? If not
167 // the the recycle bin is not the only thing on the disk.
168 if (_tcsicmp(findData.cFileName, pszFolder) == 0) {
169 // Is anything else on the disk?
170 if (!FindNextFile(hFind, &findData))
179 static BOOL DriveHasRecycleBin(LPCTSTR pszDriveRootDir)
181 if (OnlyHasFolder(pszDriveRootDir, TEXT("Recycled")))
184 if (OnlyHasFolder(pszDriveRootDir, TEXT("Recycle Bin")))
187 if (OnlyHasFolder(pszDriveRootDir, TEXT("Recycler")))
193 static BOOL DoesDriveContainNT(LPCTSTR pszDriveRootDir)
195 UINT nBufSize = MAX_PATH;
196 LPTSTR pszWinDir = 0;
199 pszWinDir = new TCHAR[nBufSize];
201 UINT nWinDirLen = GetWindowsDirectory(pszWinDir, nBufSize);
203 if (nWinDirLen > nBufSize) {
204 nBufSize = nWinDirLen;
210 BOOL bNT = (_tcsncmp(pszDriveRootDir, pszWinDir, 3) == 0);
217 static BOOL ValidateDrive(BOOL bInvalid, UINT uiErrorMsgID, LPTSTR pszErrorStr)
223 lstrcat(pszErrorStr, GetString(IDS_ERROR_SEP));
224 lstrcat(pszErrorStr, GetString(uiErrorMsgID));
229 static BOOL GetDriveInfo(TCHAR chDrive, DRIVE_INFO& di)
235 _stprintf(di.szRootDir, TEXT("%c:\\"), chDrive);
237 if (GetDriveType(di.szRootDir) != DRIVE_FIXED)
240 if (!GetVolumeInformation(di.szRootDir, di.szVolName, sizeof(di.szVolName), 0, &dwDummy, &dwDriveFlags, szFileSys, sizeof(szFileSys)))
243 TCHAR szError[256] = TEXT("");
245 BOOL bInvalid = FALSE, bHasData = FALSE;
246 BOOL bIsAfs = ValidateDrive(IsAnAfsPartition(di.szRootDir), IDS_ERROR_DRIVE_ALREADY_HAS_AFS, szError);
248 bInvalid |= ValidateDrive(dwDriveFlags & FS_VOL_IS_COMPRESSED, IDS_ERROR_DRIVE_COMPRESSED, szError);
249 bInvalid |= ValidateDrive(lstrcmp(szFileSys, TEXT("NTFS")) != 0, IDS_ERROR_FS_IS_NOT_NTFS, szError);
252 * We are no longer going to require that afs drives be empty; we will give a warning instead.
254 * bInvalid |= ValidateDrive(DoesDriveContainNT(di.szRootDir), IDS_ERROR_DRIVE_CONTAINS_NT, szError);
255 * bRecycle = ValidateDrive(DriveHasRecycleBin(di.szRootDir), IDS_WARNING_DRIVE_HAS_RECYCLE_BIN, szError);
258 bHasData = ValidateDrive(DoesDriveContainData(di.szRootDir), IDS_ERROR_DRIVE_HAS_DATA, szError);
262 lstrcpy(di.szVolName, szError);
265 di.nImage = AFS_DISK_DRIVE_IMAGE;
267 di.nImage = DISK_DRIVE_WITH_WARNING_IMAGE; // Treat this as a warning
269 di.nImage = DISABLED_DISK_DRIVE_IMAGE;
271 if (bIsAfs || bInvalid) {
273 di.dwFlags |= FLIF_DISALLOW_SELECT;
276 di.nImage = DISK_DRIVE_IMAGE;
278 if (lstrlen(di.szVolName) == 0)
279 GetString(di.szVolName, IDS_VOLUME_HAS_NO_NAME);
282 lstrncpy(di.szSize, GetDriveSizeAsString(di.szRootDir), sizeof(di.szSize));
287 static BOOL FillDriveList()
291 TCHAR chDrive = TEXT('A');
292 DWORD dwDrives = GetLogicalDrives();
294 // This failing is not fatal to this function
295 // Make sure the partition table is up to date
296 afs_status_t nStatus;
297 int nResult = ReadPartitionTable(&nStatus);
302 memset(&di, 0, sizeof(di));
304 if (GetDriveInfo(chDrive, di)) {
305 FASTLISTADDITEM ai = { 0, di.nImage, IMAGE_NOIMAGE, di.szRootDir, di.bDisabled, di.dwFlags };
306 HLISTITEM hItem = FastList_AddItem(m_hDriveList, &ai);
307 FastList_SetItemText(m_hDriveList, hItem, 1, di.szVolName);
308 FastList_SetItemText(m_hDriveList, hItem, 2, di.szSize);
319 static int CALLBACK DriveListSortFunc(HWND hList, HLISTITEM hItem1, LPARAM lpItem1, HLISTITEM hItem2, LPARAM lpItem2)
321 _ASSERTE(hList == m_hDriveList);
323 // Ignore the first call which is only used to initialize static data
324 if (!hItem1 && !hItem2)
327 // The lpItem vars contain 1 if the item is disabled, 0 if not
328 // Show enabled items before disabled items
329 if (lpItem1 != lpItem2)
330 return lpItem1 - lpItem2;
332 LPCTSTR pszItem1 = FastList_GetItemText(m_hDriveList, hItem1, 0);
333 LPCTSTR pszItem2 = FastList_GetItemText(m_hDriveList, hItem2, 0);
335 return lstrcmp(pszItem1, pszItem2);
340 * Exported Functions _________________________________________________________________
343 void SetupDriveList(HWND driveList)
345 m_hDriveList = driveList;
349 SetupDriveListCols();
351 FastList_SetSortFunction(m_hDriveList, DriveListSortFunc);
354 BOOL UpdateDriveList()
356 FastList_RemoveAll(m_hDriveList);
358 return FillDriveList();