Leaked source code of windows server 2003
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.

857 lines
30 KiB

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