/*++ Copyright (c) 1998 Microsoft Corporation Module Name: sfspace.c Abstract: sfspace calculates the amount of space required for shell folders in a clean install of Windows 2000 and outputs the results in a form which can be copied into win95upg.inf. Author: Marc R. Whitten (marcw) 24-Mar-1999 Revision History: () --*/ #include "pch.h" #include "shlobj.h" HANDLE g_hHeap; HINSTANCE g_hInst; BOOL WINAPI MigUtil_Entry (HINSTANCE, DWORD, PVOID); //BOOL WINAPI MemDb_Entry (HINSTANCE, DWORD, PVOID); #define SFLIST \ DEFMAC(AppData, CSIDL_APPDATA) \ DEFMAC(Cache, CSIDL_INTERNET_CACHE) \ DEFMAC(Cookies, CSIDL_COOKIES) \ DEFMAC(Desktop, CSIDL_DESKTOPDIRECTORY) \ DEFMAC(Favorites, CSIDL_FAVORITES) \ DEFMAC(History, CSIDL_HISTORY) \ DEFMAC(Local AppData, CSIDL_LOCAL_APPDATA) \ DEFMAC(Local Settings, CSIDL_LOCAL_APPDATA) \ DEFMAC(My Pictures, CSIDL_MYPICTURES) \ DEFMAC(NetHood, CSIDL_NETHOOD) \ DEFMAC(Personal, CSIDL_PERSONAL) \ DEFMAC(PrintHood, CSIDL_PRINTHOOD) \ DEFMAC(Programs, CSIDL_PROGRAMS) \ DEFMAC(Recent, CSIDL_RECENT) \ DEFMAC(SendTo, CSIDL_SENDTO) \ DEFMAC(Start Menu, CSIDL_STARTMENU) \ DEFMAC(StartUp, CSIDL_STARTUP) \ DEFMAC(Templates, CSIDL_TEMPLATES) \ DEFMAC(Common AppData, CSIDL_COMMON_APPDATA) \ DEFMAC(Common Desktop, CSIDL_COMMON_DESKTOPDIRECTORY) \ DEFMAC(Common Personal, CSIDL_COMMON_DOCUMENTS) \ DEFMAC(Common Favorites, CSIDL_COMMON_FAVORITES) \ DEFMAC(Common Programs, CSIDL_COMMON_PROGRAMS) \ DEFMAC(Common Start Menu, CSIDL_COMMON_STARTMENU) \ DEFMAC(Common StartUp, CSIDL_COMMON_STARTUP) \ DEFMAC(Common Templates, CSIDL_COMMON_TEMPLATES) \ enum { CS_512 = 0, CS_1024, CS_2048, CS_4096, CS_8192, CS_16384, CS_32768, CS_65536, CS_131072, CS_262144, LAST_CLUSTER_SIZE }; typedef struct { PCTSTR RegKey; UINT Csidl; PCTSTR Path; LONG TableOffset; LONG SpaceNeeded[LAST_CLUSTER_SIZE]; LONG RawSize; UINT FileCount; UINT DirectoryCount; } SFDATA, *PSFDATA; #define DEFMAC(regName, csidl) {TEXT(#regName),(csidl)}, SFDATA g_Data[] = {SFLIST /*, */ {NULL,0}}; HASHTABLE g_Table; POOLHANDLE g_Pool; BOOL g_Verbose = FALSE; UINT g_ClusterTable[LAST_CLUSTER_SIZE] = {512,1024,2048,4096,8192,16384,32768,65536,131072,262144}; #define DIRECTORY_SIZE 512 BOOL pCallEntryPoints ( DWORD Reason ) { HINSTANCE Instance; // // Simulate DllMain // Instance = g_hInst; // // Initialize the common libs // if (!MigUtil_Entry (Instance, Reason, NULL)) { return FALSE; } /* if (!MemDb_Entry (Instance, Reason, NULL)) { return FALSE; } */ return TRUE; } BOOL Init ( VOID ) { g_hHeap = GetProcessHeap(); g_hInst = GetModuleHandle (NULL); return pCallEntryPoints (DLL_PROCESS_ATTACH); } VOID Terminate ( VOID ) { pCallEntryPoints (DLL_PROCESS_DETACH); } BOOL pInitShellFolderData ( VOID ) { PSFDATA sf; TCHAR buffer[MAX_TCHAR_PATH]; PTSTR p; sf = g_Data; while (sf->RegKey) { if (SHGetFolderPath (NULL, sf->Csidl, NULL, 0, buffer) != S_OK) { _ftprintf (stderr, TEXT("sfspace: Unable to retrieve folder path for %s.\n"), sf->RegKey); return FALSE; } sf->Path = PoolMemDuplicateString (g_Pool, buffer); // // We don't have a CSIDL for the local settings directory. We need to hack it. // if (StringIMatch (sf->RegKey, TEXT("Local Settings"))) { p = _tcsrchr (sf->Path, TEXT('\\')); MYASSERT (p); *p = 0; if (g_Verbose) { _tprintf (TEXT("sfspace: Hacked path of local settings to %s.\n"), sf->Path); } } sf->TableOffset = HtAddString (g_Table, sf->Path); if (g_Verbose) { _tprintf (TEXT("sfspace: Shell folder %s has path %s.\n"), sf->RegKey, sf->Path); } sf++; } return TRUE; } BOOL pGatherSpaceRequirements ( VOID ) { PSFDATA sf; UINT i; TREE_ENUM e; LONG offset; sf = g_Data; while (sf->RegKey) { if (EnumFirstFileInTree (&e, sf->Path, NULL, FALSE)) { do { if (e.Directory) { // // Check to see if this is a different shell folder. // offset = HtFindString (g_Table, e.FullPath); if (offset && offset != sf->TableOffset) { // // This is actually another shell folder. Don't enumerate // it. // if (g_Verbose) { _tprintf (TEXT("sfspace: %s is handled by another shell folder.\n"), e.FullPath); } AbortEnumCurrentDir (&e); } else { // // Increment directory count for this shell folder. // sf->DirectoryCount++; } } else { // // this is a file. Add its data to our structure. // sf->FileCount++; sf->RawSize += e.FindData->nFileSizeLow; for (i=0; inFileSizeHigh); sf->SpaceNeeded[i] += ((e.FindData->nFileSizeLow / g_ClusterTable[i]) * g_ClusterTable[i]) + g_ClusterTable[i]; } } } while (EnumNextFileInTree (&e)); } // // Add the space for all of the directories we found in this shell folder. // for (i=0; iSpaceNeeded[i] += (((sf->DirectoryCount * DIRECTORY_SIZE) / g_ClusterTable[i]) * g_ClusterTable[i]) + g_ClusterTable[i]; } if (g_Verbose) { _tprintf ( TEXT("sfspace: %u files and %u directories enumerated for shell folder %s. Space needed (512k cluster size): %u Raw Space: %u\n"), sf->FileCount, sf->DirectoryCount, sf->RegKey, sf->SpaceNeeded[CS_512], sf->RawSize ); } sf++; } return TRUE; } PCTSTR pLeftJustify ( IN PCTSTR String, IN UINT FieldWidth ) { static TCHAR rBuffer[MAX_TCHAR_PATH]; UINT length; UINT i; MYASSERT(String); length = CharCount (String); MYASSERT(FieldWidth < MAX_TCHAR_PATH && length < FieldWidth); StringCopy (rBuffer,String); for (i=length; iRegKey) { _tprintf (TEXT("%s"),pLeftJustify (sf->RegKey,20)); for (i=0; i