Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

856 lines
30 KiB

  1. #include "pch.h"
  2. #pragma hdrstop
  3. #include <initguid.h>
  4. #include "uuid.h"
  5. #include <ccstock.h>
  6. #include "util.h"
  7. #include "config.h"
  8. #include "security.h"
  9. const TCHAR g_szKeyPolicy[] = TEXT("Software\\Policies\\Microsoft\\Windows\\NetCache");
  10. const TCHAR g_szKeyPrefs[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\NetCache");
  11. const TCHAR g_szKeyCustomActions[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\NetCache\\CustomGoOfflineActions");
  12. const TCHAR g_szValEnabled[] = TEXT("Enabled");
  13. const TCHAR g_szValEncrypted[] = TEXT("Encrypted");
  14. const TCHAR g_szValGoOfflineAction[] = TEXT("GoOfflineAction");
  15. const TCHAR g_szValDefCacheSize[] = TEXT("DefCacheSize");
  16. const TCHAR g_szValNoConfigCache[] = TEXT("NoConfigCache");
  17. const TCHAR g_szValNoCacheViewer[] = TEXT("NoCacheViewer");
  18. const TCHAR g_szValNoMakeAvailableOffline[] = TEXT("NoMakeAvailableOffline");
  19. const TCHAR g_szValNoReminders[] = TEXT("NoReminders");
  20. const TCHAR g_szValNoConfigReminders[] = TEXT("NoConfigReminders");
  21. const TCHAR g_szValSyncAtLogoff[] = TEXT("SyncAtLogoff");
  22. const TCHAR g_szValReminderFreqMinutes[] = TEXT("ReminderFreqMinutes");
  23. const TCHAR g_szValInitialBalloonTimeout[] = TEXT("InitialBalloonTimeoutSeconds");
  24. const TCHAR g_szValReminderBalloonTimeout[] = TEXT("ReminderBalloonTimeoutSeconds");
  25. const TCHAR g_szValFirstPinWizardShown[] = TEXT("FirstPinWizardShown");
  26. const TCHAR g_szValExpandStatusDlg[] = TEXT("ExpandStatusDlg");
  27. const TCHAR g_szValFormatCscDb[] = TEXT("FormatDatabase");
  28. const TCHAR g_szValEventLoggingLevel[] = TEXT("EventLoggingLevel");
  29. const TCHAR g_szValPurgeAtLogoff[] = TEXT("PurgeAtLogoff");
  30. const TCHAR g_szValExtExclusionList[] = TEXT("ExtExclusionList");
  31. const TCHAR g_szValAlwaysPinSubFolders[] = TEXT("AlwaysPinSubFolders");
  32. const TCHAR g_szNA[] = TEXT("<n/a>");
  33. const DWORD POL_CU = 0x0001; // Current user
  34. const DWORD POL_LM = 0x0002; // Local machine
  35. const DWORD PREF_CU = 0x0004;
  36. const DWORD PREF_LM = 0x0008;
  37. const DWORD PREF_BOTH = PREF_CU | PREF_LM;
  38. const DWORD POL_BOTH = POL_CU | POL_LM;
  39. const DWORD REG_ALL = PREF_BOTH | POL_BOTH;
  40. const DWORD PREF = 1;
  41. const DWORD POLICY = 2;
  42. LPTSTR GoOfflineActionText(
  43. int iValue,
  44. LPTSTR pszDest
  45. )
  46. {
  47. LPCTSTR rgpsz[] = { TEXT("(Work offline)"),
  48. TEXT("(No offline)") };
  49. if (iValue >= 0 && iValue < ARRAYSIZE(rgpsz))
  50. lstrcpy(pszDest, rgpsz[iValue]);
  51. else
  52. lstrcpy(pszDest, TEXT("<unknown>"));
  53. return pszDest;
  54. }
  55. LPTSTR SyncAtLogoffText(
  56. int iValue,
  57. LPTSTR pszDest
  58. )
  59. {
  60. LPCTSTR rgpsz[] = { TEXT("(Part sync)"),
  61. TEXT("(Full sync)") };
  62. if (iValue >= 0 && iValue < ARRAYSIZE(rgpsz))
  63. lstrcpy(pszDest, rgpsz[iValue]);
  64. else
  65. lstrcpy(pszDest, TEXT("<unknown>"));
  66. return pszDest;
  67. }
  68. LPTSTR DefCacheSizeText(
  69. int iValue,
  70. LPTSTR pszDest
  71. )
  72. {
  73. wsprintf(pszDest, TEXT("(%2d.%02d %%)"), iValue / 100, iValue % 100);
  74. return pszDest;
  75. }
  76. LPCTSTR BoolText(bool b)
  77. {
  78. static const LPCTSTR rgYN[] = { TEXT("No"), TEXT("Yes") };
  79. return rgYN[int(b)];
  80. }
  81. LPCTSTR
  82. RegValStr(
  83. HKEY hkeyRoot,
  84. LPCTSTR pszSubkey,
  85. LPCTSTR pszValue,
  86. LPTSTR pszDest
  87. )
  88. {
  89. DWORD dwValue = 0;
  90. DWORD cbData = sizeof(dwValue);
  91. DWORD dwType;
  92. DWORD dwError = SHGetValue(hkeyRoot,
  93. pszSubkey,
  94. pszValue,
  95. &dwType,
  96. (LPVOID)&dwValue,
  97. &cbData);
  98. if (ERROR_SUCCESS == dwError)
  99. {
  100. wsprintf(pszDest, TEXT("%d"), dwValue);
  101. }
  102. else if (ERROR_FILE_NOT_FOUND == dwError)
  103. {
  104. lstrcpy(pszDest, TEXT("<none>"));
  105. }
  106. else
  107. {
  108. wsprintf(pszDest, TEXT("Err %d"), dwError);
  109. }
  110. return pszDest;
  111. }
  112. LPTSTR GetOsVersionInfoText(
  113. LPTSTR pszDest
  114. )
  115. {
  116. OSVERSIONINFO osvi;
  117. ZeroMemory(&osvi, sizeof(osvi));
  118. osvi.dwOSVersionInfoSize = sizeof(osvi);
  119. *pszDest = TEXT('\0');
  120. if (GetVersionEx(&osvi))
  121. {
  122. static const TCHAR szUnknown[] = TEXT("Unknown OS");
  123. static const struct
  124. {
  125. DWORD dwPlatform;
  126. DWORD dwMinorVersion;
  127. LPCTSTR pszPlatform;
  128. } rgPlatforms[] = {{ VER_PLATFORM_WIN32s, (DWORD)-1, TEXT("Win32s") },
  129. { VER_PLATFORM_WIN32_WINDOWS, 0, TEXT("Windows 95") },
  130. { VER_PLATFORM_WIN32_WINDOWS, 10, TEXT("Windows 98") },
  131. { VER_PLATFORM_WIN32_NT, (DWORD)-1, TEXT("Windows NT") }};
  132. static const struct
  133. {
  134. DWORD dwOS;
  135. LPCTSTR pszOS;
  136. } rgOS[] = {{ OS_WIN2000TERMINAL, TEXT("Windows 2000 Terminal") },
  137. { OS_WIN2000PRO, TEXT("Windows 2000 Professional") },
  138. { OS_WIN2000ADVSERVER, TEXT("Windows 2000 Advanced Server") },
  139. { OS_WIN2000DATACENTER, TEXT("Windows 2000 Data Center") },
  140. { OS_WIN2000SERVER, TEXT("Windows 2000 Server") },
  141. { OS_WIN2000, TEXT("Windows 2000") },
  142. { OS_NT5, TEXT("Windows NT") },
  143. { OS_NT4, TEXT("Windows NT") },
  144. { OS_NT, TEXT("Windows NT") },
  145. { OS_MEMPHIS_GOLD, TEXT("Windows 98") },
  146. { OS_MEMPHIS, TEXT("Windows 98 (beta)") },
  147. { OS_WIN95, TEXT("Windows 95") },
  148. { OS_WINDOWS, TEXT("Windows") }};
  149. LPCTSTR pszPlatform = szUnknown;
  150. int i = 0;
  151. //
  152. // IsOS() is the shlwapi API for figuring out the OS type. Currently, it
  153. // provides better granularity than GetVersionEx.
  154. //
  155. for (i = 0; i < ARRAYSIZE(rgOS); i++)
  156. {
  157. if (IsOS(rgOS[i].dwOS))
  158. {
  159. pszPlatform = rgOS[i].pszOS;
  160. break;
  161. }
  162. }
  163. //
  164. // If IsOS() wasn't able to determine the platform, take the platform from
  165. // the GetVersionEx results.
  166. //
  167. if (szUnknown == pszPlatform)
  168. {
  169. for (i = 0; i < ARRAYSIZE(rgPlatforms); i++)
  170. {
  171. if (rgPlatforms[i].dwPlatform == osvi.dwPlatformId)
  172. {
  173. if ((DWORD)-1 == rgPlatforms[i].dwMinorVersion ||
  174. osvi.dwMinorVersion == rgPlatforms[i].dwMinorVersion)
  175. {
  176. pszPlatform = rgPlatforms[i].pszPlatform;
  177. break;
  178. }
  179. }
  180. }
  181. }
  182. wsprintf(pszDest, TEXT("%s version %d.%d %s build %d\n\n"), pszPlatform,
  183. osvi.dwMajorVersion,
  184. osvi.dwMinorVersion,
  185. osvi.szCSDVersion,
  186. osvi.dwBuildNumber);
  187. }
  188. return pszDest;
  189. }
  190. void DumpRegStats(void)
  191. {
  192. TCHAR szScratch[MAX_PATH];
  193. CConfig &config = CConfig::GetSingleton();
  194. typedef bool (CConfig::*PBMF)(bool *bSetByPolicy) const;
  195. typedef int (CConfig::*PIMF)(bool *bSetByPolicy) const;
  196. typedef LPTSTR (*PDF)(int iValue, LPTSTR pszDest);
  197. struct
  198. {
  199. LPCTSTR pszTitle;
  200. DWORD dwReg;
  201. HKEY hkeyRoot;
  202. LPCTSTR pszSubkey;
  203. } rgRegKeys[] = {{ TEXT("Policy (LM)"), POL_LM, HKEY_LOCAL_MACHINE, g_szKeyPolicy },
  204. { TEXT("Policy (CU)"), POL_CU, HKEY_CURRENT_USER, g_szKeyPolicy },
  205. { TEXT("Pref (LM)"), PREF_LM, HKEY_LOCAL_MACHINE, g_szKeyPrefs },
  206. { TEXT("Pref (CU)"), PREF_CU, HKEY_CURRENT_USER, g_szKeyPrefs }};
  207. struct
  208. {
  209. LPCTSTR pszValue;
  210. DWORD dwReg;
  211. PBMF pfnBool;
  212. PIMF pfnInt;
  213. PDF pfnDesc;
  214. } rgRegValues[] = {
  215. { g_szValDefCacheSize, POL_LM, NULL, (PIMF)&CConfig::DefaultCacheSize, &DefCacheSizeText },
  216. { g_szValEnabled, POL_LM, &CConfig::CscEnabled, NULL, NULL },
  217. { g_szValNoConfigCache, POL_BOTH, &CConfig::NoConfigCache, NULL, NULL },
  218. { g_szValNoCacheViewer, POL_BOTH, &CConfig::NoCacheViewer, NULL, NULL },
  219. { g_szValNoMakeAvailableOffline, POL_BOTH, &CConfig::NoMakeAvailableOffline, NULL, NULL },
  220. { g_szValGoOfflineAction, PREF_CU | POL_BOTH, NULL, &CConfig::GoOfflineAction, &GoOfflineActionText },
  221. { g_szValEventLoggingLevel, REG_ALL, NULL, &CConfig::EventLoggingLevel, NULL },
  222. { g_szValFirstPinWizardShown, PREF_CU, (PBMF)&CConfig::FirstPinWizardShown, NULL, NULL },
  223. { g_szValNoReminders, POL_BOTH | PREF_CU, &CConfig::NoReminders, NULL, NULL },
  224. { g_szValPurgeAtLogoff, POL_LM, &CConfig::PurgeAtLogoff, NULL, NULL },
  225. { g_szValSyncAtLogoff, POL_BOTH | PREF_CU, NULL, &CConfig::SyncAtLogoff, &SyncAtLogoffText },
  226. { g_szValInitialBalloonTimeout, POL_BOTH, NULL, &CConfig::InitialBalloonTimeoutSeconds, NULL },
  227. { g_szValReminderBalloonTimeout, POL_BOTH, NULL, &CConfig::ReminderBalloonTimeoutSeconds, NULL },
  228. { g_szValReminderFreqMinutes, POL_BOTH | PREF_CU, NULL, &CConfig::ReminderFreqMinutes, NULL },
  229. { g_szValAlwaysPinSubFolders, POL_LM, &CConfig::AlwaysPinSubFolders, NULL, NULL }
  230. };
  231. _tprintf(TEXT("Registry Information:\n\n"));
  232. _tprintf(TEXT("%-30s%15s%15s%15s%15s%15s\n"),
  233. TEXT("Value"),
  234. rgRegKeys[0].pszTitle,
  235. rgRegKeys[1].pszTitle,
  236. rgRegKeys[2].pszTitle,
  237. rgRegKeys[3].pszTitle,
  238. TEXT("Result"));
  239. for (int iVal = 0; iVal < ARRAYSIZE(rgRegValues); iVal++)
  240. {
  241. PBMF pfnBool = rgRegValues[iVal].pfnBool;
  242. PIMF pfnInt = rgRegValues[iVal].pfnInt;
  243. _tprintf(TEXT("%-30s"), rgRegValues[iVal].pszValue);
  244. for (int iKey = 0; iKey < ARRAYSIZE(rgRegKeys); iKey++)
  245. {
  246. if (rgRegValues[iVal].dwReg & rgRegKeys[iKey].dwReg)
  247. {
  248. _tprintf(TEXT("%15s"), RegValStr(rgRegKeys[iKey].hkeyRoot,
  249. rgRegKeys[iKey].pszSubkey,
  250. rgRegValues[iVal].pszValue,
  251. szScratch));
  252. }
  253. else
  254. {
  255. _tprintf(TEXT("%15s"), g_szNA);
  256. }
  257. }
  258. int iValue = 0;
  259. if (NULL != pfnBool)
  260. iValue = (config.*pfnBool)(NULL);
  261. else
  262. iValue = (config.*pfnInt)(NULL);
  263. _tprintf(TEXT("%15d"), iValue);
  264. if (NULL != rgRegValues[iVal].pfnDesc)
  265. _tprintf(TEXT(" %s"), (*rgRegValues[iVal].pfnDesc)(iValue, szScratch));
  266. _tprintf(TEXT("\n"));
  267. }
  268. _tprintf(TEXT("\n"));
  269. CConfig::OfflineActionIter iter = config.CreateOfflineActionIter();
  270. CConfig::OfflineActionInfo oai;
  271. _tprintf(TEXT("Offline action exceptions. Default is %s:\n\n"), GoOfflineActionText(config.GoOfflineAction(), szScratch));
  272. _tprintf(TEXT("%-30s%s\n"), TEXT("Server"), TEXT("Action"));
  273. while(S_OK == iter.Next(&oai))
  274. {
  275. _tprintf(TEXT("%-30s%s\n"), oai.szServer, GoOfflineActionText(oai.iAction, szScratch));
  276. }
  277. }
  278. LPTSTR GetMachineName(
  279. LPTSTR pszDest,
  280. UINT cchDest
  281. )
  282. {
  283. ULONG cchComputer = cchDest;
  284. GetComputerName(pszDest, &cchComputer);
  285. return pszDest;
  286. }
  287. LPTSTR FormatDateTime(
  288. const SYSTEMTIME& time,
  289. LPTSTR pszDest,
  290. UINT cchDest
  291. )
  292. {
  293. LPTSTR pszWrite = pszDest;
  294. GetDateFormat(LOCALE_USER_DEFAULT,
  295. DATE_SHORTDATE,
  296. &time,
  297. NULL,
  298. pszWrite,
  299. cchDest);
  300. lstrcat(pszWrite, TEXT(" "));
  301. int len = lstrlen(pszWrite);
  302. pszWrite += len;
  303. cchDest -= len;
  304. GetTimeFormat(LOCALE_USER_DEFAULT,
  305. LOCALE_NOUSEROVERRIDE,
  306. &time,
  307. NULL,
  308. pszWrite,
  309. cchDest);
  310. return pszDest;
  311. }
  312. LPTSTR GetCurrentDateTime(
  313. LPTSTR pszDest,
  314. UINT cchDest
  315. )
  316. {
  317. SYSTEMTIME now;
  318. GetLocalTime(&now);
  319. return FormatDateTime(now, pszDest, cchDest);
  320. }
  321. LPTSTR
  322. Int64ToCommaSepString(
  323. LONGLONG n,
  324. LPTSTR pszOut,
  325. int cchOut
  326. )
  327. {
  328. ULONG ulTemp;
  329. UNICODE_STRING s;
  330. NUMBERFMTW nfmtW;
  331. LPWSTR pszFmtOutW;
  332. int cchFmtOut;
  333. WCHAR szTextW[30];
  334. WCHAR szSep[5];
  335. //
  336. // Convert the 64-bit int to a text string.
  337. //
  338. s.Length = 0;
  339. s.MaximumLength = ARRAYSIZE(szTextW);
  340. s.Buffer = szTextW;
  341. RtlInt64ToUnicodeString(n, 10, &s);
  342. //
  343. // Format the number with commas according to locale conventions.
  344. //
  345. nfmtW.NumDigits = 0;
  346. nfmtW.LeadingZero = 0;
  347. GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SGROUPING, szSep, ARRAYSIZE(szSep));
  348. RtlInitUnicodeString(&s, szSep);
  349. RtlUnicodeStringToInteger(&s, 10, &ulTemp);
  350. nfmtW.Grouping = UINT(ulTemp);
  351. GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, szSep, ARRAYSIZE(szSep));
  352. nfmtW.lpDecimalSep = nfmtW.lpThousandSep = szSep;
  353. nfmtW.NegativeOrder = 0;
  354. #ifndef UNICODE
  355. //
  356. // If ansi build we need a wide-char buffer as format destination.
  357. //
  358. WCHAR szNumW[30];
  359. pszFmtOutW = szNumW;
  360. cchFmtOut = ARRAYSIZE(szNumW);
  361. #else
  362. //
  363. // If unicode build we can format directly to the destination buffer.
  364. //
  365. pszFmtOutW = pszOut;
  366. cchFmtOut = cchOut;
  367. #endif
  368. GetNumberFormatW(LOCALE_USER_DEFAULT,
  369. 0,
  370. szTextW,
  371. &nfmtW,
  372. pszFmtOutW,
  373. cchFmtOut);
  374. #ifndef UNICODE
  375. //
  376. // If ansi build, need extra step to convert formatted number string
  377. // (wide char) back to ansi.
  378. //
  379. WideCharToMultiByte(CP_ACP,
  380. 0,
  381. pszFmtOutW,
  382. -1,
  383. pszOut,
  384. cchOut,
  385. NULL,
  386. NULL);
  387. #endif
  388. return pszOut;
  389. }
  390. void PrintFileStatusFlags(void)
  391. {
  392. struct
  393. {
  394. DWORD dwFlags;
  395. LPCTSTR pszText;
  396. } rgMap[] = {{ FLAG_CSC_COPY_STATUS_DATA_LOCALLY_MODIFIED, TEXT("Data locally modified") },
  397. { FLAG_CSC_COPY_STATUS_ATTRIB_LOCALLY_MODIFIED, TEXT("Attrib locally modified") },
  398. { FLAG_CSC_COPY_STATUS_TIME_LOCALLY_MODIFIED, TEXT("Time locally modified") },
  399. { FLAG_CSC_COPY_STATUS_STALE, TEXT("Stale") },
  400. { FLAG_CSC_COPY_STATUS_LOCALLY_DELETED, TEXT("Locally deleted") },
  401. { FLAG_CSC_COPY_STATUS_SPARSE, TEXT("Sparse") },
  402. { FLAG_CSC_COPY_STATUS_ORPHAN, TEXT("Orphan") },
  403. { FLAG_CSC_COPY_STATUS_SUSPECT, TEXT("Suspect") },
  404. { FLAG_CSC_COPY_STATUS_LOCALLY_CREATED, TEXT("Locally created") },
  405. { 0x00010000, TEXT("User has READ access") },
  406. { 0x00020000, TEXT("User has WRITE access") },
  407. { 0x00040000, TEXT("Guest has READ access") },
  408. { 0x00080000, TEXT("Guest has WRITE access") },
  409. { 0x00100000, TEXT("Other has READ access") },
  410. { 0x00200000, TEXT("Other has WRITE access") },
  411. { FLAG_CSC_COPY_STATUS_IS_FILE, TEXT("Entry is a file") },
  412. { FLAG_CSC_COPY_STATUS_FILE_IN_USE, TEXT("File in use") },
  413. };
  414. _tprintf(TEXT("\nFile status flags ------------------------\n\n"));
  415. for (int i = 0; i < ARRAYSIZE(rgMap); i++)
  416. {
  417. _tprintf(TEXT("0x%08X %s\n"), rgMap[i].dwFlags, rgMap[i].pszText);
  418. }
  419. _tprintf(TEXT("\n\n"));
  420. }
  421. void PrintShareStatusFlags(void)
  422. {
  423. struct
  424. {
  425. DWORD dwFlags;
  426. LPCTSTR pszText;
  427. } rgMap[] = {{ FLAG_CSC_SHARE_STATUS_MANUAL_REINT, TEXT("Manual Caching") }, // 0x00000000
  428. { FLAG_CSC_SHARE_STATUS_MODIFIED_OFFLINE, TEXT("Modified offline") }, // 0x00000001
  429. { FLAG_CSC_SHARE_STATUS_AUTO_REINT, TEXT("Auto Caching") }, // 0x00000040
  430. { FLAG_CSC_SHARE_STATUS_VDO, TEXT("Virtually Disconnected Ops") }, // 0x00000080
  431. { FLAG_CSC_SHARE_STATUS_NO_CACHING, TEXT("No Caching") }, // 0x000000C0
  432. { FLAG_CSC_SHARE_STATUS_FINDS_IN_PROGRESS, TEXT("Finds in progress") }, // 0x00000200
  433. { FLAG_CSC_SHARE_STATUS_FILES_OPEN, TEXT("Open files") }, // 0x00000400
  434. { FLAG_CSC_SHARE_STATUS_CONNECTED, TEXT("Connected") }, // 0x00000800
  435. { FLAG_CSC_SHARE_MERGING, TEXT("Merging") }, // 0x40000000
  436. { FLAG_CSC_SHARE_STATUS_DISCONNECTED_OP, TEXT("Disconnected Op") }, // 0x80000000
  437. };
  438. _tprintf(TEXT("\nShare status flags -------------------\n\n"));
  439. for (int i = 0; i < ARRAYSIZE(rgMap); i++)
  440. {
  441. _tprintf(TEXT("%30s0x%08X %s\n"), TEXT(""), rgMap[i].dwFlags, rgMap[i].pszText);
  442. }
  443. _tprintf(TEXT("\n\n"));
  444. }
  445. void PrintHintFlags(void)
  446. {
  447. struct
  448. {
  449. DWORD dwFlags;
  450. LPCTSTR pszText;
  451. } rgMap[] = {{ FLAG_CSC_HINT_PIN_USER, TEXT("Pin User") }, // 0x00000001
  452. { FLAG_CSC_HINT_PIN_INHERIT_USER, TEXT("Pin Inherit User") }, // 0x00000002
  453. { FLAG_CSC_HINT_PIN_INHERIT_SYSTEM, TEXT("Pin Inherit System") }, // 0x00000004
  454. { FLAG_CSC_HINT_CONSERVE_BANDWIDTH, TEXT("Conserve Bandwidth") }, // 0x00000008
  455. { FLAG_CSC_HINT_PIN_SYSTEM, TEXT("Pin System") }, // 0x00000010
  456. };
  457. _tprintf(TEXT("\nFile hint flags -------------------\n\n"));
  458. for (int i = 0; i < ARRAYSIZE(rgMap); i++)
  459. {
  460. _tprintf(TEXT("0x%08X %s\n"), rgMap[i].dwFlags, rgMap[i].pszText);
  461. }
  462. _tprintf(TEXT("\n\n"));
  463. }
  464. void DumpCacheStats(void)
  465. {
  466. DWORD dwStatus;
  467. WIN32_FIND_DATA fd;
  468. TCHAR szScratch[MAX_PATH];
  469. BOOL bEnabled = CSCIsCSCEnabled();
  470. CSCSPACEUSAGEINFO sui;
  471. ZeroMemory(&sui, sizeof(sui));
  472. GetCscSpaceUsageInfo(&sui);
  473. _tprintf(TEXT("Cache information:\n\n"));
  474. _tprintf(TEXT("CSC enabled.........: %s\n"), BoolText(boolify(CSCIsCSCEnabled())));
  475. _tprintf(TEXT("Volume..............: %s\n"), sui.szVolume);
  476. _tprintf(TEXT("Bytes on volume.....: %s\n"), Int64ToCommaSepString(sui.llBytesOnVolume, szScratch, ARRAYSIZE(szScratch)));
  477. _tprintf(TEXT("Bytes in cache......: %s\n"), Int64ToCommaSepString(sui.llBytesTotalInCache, szScratch, ARRAYSIZE(szScratch)));
  478. _tprintf(TEXT("Bytes used in cache.: %s\n"), Int64ToCommaSepString(sui.llBytesUsedInCache, szScratch, ARRAYSIZE(szScratch)));
  479. _tprintf(TEXT("Files in cache......: %d\n"), sui.dwNumFilesInCache);
  480. _tprintf(TEXT("Directories in cache: %d\n\n"), sui.dwNumDirsInCache);
  481. CCscFindHandle hFind(CacheFindFirst(NULL, &fd, &dwStatus, NULL, NULL, NULL));
  482. if (hFind.IsValid())
  483. {
  484. BOOL bResult = TRUE;
  485. CSCSHARESTATS ss;
  486. CSCCACHESTATS cs;
  487. CSCGETSTATSINFO si = { SSEF_NONE, SSUF_NONE, true, false };
  488. ZeroMemory(&cs, sizeof(cs));
  489. _tprintf(TEXT("%-30s%-12s%10s%10s%10s%10s%10s%10s%10s%10s%10s%12s\n"),
  490. TEXT("Share"),
  491. TEXT("Status"),
  492. TEXT("Files"),
  493. TEXT("Dirs"),
  494. TEXT("Pinned"),
  495. TEXT("Modified"),
  496. TEXT("Sparse"),
  497. TEXT("USER"),
  498. TEXT("GUEST"),
  499. TEXT("OTHER"),
  500. TEXT("Offline?"),
  501. TEXT("OpenFiles?"));
  502. do
  503. {
  504. cs.cShares++;
  505. if (bResult = _GetShareStatistics(fd.cFileName,
  506. &si,
  507. &ss))
  508. {
  509. _tprintf(TEXT("%-30s0x%08X %10d%10d%10d%10d%10d%10d%10d%10d%10s%12s\n"),
  510. fd.cFileName,
  511. dwStatus,
  512. ss.cTotal - ss.cDirs,
  513. ss.cDirs,
  514. ss.cPinned,
  515. ss.cModified,
  516. ss.cSparse,
  517. ss.cAccessUser,
  518. ss.cAccessGuest,
  519. ss.cAccessOther,
  520. BoolText(ss.bOffline),
  521. BoolText(ss.bOpenFiles));
  522. cs.cTotal += ss.cTotal;
  523. cs.cPinned += ss.cPinned;
  524. cs.cModified += ss.cModified;
  525. cs.cSparse += ss.cSparse;
  526. cs.cDirs += ss.cDirs;
  527. cs.cAccessUser += ss.cAccessUser;
  528. cs.cAccessGuest += ss.cAccessGuest;
  529. cs.cAccessOther += ss.cAccessOther;
  530. cs.cSharesOffline += int(ss.bOffline);
  531. cs.cSharesWithOpenFiles += int(ss.bOpenFiles);
  532. }
  533. }
  534. while(bResult && CacheFindNext(hFind, &fd, &dwStatus, NULL, NULL, NULL));
  535. _tprintf(TEXT("%-30s%-12s%10d%10d%10d%10d%10d%10d%10d%10d%10d%12d\n\n"),
  536. TEXT("SUMMARY"),
  537. TEXT(""),
  538. cs.cTotal - cs.cDirs,
  539. cs.cDirs,
  540. cs.cPinned,
  541. cs.cModified,
  542. cs.cSparse,
  543. cs.cAccessUser,
  544. cs.cAccessGuest,
  545. cs.cAccessOther,
  546. cs.cSharesOffline,
  547. cs.cSharesWithOpenFiles);
  548. }
  549. }
  550. void DumpFileInformation(LPCTSTR pszFile)
  551. {
  552. TCHAR szExpanded[MAX_PATH*2];
  553. ExpandEnvironmentStrings(pszFile, szExpanded, ARRAYSIZE(szExpanded));
  554. HANDLE hFile = CreateFile(szExpanded,
  555. GENERIC_READ,
  556. FILE_SHARE_READ,
  557. NULL,
  558. OPEN_EXISTING,
  559. FILE_ATTRIBUTE_NORMAL,
  560. NULL);
  561. if (INVALID_HANDLE_VALUE != hFile)
  562. {
  563. BY_HANDLE_FILE_INFORMATION fi;
  564. if (GetFileInformationByHandle(hFile, &fi))
  565. {
  566. TCHAR szScratch[80];
  567. ULARGE_INTEGER llSize = { fi.nFileSizeLow, fi.nFileSizeHigh };
  568. FILETIME localfiletime;
  569. SYSTEMTIME systime;
  570. FileTimeToLocalFileTime(&fi.ftLastWriteTime, &localfiletime);
  571. FileTimeToSystemTime(&localfiletime, &systime);
  572. _tprintf(TEXT("File.......: %s\n"), szExpanded);
  573. _tprintf(TEXT("Size.......: %s bytes\n"), Int64ToCommaSepString(llSize.QuadPart, szScratch, ARRAYSIZE(szScratch)));
  574. _tprintf(TEXT("Created....: %s\n\n"), FormatDateTime(systime, szScratch, ARRAYSIZE(szScratch)));
  575. }
  576. CloseHandle(hFile);
  577. }
  578. else
  579. {
  580. _tprintf(TEXT("ERROR %d opening %s\n\n"), GetLastError(), szExpanded);
  581. }
  582. }
  583. void PrintOneEnumEntry(LPCTSTR pszPath, DWORD dwStatus, DWORD dwPinCount, DWORD dwHintFlags)
  584. {
  585. _tprintf(TEXT("0x%08X %d 0x%08X %s\n"), dwStatus, dwPinCount, dwHintFlags, pszPath);
  586. }
  587. void EnumTree(LPTSTR pszPath, LPTSTR pszPathToPrint)
  588. {
  589. WIN32_FIND_DATA fd;
  590. DWORD dwStatus, dwPinCount, dwHintFlags;
  591. CCscFindHandle hFind(CacheFindFirst(pszPath, &fd, &dwStatus, &dwPinCount, &dwHintFlags, NULL));
  592. if (hFind.IsValid())
  593. {
  594. do
  595. {
  596. if (!PathIsDotOrDotDot(pszPath))
  597. {
  598. const bool bIsDir = 0 != (FILE_ATTRIBUTE_DIRECTORY & fd.dwFileAttributes);
  599. PathCombine(pszPathToPrint, pszPath, fd.cFileName);
  600. if (bIsDir)
  601. {
  602. lstrcat(pszPathToPrint, TEXT(" [DIR]"));
  603. }
  604. PrintOneEnumEntry(pszPathToPrint, dwStatus, dwPinCount, dwHintFlags);
  605. if (bIsDir)
  606. {
  607. PathAppend(pszPath, fd.cFileName);
  608. EnumTree(pszPath, pszPathToPrint);
  609. }
  610. }
  611. }
  612. while(CacheFindNext(hFind, &fd, &dwStatus, &dwPinCount, &dwHintFlags, NULL));
  613. }
  614. PathRemoveFileSpec(pszPath);
  615. }
  616. void EnumFiles(void)
  617. {
  618. WIN32_FIND_DATA fd;
  619. DWORD dwStatus, dwPinCount, dwHintFlags;
  620. _tprintf(TEXT("Status PinCnt Hints Name\n"));
  621. CCscFindHandle hFind(CacheFindFirst(NULL, &fd, &dwStatus, &dwPinCount, &dwHintFlags, NULL));
  622. if (hFind.IsValid())
  623. {
  624. do
  625. {
  626. //
  627. // We create only one path and print-path buffer that we pass
  628. // into the recursive EnumTree() function. This way we don't have
  629. // a path buffer on each call stack as we recurse.
  630. //
  631. TCHAR szPath[MAX_PATH * 2]; // Working path buffer.
  632. TCHAR szPathToPrint[MAX_PATH * 2]; // For printing only.
  633. wsprintf(szPathToPrint, TEXT("%s [SHARE]"), fd.cFileName);
  634. PrintOneEnumEntry(szPathToPrint, dwStatus, dwPinCount, dwHintFlags);
  635. lstrcpyn(szPath, fd.cFileName, ARRAYSIZE(szPath));
  636. EnumTree(szPath, szPathToPrint);
  637. }
  638. while(CacheFindNext(hFind, &fd, &dwStatus, &dwPinCount, &dwHintFlags, NULL));
  639. }
  640. _tprintf(TEXT("\n\n"));
  641. }
  642. void ShowUsage(void)
  643. {
  644. _tprintf(TEXT("\aUsage: cscsniff [-f] [-c] [-r] [-e] [-a]\n\n"));
  645. _tprintf(TEXT("\t-f = Show file information.\n"));
  646. _tprintf(TEXT("\t-c = Show cache information.\n"));
  647. _tprintf(TEXT("\t-r = Show registry information.\n"));
  648. _tprintf(TEXT("\t-e = Enumerate all files.\n"));
  649. _tprintf(TEXT("\t-a = Show ALL output.\n\n"));
  650. _tprintf(TEXT("Default is -f -c -r\n"));
  651. }
  652. void __cdecl main(int argc, char **argv)
  653. {
  654. // if (!IsCurrentUserAnAdminMember())
  655. // {
  656. // _tprintf(TEXT("\aYou must be an administrator on this computer to run cscsniff.\n"));
  657. // return;
  658. // }
  659. const char chDash = '-';
  660. const char chSlash = '/';
  661. const DWORD SHOW_CACHEINFO = 0x00000001;
  662. const DWORD SHOW_REGINFO = 0x00000002;
  663. const DWORD SHOW_FILEINFO = 0x00000004;
  664. const DWORD SHOW_ENUMFILES = 0x00000008;
  665. const DWORD SHOW_DEFAULT = SHOW_CACHEINFO | SHOW_REGINFO | SHOW_FILEINFO;
  666. const DWORD SHOW_ALL = SHOW_DEFAULT | SHOW_ENUMFILES;
  667. DWORD dwShow = 0;
  668. for (int i = 1; i < argc; i++)
  669. {
  670. if (chDash == argv[i][0] || chSlash == argv[i][0])
  671. {
  672. switch(argv[i][1])
  673. {
  674. case 'C':
  675. case 'c':
  676. dwShow |= SHOW_CACHEINFO;
  677. break;
  678. case 'R':
  679. case 'r':
  680. dwShow |= SHOW_REGINFO;
  681. break;
  682. case 'F':
  683. case 'f':
  684. dwShow |= SHOW_FILEINFO;
  685. break;
  686. case 'E':
  687. case 'e':
  688. dwShow |= SHOW_ENUMFILES;
  689. break;
  690. case 'A':
  691. case 'a':
  692. dwShow |= SHOW_ALL;
  693. break;
  694. default:
  695. ShowUsage();
  696. return;
  697. }
  698. }
  699. }
  700. if (0 == dwShow)
  701. {
  702. dwShow = SHOW_DEFAULT;
  703. }
  704. TCHAR szScratch[MAX_PATH];
  705. TCHAR szComputer[MAX_COMPUTERNAME_LENGTH + 1];
  706. TCHAR szDateTime[80];
  707. _tprintf(TEXT("Status of CSC for %s (%s)\n\n"),
  708. GetMachineName(szComputer, ARRAYSIZE(szComputer)),
  709. GetCurrentDateTime(szDateTime, ARRAYSIZE(szDateTime)));
  710. _tprintf(TEXT("Operating system: %s\n\n"), GetOsVersionInfoText(szScratch));
  711. if (dwShow & SHOW_FILEINFO)
  712. {
  713. _tprintf(TEXT("Binary file information:\n\n"));
  714. DumpFileInformation(TEXT("%systemroot%\\system32\\CSCDLL.DLL"));
  715. DumpFileInformation(TEXT("%systemroot%\\system32\\CSCUI.DLL"));
  716. }
  717. if (dwShow & SHOW_CACHEINFO)
  718. {
  719. DumpCacheStats();
  720. PrintShareStatusFlags();
  721. }
  722. if (dwShow & SHOW_ENUMFILES)
  723. {
  724. EnumFiles();
  725. PrintFileStatusFlags();
  726. PrintHintFlags();
  727. }
  728. if (dwShow & SHOW_REGINFO)
  729. DumpRegStats();
  730. }