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.

385 lines
10 KiB

  1. //Copyright (c) 1998 - 1999 Microsoft Corporation
  2. /* Get the standard C includes */
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <process.h>
  7. #include <dos.h>
  8. #include <errno.h>
  9. #define FALSE 0
  10. #define TRUE 1
  11. #define STARTMON "StartMonitor"
  12. /*=============================================================================
  13. == External Functions Used
  14. =============================================================================*/
  15. int OptionsParse( int, char * [] );
  16. /*=============================================================================
  17. == Local Functions Used
  18. =============================================================================*/
  19. char GetCommandLine(char *);
  20. /*=============================================================================
  21. == Global data
  22. =============================================================================*/
  23. char bQ = FALSE;
  24. char bDefaults = FALSE;
  25. char bStartMonitor = FALSE;
  26. char bStopMonitor = FALSE;
  27. int dDetectProbationCount = -1;
  28. int dInProbationCount = -1;
  29. int dmsAllowed = -1;
  30. int dmsSleep = -1;
  31. int dBusymsAllowed = -1;
  32. int dmsProbationTrial = -1;
  33. int dmsGoodProbationEnd = -1;
  34. int dDetectionInterval = -1;
  35. typedef struct _DOSKBDIDLEKNOBS
  36. {
  37. short int DetectProbationCount;
  38. short int InProbationCount;
  39. short int BusymsAllowed;
  40. short int msAllowed;
  41. short int msGoodProbationEnd;
  42. short int msProbationTrial;
  43. short int msSleep;
  44. short int msInSystemTick;
  45. short int DetectionInterval;
  46. } DOSKBDIDLEKNOBS, *PDOSKBDIDLEKNOBS;
  47. typedef union {
  48. unsigned long longword;
  49. struct {
  50. unsigned short usloword;
  51. unsigned short ushiword;
  52. } words;
  53. } LONGTYPE;
  54. /*******************************************************************************
  55. *
  56. * main
  57. *
  58. * ENTRY:
  59. * argc (input)
  60. * number of arguments
  61. * argv (input)
  62. * pointer to arguments
  63. *
  64. * EXIT:
  65. *
  66. ******************************************************************************/
  67. void
  68. main( int argc, char * argv[] )
  69. {
  70. LONGTYPE totalticks;
  71. LONGTYPE totalpolls;
  72. unsigned short usminpolls;
  73. unsigned short usmaxpolls;
  74. int rc;
  75. char bExec = FALSE;
  76. DOSKBDIDLEKNOBS data = {-1,-1,-1,-1,-1,-1,-1,-1,-1};
  77. //get command line options into global variables
  78. if (OptionsParse( argc, argv )) return; //non zero return code is failure
  79. //if /Defaults then we do a special bop to reset everything
  80. //and then we continue as a display information only
  81. //dont worry about optimizing for the /q case
  82. if (bDefaults) {
  83. _asm {
  84. push ax
  85. mov al,3 ;for the set registry defaults subparm
  86. mov ah,254 ;for the main pop parm
  87. mov BYTE PTR cs:crap,0c4h
  88. mov BYTE PTR cs:crap+1,0c4H
  89. mov BYTE PTR cs:crap+2,16H
  90. ;we need to flush the prefetch buffer for self modifying code
  91. ;asm in c will not allow db directive
  92. jmp short crap
  93. crap:
  94. nop
  95. nop
  96. nop
  97. ; db 0c4H;,0c4H,16H ;the bop
  98. pop ax
  99. }
  100. }
  101. _asm {
  102. push ax
  103. push bx
  104. push cx
  105. push dx
  106. mov al,0 ;for first BOP
  107. mov ah,254 ;for first BOP
  108. mov bx,WORD PTR dDetectProbationCount
  109. mov cx,WORD PTR dInProbationCount
  110. mov BYTE PTR cs:crap1,0c4h
  111. mov BYTE PTR cs:crap1+1,0c4H
  112. mov BYTE PTR cs:crap1+2,16H
  113. ;we need to flush the prefetch buffer for self modifying code
  114. ;asm in c will not allow db directive
  115. jmp short crap1
  116. crap1:
  117. nop
  118. nop
  119. nop
  120. ; db 0c4H;,0c4H,16H ;the bop
  121. mov WORD PTR data.DetectProbationCount,bx
  122. mov WORD PTR data.InProbationCount,cx
  123. mov WORD PTR data.msInSystemTick,dx
  124. mov al,1 ;for second BOP
  125. mov ah,254 ;for second BOP
  126. mov bx,WORD PTR dBusymsAllowed
  127. mov cx,WORD PTR dmsAllowed
  128. mov dx,WORD PTR dmsSleep
  129. mov BYTE PTR cs:crap2,0c4h
  130. mov BYTE PTR cs:crap2+1,0c4H
  131. mov BYTE PTR cs:crap2+2,16H
  132. ;we need to flush the prefetch buffer for self modifying code
  133. ;asm in c will not allow db directive
  134. jmp short crap2
  135. crap2:
  136. nop
  137. nop
  138. nop
  139. ; db 0c4H;,0c4H,16H ;the BOP
  140. mov WORD PTR data.BusymsAllowed,bx
  141. mov WORD PTR data.msAllowed,cx
  142. mov WORD PTR data.msSleep,dx
  143. mov al,2
  144. mov ah,254
  145. mov bx,WORD PTR dmsGoodProbationEnd
  146. mov cx,WORD PTR dmsProbationTrial
  147. mov dx,WORD PTR dDetectionInterval
  148. mov BYTE PTR cs:crap3,0c4h
  149. mov BYTE PTR cs:crap3+1,0c4H
  150. mov BYTE PTR cs:crap3+2,16H
  151. ;we need to flush the prefetch buffer for self modifying code
  152. ;asm in c will not allow db directive
  153. jmp short crap3
  154. crap3:
  155. nop
  156. nop
  157. nop
  158. ; db 0c4H;,0c4H,16H
  159. mov WORD PTR data.msGoodProbationEnd,bx
  160. mov WORD PTR data.msProbationTrial,cx
  161. mov WORD PTR data.DetectionInterval,dx
  162. pop dx
  163. pop cx
  164. pop bx
  165. pop ax
  166. }
  167. // Turn on keyboard monitoring
  168. if (bStartMonitor) {
  169. _asm {
  170. mov al,4
  171. mov ah,254
  172. mov BYTE PTR cs:crap4,0c4h
  173. mov BYTE PTR cs:crap4+1,0c4H
  174. mov BYTE PTR cs:crap4+2,16H
  175. ;we need to flush the prefetch buffer for self modifying code
  176. ;asm in c will not allow db directive
  177. jmp short crap4
  178. crap4:
  179. nop
  180. nop
  181. nop
  182. ; db 0c4H;,0c4H,16H
  183. }
  184. // If they specified the name of the app, try to exec it
  185. if (argc > 2) {
  186. char *pch = NULL;
  187. char bBatFile = FALSE;
  188. // If this is a batch file, pass to command processor
  189. if ((pch = strrchr(argv[2],'.')) && !stricmp(pch, ".bat")) {
  190. bBatFile = TRUE;
  191. } else {
  192. rc = spawnvp(P_WAIT, argv[2], &argv[2]);
  193. }
  194. bExec = TRUE;
  195. if ((rc == -1) || bBatFile) {
  196. // maybe they tried to run a batch file, so look for xxx.bat
  197. if ((errno == ENOENT) || (bBatFile)) {
  198. char pcmdline[256];
  199. if (GetCommandLine(pcmdline)) {
  200. rc = system(pcmdline);
  201. }
  202. }
  203. }
  204. }
  205. }
  206. if (bStopMonitor || bExec) {
  207. _asm {
  208. push di
  209. push si
  210. mov al,5
  211. mov ah,254
  212. mov BYTE PTR cs:crap5,0c4h
  213. mov BYTE PTR cs:crap5+1,0c4H
  214. mov BYTE PTR cs:crap5+2,16H
  215. ;we need to flush the prefetch buffer for self modifying code
  216. ;asm in c will not allow db directive
  217. jmp short crap5
  218. crap5:
  219. nop
  220. nop
  221. nop
  222. ; db 0c4H;,0c4H,16H
  223. mov totalticks.words.usloword, ax ; get the polling data
  224. mov totalticks.words.ushiword, bx ; get the polling data
  225. mov totalpolls.words.usloword, cx
  226. mov totalpolls.words.ushiword, dx
  227. mov usmaxpolls, si
  228. mov usminpolls, di
  229. pop si
  230. pop di
  231. }
  232. // If they entered /stopmonitor or the app exited while monitoring,
  233. // display the statistics
  234. if (!bExec || (bExec && (rc != -1))) {
  235. double avg;
  236. printf("\nTotal polls: %lu\n", totalpolls.longword);
  237. printf("Total ticks: %lu\n", totalticks.longword);
  238. avg = (double)(totalpolls.longword)/(double)(totalticks.longword);
  239. printf("Avg. polls/tick: %.1f\n", avg);
  240. printf("Minimum polls per detection interval: %u\n", usminpolls);
  241. printf("Maximum polls per detection interval: %u\n", usmaxpolls);
  242. printf("Number of milliseconds in a system timer tick is %hd\n",
  243. data.msInSystemTick);
  244. printf("DetectionInterval = %hd tick(s) (%hd msec)\n",
  245. data.DetectionInterval,
  246. data.DetectionInterval*data.msInSystemTick);
  247. }
  248. }
  249. if (!bQ && !bStartMonitor && !bStopMonitor) {
  250. printf("Number of milliseconds in a system timer tick is %hd\n",
  251. data.msInSystemTick);
  252. printf("DetectionInterval = %hd tick(s) (%hd msec)\n",
  253. data.DetectionInterval,
  254. data.DetectionInterval*data.msInSystemTick);
  255. printf("DetectProbationCount= %hd\nInProbationCount= %hd\n",
  256. data.DetectProbationCount,data.InProbationCount);
  257. printf("msAllowed= %hd\nmsSleep= %hd\n",data.msAllowed,data.msSleep);
  258. printf("BusymsAllowed= %hd\nmsProbationTrial= %hd\n\
  259. msGoodProbationEnd= %hd\n",data.BusymsAllowed,
  260. data.msProbationTrial,data.msGoodProbationEnd);
  261. }
  262. }
  263. /*******************************************************************************
  264. *
  265. * GetCommandLine
  266. *
  267. * Return the command line following the /startmonitor switch.
  268. *
  269. * ENTRY:
  270. * char *pbuff: pointer to hold command line (returned)
  271. *
  272. * EXIT:
  273. * SUCCESS: returns TRUE
  274. * FAILURE: returns FALSE
  275. *
  276. ******************************************************************************/
  277. char GetCommandLine(char *pbuff)
  278. {
  279. char *pch, *pcmdline;
  280. char bfound = FALSE;
  281. // copy the command line from the PSP to a near buffer
  282. if (pcmdline = malloc(256)) {
  283. _asm {
  284. push ds
  285. push si
  286. push di
  287. mov ax, _psp
  288. mov ds, ax
  289. mov si, 80h
  290. mov di, pcmdline
  291. xor ax,ax
  292. lodsb
  293. mov cx,ax
  294. rep movsb
  295. xor ax,ax
  296. stosb
  297. pop di
  298. pop si
  299. pop ds
  300. }
  301. pch = pcmdline;
  302. while (pch && !bfound) {
  303. // Get next / or -
  304. pch = strchr(pch, '/');
  305. if (!pch) {
  306. pch = strchr(pch, '-');
  307. }
  308. // If we found a / or -, skip over it and check for startmonitor
  309. if (pch) {
  310. pch++;
  311. if (!strnicmp(pch, STARTMON, sizeof(STARTMON) - 1)) {
  312. pch += sizeof(STARTMON);
  313. bfound = TRUE;
  314. }
  315. }
  316. }
  317. // If we found /startmonitor, return the rest of the command line
  318. if (bfound) {
  319. strcpy(pbuff, pch);
  320. return(TRUE);
  321. }
  322. free(pcmdline);
  323. }
  324. return(FALSE);
  325. }