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.

452 lines
13 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. ntfrsutl.c
  5. Abstract:
  6. This is a utility program to help debug File Replication Service.
  7. It dumps the internal tables, thread and memory information. It runs
  8. on local as well as remote server. It uses RPC to communicate with the
  9. service.
  10. Author:
  11. Sudarshan Chitre 12-Aug-1999
  12. Environment
  13. User mode, winnt32
  14. --*/
  15. #include <ntreppch.h>
  16. #pragma hdrstop
  17. #include <frs.h>
  18. #include <ntfrsapi.h>
  19. VOID
  20. Win32ToMsg (
  21. IN PWCHAR Prefix,
  22. IN DWORD WindowsErrorCode
  23. )
  24. /*++
  25. Routine Description:
  26. Translate a error code into a error message using FormatMessage()
  27. and print to stderr. If no message is available, the error code
  28. is printed in decimal and hex.
  29. Arguments:
  30. Prefix - prefix to error message
  31. WStatus - Standard win32 error code.
  32. Return Value:
  33. None.
  34. --*/
  35. {
  36. DWORD NumChar;
  37. PWCHAR Buffer;
  38. //
  39. // Use the system formatter for standard error codes
  40. //
  41. NumChar = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  42. NULL,
  43. WindowsErrorCode,
  44. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  45. (LPTSTR) &Buffer,
  46. 0,
  47. NULL
  48. );
  49. if (NumChar) {
  50. fprintf(stderr, "%ws %ws\n", Prefix, Buffer);
  51. } else {
  52. fprintf(stderr, "%ws Status %d (0x%08x)\n", Prefix, WindowsErrorCode, WindowsErrorCode);
  53. }
  54. LocalFree( Buffer );
  55. }
  56. VOID
  57. Usage(
  58. IN DWORD ExitStatus
  59. )
  60. /*++
  61. Routine Description:
  62. Print usage and exit
  63. Arguments:
  64. ExitStatus - exits with this status
  65. Return Value:
  66. Exit(ExitStatus)
  67. --*/
  68. {
  69. printf("Ntfrsutl dumps the internal tables, thread and memory information\n");
  70. printf("for the ntfrs service.It runs against local as well as remote server.\n\n");
  71. printf("Note : To access the internal information, the logged in user should\n");
  72. printf(" have the required access on the following registry keys on the\n");
  73. printf(" target server.\n\n");
  74. printf(" HKLM\\System\\CCS\\Services\\Ntfrs\\Parameters\\Access Checks\\\n");
  75. printf(" Get Internal Information : Full control\n");
  76. printf(" Get Ds Polling Interval : Read\n");
  77. printf(" Set Ds Polling Interval : Full Control\n\n");
  78. printf("ntfrsutl [idtable | configtable | inlog | outlog] [computer]\n");
  79. printf("\t = enumerate the service's idtable/configtable/inlog/outlog \n");
  80. printf("\tcomputer = talk to the NtFrs service on this machine.\n");
  81. printf("\n");
  82. printf("ntfrsutl [memory|threads|stage] [computer]\n");
  83. printf("\t = list the service's memory usage\n");
  84. printf("\tcomputer = talk to the NtFrs service on this machine.\n");
  85. printf("\n");
  86. printf("ntfrsutl ds [computer]\n");
  87. printf("\t = list the service's view of the DS\n");
  88. printf("\tcomputer = talk to the NtFrs service on this machine.\n");
  89. printf("\n");
  90. printf("ntfrsutl sets [computer]\n");
  91. printf("\t = list the active replica sets\n");
  92. printf("\tcomputer = talk to the NtFrs service on this machine.\n");
  93. printf("\n");
  94. printf("ntfrsutl version [computer]\n");
  95. printf("\t = list the api and service versions\n");
  96. printf("\tcomputer = talk to the NtFrs service on this machine.\n");
  97. printf("\n");
  98. printf("ntfrsutl poll [/quickly[=[N]]] [/slowly[=[N]]] [/now] [computer]\n");
  99. printf("\t = list the current polling intervals.\n");
  100. printf("\tnow = Poll now.\n");
  101. printf("\tquickly = Poll quickly until stable configuration retrieved.\n");
  102. printf("\tquickly= = Poll quickly every default minutes.\n");
  103. printf("\tquickly=N = Poll quickly every N minutes.\n");
  104. printf("\tslowly = Poll slowly until stable configuration retrieved.\n");
  105. printf("\tslowly= = Poll slowly every default minutes.\n");
  106. printf("\tslowly=N = Poll slowly every N minutes.\n");
  107. printf("\tcomputer = talk to the NtFrs service on this machine.\n");
  108. printf("\n");
  109. exit(ExitStatus);
  110. }
  111. PWCHAR *
  112. ConvertArgv(
  113. DWORD argc,
  114. PCHAR *argv
  115. )
  116. /*++
  117. Routine Description:
  118. Convert short char argv into wide char argv
  119. Arguments:
  120. argc - From main
  121. argv - From main
  122. Return Value:
  123. Address of the new argv
  124. --*/
  125. {
  126. PWCHAR *wideargv;
  127. wideargv = LocalAlloc(LMEM_FIXED, (argc + 1) * sizeof(PWCHAR));
  128. if (wideargv == NULL) {
  129. fprintf(stderr, "Can't get memory; Win32 Status %d\n",
  130. GetLastError());
  131. exit(1);
  132. }
  133. wideargv[argc] = NULL;
  134. while (argc-- >= 1) {
  135. wideargv[argc] = LocalAlloc(LMEM_FIXED,
  136. (strlen(argv[argc]) + 1) * sizeof(WCHAR));
  137. if (wideargv[argc] == NULL) {
  138. fprintf(stderr, "Can't get memory; Win32 Status %d\n",
  139. GetLastError());
  140. exit(1);
  141. }
  142. wsprintf(wideargv[argc], L"%hs", argv[argc]);
  143. FRS_WCSLWR(wideargv[argc]);
  144. }
  145. return wideargv;
  146. }
  147. VOID
  148. ProcessPoll(
  149. IN DWORD argc,
  150. IN PWCHAR *Argv
  151. )
  152. /*++
  153. Routine Description:
  154. Process the command line for the subcommand poll.
  155. Arguments:
  156. argc
  157. Argv
  158. Return Value:
  159. Exits with 0 if everything went okay. Otherwise, 1.
  160. --*/
  161. {
  162. DWORD WStatus;
  163. DWORD i;
  164. ULONG LongInterval;
  165. ULONG ShortInterval;
  166. ULONG UseShortInterval;
  167. ULONG Interval;
  168. DWORD ComputerLen;
  169. PWCHAR ComputerName;
  170. BOOL SetInterval;
  171. //
  172. // Initialize the input parameters
  173. //
  174. LongInterval = 0;
  175. ShortInterval = 0;
  176. UseShortInterval = 0;
  177. ComputerName = NULL;
  178. SetInterval = FALSE;
  179. for (i = 2; i < argc; ++i) {
  180. //
  181. // Process options for poll
  182. //
  183. //
  184. // Not a parameter; must be the computer name
  185. //
  186. if (*Argv[i] != L'/' && *Argv[i] != L'-') {
  187. if (ComputerName) {
  188. fprintf(stderr, "Multiple computer names are not allowed\n");
  189. Usage(1);
  190. }
  191. ComputerName = Argv[i];
  192. //
  193. // /?
  194. //
  195. } else if (wcsstr(Argv[i] + 1, L"?") == Argv[i] + 1) {
  196. Usage(0);
  197. //
  198. // /quickly
  199. //
  200. } else if (!_wcsnicmp(Argv[i], L"/quickly", 8)) {
  201. SetInterval = TRUE;
  202. UseShortInterval = 1;
  203. if (*(Argv[i] + 8) != L'\0') {
  204. if (*(Argv[i] + 8) != L'=') {
  205. fprintf(stderr, "Don't understand %ws\n", Argv[i]);
  206. Usage(1);
  207. }
  208. if (*(Argv[i] + 9) == L'\0') {
  209. ShortInterval = NTFRSAPI_DEFAULT_SHORT_INTERVAL;
  210. } else {
  211. ShortInterval = wcstoul(Argv[i] + 9, NULL, 10);
  212. }
  213. if (ShortInterval < NTFRSAPI_MIN_INTERVAL ||
  214. ShortInterval > NTFRSAPI_MAX_INTERVAL) {
  215. fprintf(stderr, "Interval must be between %d and %d\n",
  216. NTFRSAPI_MIN_INTERVAL, NTFRSAPI_MAX_INTERVAL);
  217. Usage(1);
  218. }
  219. }
  220. //
  221. // /slowly
  222. //
  223. } else if (!_wcsnicmp(Argv[i], L"/slowly", 7)) {
  224. SetInterval = TRUE;
  225. if (*(Argv[i] + 7) != L'\0') {
  226. if (*(Argv[i] + 7) != L'=') {
  227. fprintf(stderr, "Don't understand %ws\n", Argv[i]);
  228. Usage(1);
  229. }
  230. if (*(Argv[i] + 8) == L'\0') {
  231. LongInterval = NTFRSAPI_DEFAULT_LONG_INTERVAL;
  232. } else {
  233. LongInterval = wcstoul(Argv[i] + 8, NULL, 10);
  234. }
  235. if (LongInterval < NTFRSAPI_MIN_INTERVAL ||
  236. LongInterval > NTFRSAPI_MAX_INTERVAL) {
  237. fprintf(stderr, "Interval must be between %d and %d\n",
  238. NTFRSAPI_MIN_INTERVAL, NTFRSAPI_MAX_INTERVAL);
  239. Usage(1);
  240. }
  241. }
  242. //
  243. // /now
  244. //
  245. } else if (!_wcsnicmp(Argv[i], L"/now", 4)) {
  246. SetInterval = TRUE;
  247. if (*(Argv[i] + 4) != L'\0') {
  248. fprintf(stderr, "Don't understand %ws\n", Argv[i]);
  249. Usage(1);
  250. }
  251. //
  252. // Don't understand
  253. //
  254. } else {
  255. fprintf(stderr, "Don't understand %ws\n", Argv[i]);
  256. Usage(1);
  257. }
  258. }
  259. if (SetInterval) {
  260. //
  261. // Set the interval and initiate a new polling cycle
  262. //
  263. WStatus = NtFrsApi_Set_DsPollingIntervalW(ComputerName,
  264. UseShortInterval,
  265. LongInterval,
  266. ShortInterval);
  267. if (!WIN_SUCCESS(WStatus)) {
  268. Win32ToMsg(L"Can't set interval:", WStatus);
  269. exit(1);
  270. }
  271. } else {
  272. //
  273. // Get the current polling cycles
  274. //
  275. WStatus = NtFrsApi_Get_DsPollingIntervalW(ComputerName,
  276. &Interval,
  277. &LongInterval,
  278. &ShortInterval);
  279. if (!WIN_SUCCESS(WStatus)) {
  280. Win32ToMsg(L"Can't get intervals:", WStatus);
  281. exit(1);
  282. }
  283. printf("Current Interval: %6d minutes\n", Interval);
  284. printf("Short Interval : %6d minutes\n", ShortInterval);
  285. printf("Long Interval : %6d minutes\n", LongInterval);
  286. }
  287. exit(0);
  288. }
  289. VOID
  290. ProcessDump(
  291. IN DWORD argc,
  292. IN PWCHAR *Argv,
  293. IN DWORD TypeOfInformation
  294. )
  295. /*++
  296. Routine Description:
  297. Dump bunches of stuff
  298. Arguments:
  299. argc
  300. Argv
  301. TypeOfInformation
  302. Return Value:
  303. Exits with 0 if everything went okay. Otherwise, 1.
  304. --*/
  305. {
  306. DWORD WStatus;
  307. PCHAR Line;
  308. BOOL FirstTime = TRUE;
  309. PVOID Info = NULL;
  310. PWCHAR ComputerName = NULL;
  311. if (argc > 2) {
  312. ComputerName = Argv[2];
  313. }
  314. do {
  315. WStatus = NtFrsApi_InfoW(ComputerName,
  316. TypeOfInformation,
  317. 0,
  318. &Info);
  319. if (!WIN_SUCCESS(WStatus)) {
  320. fprintf(stderr, "ERROR NtFrsApi_InfoW() Error %d\n", WStatus);
  321. NtFrsApi_InfoFreeW(&Info);
  322. exit(1);
  323. }
  324. if (Info) {
  325. if (!FirstTime) {
  326. printf("===== THE FOLLOWING INFO MAY BE INCONSISTENT DUE TO REFETCH =====\n");
  327. }
  328. FirstTime = FALSE;
  329. Line = NULL;
  330. do {
  331. WStatus = NtFrsApi_InfoLineW(Info, &Line);
  332. if (!WIN_SUCCESS(WStatus)) {
  333. fprintf(stderr, "ERROR NtFrsApi_InfoLineW() Error %d\n", WStatus);
  334. NtFrsApi_InfoFreeW(&Info);
  335. exit(1);
  336. }
  337. if (Line) {
  338. printf("%s", Line);
  339. }
  340. } while (Line);
  341. }
  342. } while (Info);
  343. exit(0);
  344. }
  345. VOID _cdecl
  346. main(
  347. IN DWORD argc,
  348. IN PCHAR *argv
  349. )
  350. /*++
  351. Routine Description:
  352. Process the command line.
  353. Arguments:
  354. argc
  355. argv
  356. Return Value:
  357. Exits with 0 if everything went okay. Otherwise, 1.
  358. --*/
  359. {
  360. PWCHAR *Argv;
  361. //
  362. // Print usage and exit
  363. //
  364. if (argc == 1) {
  365. Usage(0);
  366. }
  367. //
  368. // Use wide char parameters
  369. //
  370. Argv = ConvertArgv(argc, argv);
  371. //
  372. // Find the subcommand
  373. //
  374. if (!wcscmp(Argv[1], L"poll")) {
  375. ProcessPoll(argc, Argv);
  376. } else if (!_wcsicmp(Argv[1], L"version")) {
  377. ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_VERSION);
  378. } else if (!_wcsicmp(Argv[1], L"sets")) {
  379. ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_SETS);
  380. } else if (!_wcsicmp(Argv[1], L"ds")) {
  381. ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_DS);
  382. } else if (!_wcsicmp(Argv[1], L"memory")) {
  383. ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_MEMORY);
  384. } else if (!_wcsicmp(Argv[1], L"idtable")) {
  385. ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_IDTABLE);
  386. } else if (!_wcsicmp(Argv[1], L"configtable")) {
  387. ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_CONFIGTABLE);
  388. } else if (!_wcsicmp(Argv[1], L"inlog")) {
  389. ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_INLOG);
  390. } else if (!_wcsicmp(Argv[1], L"outlog")) {
  391. ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_OUTLOG);
  392. } else if (!_wcsicmp(Argv[1], L"threads")) {
  393. ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_THREADS);
  394. } else if (!_wcsicmp(Argv[1], L"stage")) {
  395. ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_STAGE);
  396. } else if (!_wcsicmp(Argv[1], L"/?")) {
  397. Usage(0);
  398. } else {
  399. fprintf(stderr, "Don't understand %ws\n", Argv[1]);
  400. }
  401. exit(0);
  402. }