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.

557 lines
14 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. winidle.c
  5. Abstract:
  6. This module builds a gui test program for the idle detection which
  7. pops up a window and uses CPU to simulate a running idle task when
  8. the system becomes idle.
  9. The test programs are built from the same sources as the original. This
  10. allows the test program to override parts of the original program to run
  11. it in a managed environment, and be able to test individual functions.
  12. The quality of the code for the test programs is as such.
  13. Author:
  14. Cenk Ergan (cenke)
  15. Environment:
  16. User Mode
  17. --*/
  18. #include <nt.h>
  19. #include <ntrtl.h>
  20. #include <nturtl.h>
  21. #include <windows.h>
  22. #include <wmium.h>
  23. #include <ntdddisk.h>
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include <time.h>
  27. #include "idlrpc.h"
  28. #include "idlecomn.h"
  29. //
  30. // This is mostly based on DavidFie's original IdleInfo application.
  31. //
  32. //
  33. // Note that this code is written for a test app, and is of that
  34. // quality.
  35. //
  36. DWORD
  37. RegisterIdleTask (
  38. IN IT_IDLE_TASK_ID IdleTaskId,
  39. OUT HANDLE *ItHandle,
  40. OUT HANDLE *StartEvent,
  41. OUT HANDLE *StopEvent
  42. );
  43. DWORD
  44. UnregisterIdleTask (
  45. IN HANDLE ItHandle,
  46. IN HANDLE StartEvent,
  47. IN HANDLE StopEvent
  48. );
  49. WCHAR *WinIdleUsage =
  50. L"Usage: winidle [options] \n"
  51. L"Options: \n"
  52. L" -wintimeout=x Sets how long notification window takes to go away. \n"
  53. L" -logtrace Will write a trace-log to c:\\idledbg.txt. \n"
  54. L" -stressparams Sets idle detection defaults for the above to small \n"
  55. L" values so you can make sure it is working. These can \n"
  56. L" still be overriden by setting the above parameters. \n"
  57. L"StressParams OVERRIDES: To be used only if -stressparams is specified \n"
  58. L" -period=x Sets idle detection period to x ms. \n"
  59. L" -vperiod=x Sets idle detection verification period to x ms. \n"
  60. L" -vnum=x Idle is verified over x verification periods. \n"
  61. L" -taskcheck=x Sets idle-task-running check to x ms. \n"
  62. L" -mincpu=x Sets min cpu percentage at which system can be idle. \n"
  63. L" -mindisk=x Sets min disk percentage at which system can be idle. \n"
  64. ;
  65. #define DBGPRNT(x) FileDbgPrintEx x
  66. FILE *WinIdleDbgFile = NULL;
  67. BOOLEAN WinIdleLogToFile = FALSE;
  68. ULONG
  69. _cdecl
  70. FileDbgPrintEx(
  71. IN PCH Format,
  72. ...
  73. )
  74. {
  75. va_list args;
  76. if (!WinIdleLogToFile) {
  77. return 0;
  78. }
  79. if (!WinIdleDbgFile) {
  80. char CurTime[20];
  81. char CurDate[20];
  82. WinIdleDbgFile = fopen("c:\\idledbg.txt", "a+");
  83. if (!WinIdleDbgFile) {
  84. return 0;
  85. }
  86. if (setvbuf(WinIdleDbgFile, NULL, _IONBF, 0)) {
  87. return 0;
  88. }
  89. _strtime(CurTime);
  90. _strdate(CurDate);
  91. fprintf(WinIdleDbgFile, ">>>>>> STARTING NEW LOG AT %s %s <<<<<<\n",
  92. CurTime, CurDate);
  93. }
  94. va_start(args, Format);
  95. vfprintf(WinIdleDbgFile, Format, args);
  96. va_end(args);
  97. return 0;
  98. }
  99. #define II_POPUP_WIDTH 300
  100. #define II_POPUP_HEIGHT 60
  101. #define II_APPNAME L"IdleInfo"
  102. #define II_MAINWINDOW_CLASSNAME L"IdleInfoMainClass"
  103. HINSTANCE IiInstance = NULL;
  104. HWND IiMainWindow = NULL;
  105. WCHAR *IiMessageStrings[] = {
  106. L"Running idle task.",
  107. L"No longer idle!",
  108. };
  109. #define II_MSG_RUNNING 0
  110. #define II_MSG_NOTIDLE 1
  111. ULONG IiCurrentMessageIdx = 0;
  112. LRESULT
  113. CALLBACK
  114. IiMainWndProc(
  115. HWND hWnd,
  116. UINT uMsg,
  117. WPARAM wParam,
  118. LPARAM lParam
  119. )
  120. {
  121. HDC hDc;
  122. PAINTSTRUCT Paint;
  123. RECT Rect;
  124. static HWND Button;
  125. static LONG CharHeight;
  126. switch (uMsg) {
  127. case WM_CLOSE:
  128. PostQuitMessage (0);
  129. return 0;
  130. case WM_PAINT:
  131. hDc = BeginPaint(hWnd, &Paint);
  132. GetClientRect(hWnd, &Rect);
  133. Rect.top += CharHeight / 2;
  134. DrawText(hDc,
  135. IiMessageStrings[IiCurrentMessageIdx],
  136. -1,
  137. &Rect,
  138. DT_SINGLELINE | DT_CENTER | DT_VCENTER);
  139. EndPaint(hWnd, &Paint);
  140. return 0;
  141. case WM_TIMER:
  142. ShowWindow(IiMainWindow, SW_HIDE);
  143. return 0;
  144. default:
  145. break;
  146. }
  147. return DefWindowProc(hWnd, uMsg, wParam, lParam);
  148. }
  149. HWND
  150. IiInit(
  151. HINSTANCE Instance
  152. )
  153. {
  154. DWORD ErrorCode;
  155. WNDCLASSEX WindowClass;
  156. LONG WindowHeight;
  157. WindowClass.cbSize = sizeof(WNDCLASSEX);
  158. WindowClass.style = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW;
  159. WindowClass.lpfnWndProc = IiMainWndProc;
  160. WindowClass.cbClsExtra = 0;
  161. WindowClass.cbWndExtra = 0;
  162. WindowClass.hInstance = Instance;
  163. WindowClass.hIcon = LoadIcon(NULL, IDI_INFORMATION);
  164. WindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  165. WindowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  166. WindowClass.lpszMenuName = NULL;
  167. WindowClass.lpszClassName = II_MAINWINDOW_CLASSNAME;
  168. WindowClass.hIconSm = LoadIcon(NULL, IDI_INFORMATION);
  169. if (!RegisterClassEx(&WindowClass)) {
  170. return NULL;
  171. }
  172. WindowHeight = II_POPUP_HEIGHT +
  173. GetSystemMetrics(SM_CYCAPTION) +
  174. GetSystemMetrics(SM_CYFIXEDFRAME) +
  175. GetSystemMetrics(SM_CYEDGE);
  176. return CreateWindowEx(
  177. WS_EX_TOPMOST | WS_EX_OVERLAPPEDWINDOW,
  178. II_MAINWINDOW_CLASSNAME,
  179. II_APPNAME,
  180. WS_SYSMENU,
  181. (GetSystemMetrics(SM_CXSCREEN) - II_POPUP_WIDTH) / 2,
  182. (GetSystemMetrics(SM_CYSCREEN) - WindowHeight) / 2,
  183. II_POPUP_WIDTH,
  184. WindowHeight,
  185. NULL,
  186. NULL,
  187. Instance,
  188. NULL);
  189. }
  190. DWORD
  191. RunIdleTask(
  192. HANDLE StopEvent,
  193. BOOLEAN *ShouldExitApp
  194. )
  195. {
  196. DWORD EndTime;
  197. DWORD ErrorCode;
  198. DWORD WaitResult;
  199. MSG Msg;
  200. //
  201. // Initialize locals.
  202. //
  203. *ShouldExitApp = FALSE;
  204. DBGPRNT(("WIN: RunIdleTask()\n"));
  205. while (TRUE) {
  206. WaitResult = MsgWaitForMultipleObjects (1,
  207. &StopEvent,
  208. FALSE,
  209. 0,
  210. QS_ALLEVENTS|QS_ALLINPUT);
  211. switch (WaitResult) {
  212. case WAIT_OBJECT_0:
  213. DBGPRNT(("WIN: RunIdleTask-StopEvent\n"));
  214. ErrorCode = ERROR_SUCCESS;
  215. goto cleanup;
  216. break;
  217. case WAIT_OBJECT_0 + 1:
  218. DBGPRNT(("WIN: RunIdleTask-WindowMessage\n"));
  219. if (PeekMessage (&Msg, NULL, 0, 0, PM_REMOVE)) {
  220. if (Msg.message == WM_QUIT) {
  221. *ShouldExitApp = TRUE;
  222. ErrorCode = ERROR_SUCCESS;
  223. goto cleanup;
  224. }
  225. TranslateMessage (&Msg);
  226. DispatchMessage (&Msg);
  227. }
  228. break;
  229. case WAIT_TIMEOUT:
  230. EndTime = GetTickCount() + 50;
  231. while (GetTickCount() < EndTime);
  232. break;
  233. default:
  234. ErrorCode = GetLastError();
  235. goto cleanup;
  236. }
  237. }
  238. ErrorCode = ERROR_SUCCESS;
  239. cleanup:
  240. DBGPRNT(("WIN: RunIdleTask()=%x\n",ErrorCode));
  241. return ErrorCode;
  242. }
  243. INT WINAPI WinMain(
  244. HINSTANCE Instance,
  245. HINSTANCE PreviousInstance,
  246. LPSTR CommandLine,
  247. INT ShowCommand)
  248. {
  249. DWORD ErrorCode;
  250. DWORD WaitResult;
  251. HANDLE StartEvent;
  252. HANDLE StopEvent;
  253. MSG Msg;
  254. IT_IDLE_DETECTION_PARAMETERS Parameters;
  255. BOOLEAN ShouldExitApp;
  256. PCHAR Argument;
  257. DWORD IdleWindowTimeout;
  258. BOOLEAN RegisteredIdleTask;
  259. DWORD NotIdleTimerId;
  260. IT_HANDLE ItHandle;
  261. //
  262. // Initialize locals.
  263. //
  264. RegisteredIdleTask = FALSE;
  265. IdleWindowTimeout = 3000; // 3 seconds.
  266. NotIdleTimerId = 1;
  267. //
  268. // Check for a running instance. If this is the first instance,
  269. // continue initialization.
  270. //
  271. if (PreviousInstance) {
  272. ErrorCode = ERROR_ALREADY_EXISTS;
  273. goto cleanup;
  274. }
  275. //
  276. // Turn on file logging if asked for.
  277. //
  278. if (Argument = strstr(CommandLine, "-logtrace")) {
  279. WinIdleLogToFile = TRUE;
  280. }
  281. IiInstance = Instance;
  282. IiMainWindow = IiInit(IiInstance);
  283. if (!IiMainWindow) {
  284. ErrorCode = ERROR_INVALID_FUNCTION;
  285. goto cleanup;
  286. }
  287. //
  288. // Check if we need to display help.
  289. //
  290. if (Argument = strstr(CommandLine, "?")) {
  291. MessageBox(IiMainWindow,
  292. WinIdleUsage,
  293. L"WinIdle - Idle Detection Test Program",
  294. MB_OK);
  295. ErrorCode = ERROR_SUCCESS;
  296. goto cleanup;
  297. }
  298. //
  299. // Idle notification window timeout.
  300. //
  301. if (Argument = strstr(CommandLine, "-wintimeout=")) {
  302. sscanf(Argument, "-wintimeout=%u", &IdleWindowTimeout);
  303. }
  304. //
  305. // Set defaults to stress values if asked for.
  306. //
  307. Parameters.MaxNumRegisteredTasks = 256;
  308. if (Argument = strstr(CommandLine, "-stressparams")) {
  309. Parameters.IdleDetectionPeriod = 1000;
  310. Parameters.IdleVerificationPeriod = 500;
  311. Parameters.NumVerifications = 2;
  312. Parameters.IdleInputCheckPeriod = 200;
  313. Parameters.IdleTaskRunningCheckPeriod = 1000;
  314. Parameters.MinCpuIdlePercentage = 90;
  315. Parameters.MinDiskIdlePercentage = 85;
  316. //
  317. // Update parameters from command line options.
  318. //
  319. if (Argument = strstr(CommandLine, "-period=")) {
  320. sscanf(Argument, "-period=%u", &Parameters.IdleDetectionPeriod);
  321. }
  322. if (Argument = strstr(CommandLine, "-vperiod=")) {
  323. sscanf(Argument, "-vperiod=%u", &Parameters.IdleVerificationPeriod);
  324. }
  325. if (Argument = strstr(CommandLine, "-vnum=")) {
  326. sscanf(Argument, "-vnum=%u", &Parameters.NumVerifications);
  327. }
  328. if (Argument = strstr(CommandLine, "-taskcheck=")) {
  329. sscanf(Argument, "-taskcheck=%u", &Parameters.IdleTaskRunningCheckPeriod);
  330. }
  331. if (Argument = strstr(CommandLine, "-mincpu=")) {
  332. sscanf(Argument, "-mincpu=%u", &Parameters.MinCpuIdlePercentage);
  333. }
  334. if (Argument = strstr(CommandLine, "-mindisk=")) {
  335. sscanf(Argument, "-mindisk=%u", &Parameters.MinDiskIdlePercentage);
  336. }
  337. //
  338. // Set the parameters on the server.
  339. //
  340. RpcTryExcept {
  341. ErrorCode = ItSrvSetDetectionParameters(NULL, &Parameters);
  342. }
  343. RpcExcept(IT_RPC_EXCEPTION_HANDLER()) {
  344. ErrorCode = RpcExceptionCode();
  345. }
  346. RpcEndExcept
  347. DBGPRNT(("WIN: WinMain-SetParameters()=%d\n",ErrorCode));
  348. if (ErrorCode != RPC_S_OK) {
  349. goto cleanup;
  350. }
  351. }
  352. //
  353. // Register idle task.
  354. //
  355. ErrorCode = RegisterIdleTask(ItOptimalDiskLayoutTaskId,
  356. &ItHandle,
  357. &StartEvent,
  358. &StopEvent);
  359. DBGPRNT(("WIN: WinMain-RegisterTask()=%d\n",ErrorCode));
  360. if (ErrorCode != ERROR_SUCCESS) {
  361. goto cleanup;
  362. }
  363. RegisteredIdleTask = TRUE;
  364. while (TRUE) {
  365. WaitResult = MsgWaitForMultipleObjects (1,
  366. &StartEvent,
  367. FALSE,
  368. INFINITE,
  369. QS_ALLEVENTS|QS_ALLINPUT);
  370. switch (WaitResult) {
  371. case WAIT_OBJECT_0:
  372. DBGPRNT(("WIN: WinMain-StartEvent\n"));
  373. KillTimer(IiMainWindow, NotIdleTimerId);
  374. IiCurrentMessageIdx = II_MSG_RUNNING;
  375. InvalidateRect(IiMainWindow, NULL, TRUE);
  376. ShowWindow(IiMainWindow, SW_SHOW);
  377. ErrorCode = RunIdleTask(StopEvent, &ShouldExitApp);
  378. if (ErrorCode != ERROR_SUCCESS) {
  379. goto cleanup;
  380. }
  381. if (ShouldExitApp) {
  382. goto cleanup;
  383. }
  384. IiCurrentMessageIdx = II_MSG_NOTIDLE;
  385. InvalidateRect(IiMainWindow, NULL, TRUE);
  386. SetTimer(IiMainWindow, NotIdleTimerId, IdleWindowTimeout, NULL);
  387. break;
  388. case WAIT_OBJECT_0 + 1:
  389. DBGPRNT(("WIN: WinMain-WindowMessage\n"));
  390. if (PeekMessage (&Msg, NULL, 0, 0, PM_REMOVE)) {
  391. if (Msg.message == WM_QUIT) {
  392. ErrorCode = ERROR_SUCCESS;
  393. goto cleanup;
  394. }
  395. TranslateMessage (&Msg);
  396. DispatchMessage (&Msg);
  397. }
  398. break;
  399. default:
  400. ErrorCode = GetLastError();
  401. goto cleanup;
  402. }
  403. }
  404. ErrorCode = ERROR_SUCCESS;
  405. cleanup:
  406. if (RegisteredIdleTask) {
  407. UnregisterIdleTask(ItHandle,
  408. StartEvent,
  409. StopEvent);
  410. }
  411. DBGPRNT(("WIN: WinMain()=%d\n",ErrorCode));
  412. return ErrorCode;
  413. }
  414. /*********************************************************************/
  415. /* MIDL allocate and free */
  416. /*********************************************************************/
  417. void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
  418. {
  419. return(HeapAlloc(GetProcessHeap(),0,(len)));
  420. }
  421. void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
  422. {
  423. HeapFree(GetProcessHeap(),0,(ptr));
  424. }