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.

1458 lines
44 KiB

  1. ///////////////////////////////////////////////////////////////////////////
  2. // File: WinHttpStressScheduler.cpp
  3. //
  4. // Copyright (c) 2001 Microsoft Corporation. All Rights Reserved.
  5. //
  6. // Purpose:
  7. // ServerCommands.cpp: implementation of the ServerCommands class.
  8. // This class is used to retrieve and act on command from the server.
  9. //
  10. // History:
  11. // 02/08/01 DennisCh Created
  12. //
  13. //////////////////////////////////////////////////////////////////////
  14. //////////////////////////////////////////////////////////////////////
  15. // Includes
  16. //////////////////////////////////////////////////////////////////////
  17. //
  18. // WIN32 headers
  19. //
  20. //
  21. // Project headers
  22. //
  23. #include "ServerCommands.h"
  24. #include "NetworkTools.h"
  25. //////////////////////////////////////////////////////////////////////
  26. // Globals and statics
  27. //////////////////////////////////////////////////////////////////////
  28. HANDLE g_hQueryServerForCommands; // Handle for the thread that queries the server for commands
  29. CRITICAL_SECTION g_csServerCommandsVars; // For protecting CommandServer private member vars. Used in the QueryServerForCommands_ThreadProc.
  30. extern ServerCommands g_objServerCommands; // Declared in WinHttpStressScheduler.cpp
  31. ////////////////////////////////////////////////////////////
  32. // Function: QueryServerForCommands_ThreadProc(LPVOID)
  33. //
  34. // Purpose:
  35. // This method sends a request to the command server for instructions
  36. // and saves them in the public vars of ServerCommands.
  37. //
  38. ////////////////////////////////////////////////////////////
  39. DWORD
  40. WINAPI
  41. QueryServerForCommands_ThreadProc(
  42. LPVOID lpParam // [IN] thread proc param
  43. )
  44. {
  45. BOOL bResult = TRUE;
  46. HINTERNET hRoot = NULL;
  47. HINTERNET hSession = NULL;
  48. HINTERNET hRequest = NULL;
  49. URL_COMPONENTSW urlComponents;
  50. // Allocate space for URL components
  51. ZeroMemory(&urlComponents, sizeof(urlComponents));
  52. urlComponents.dwSchemeLength = MAX_PATH;
  53. urlComponents.lpszScheme = new TCHAR[MAX_PATH];
  54. urlComponents.dwHostNameLength = MAX_PATH;
  55. urlComponents.lpszHostName = new TCHAR[MAX_PATH];
  56. urlComponents.dwUrlPathLength = MAX_PATH;
  57. urlComponents.lpszUrlPath = new TCHAR[MAX_PATH];
  58. urlComponents.dwExtraInfoLength = MAX_PATH;
  59. urlComponents.lpszExtraInfo = new TCHAR[MAX_PATH];
  60. urlComponents.dwUserNameLength = MAX_PATH;
  61. urlComponents.lpszUserName = new TCHAR[MAX_PATH];
  62. urlComponents.dwPasswordLength = MAX_PATH;
  63. urlComponents.lpszPassword = new TCHAR[MAX_PATH];
  64. urlComponents.nPort = 0;
  65. urlComponents.dwStructSize = sizeof(URL_COMPONENTSW);
  66. // crack the Command Server URL to be used later
  67. if (!WinHttpCrackUrl(
  68. g_objServerCommands.Get_CommandServerURL(),
  69. _tcslen(g_objServerCommands.Get_CommandServerURL()),
  70. ICU_ESCAPE,
  71. &urlComponents)
  72. )
  73. {
  74. bResult = FALSE;
  75. goto Exit;
  76. }
  77. hRoot = WinHttpOpen(
  78. STRESS_SCHEDULER_USER_AGENT,
  79. WINHTTP_ACCESS_TYPE_NO_PROXY,
  80. NULL,
  81. NULL,
  82. 0);
  83. if (!hRoot)
  84. {
  85. bResult = FALSE;
  86. goto Exit;
  87. }
  88. hSession = WinHttpConnect(
  89. hRoot,
  90. urlComponents.lpszHostName,
  91. // If the URL in urlComponents uses standard HTTP or HTTPS ports then use INTERNET_DEFAULT_PORT. Otherwise use the non-standard port gleaned from the URL.
  92. ((urlComponents.nPort == 80) || (urlComponents.nPort == 443)) ? INTERNET_DEFAULT_PORT : urlComponents.nPort,
  93. 0);
  94. if (!hSession)
  95. {
  96. bResult = FALSE;
  97. goto Exit;
  98. }
  99. // Build a full URL with path and querystring
  100. TCHAR szFullPath[MAX_PATH*2];
  101. ZeroMemory(szFullPath, sizeof(szFullPath));
  102. _tcsncpy(szFullPath, urlComponents.lpszUrlPath, urlComponents.dwUrlPathLength);
  103. //szFullPath[urlComponents.dwUrlPathLength] = _T('\0');
  104. _tcsncat(szFullPath, urlComponents.lpszExtraInfo, urlComponents.dwExtraInfoLength);
  105. hRequest = WinHttpOpenRequest(
  106. hSession,
  107. _T("POST"),
  108. szFullPath,
  109. NULL,
  110. NULL,
  111. NULL,
  112. // if the URL in urlComponents uses HTTPS then pass in WINHTTP_FLAG_SECURE to this param. Otherwise, 0.
  113. (0 == _tcsnicmp(urlComponents.lpszScheme, _T("https"), 5)) ? WINHTTP_FLAG_SECURE : 0);
  114. if (!hRequest)
  115. {
  116. bResult = FALSE;
  117. goto Exit;
  118. }
  119. // Set reasonable timeouts just in case
  120. if (!WinHttpSetTimeouts(hRequest, 5000, 5000, 5000, 5000))
  121. {
  122. bResult = FALSE;
  123. goto Exit;
  124. }
  125. // Get the computer name and send it in a POST request
  126. LPSTR szPost, szMachineName;
  127. szPost = new CHAR[MAX_PATH];
  128. szMachineName = new CHAR[MAX_PATH];
  129. GetEnvironmentVariableA("COMPUTERNAME", szMachineName, MAX_PATH);
  130. strcpy(szPost, FIELDNAME__USERINFO_MACHINENAME);
  131. strcat(szPost, szMachineName);
  132. bResult = WinHttpSendRequest(
  133. hRequest,
  134. _T("Content-Type: application/x-www-form-urlencoded"),
  135. -1L,
  136. szPost,
  137. strlen(szPost),
  138. strlen(szPost),
  139. 0);
  140. delete [] szPost;
  141. delete [] szMachineName;
  142. szPost = NULL;
  143. szMachineName = NULL;
  144. if (!WinHttpReceiveResponse(hRequest, NULL))
  145. {
  146. bResult = FALSE;
  147. goto Exit;
  148. }
  149. TCHAR szBuffer[MAX_URL];
  150. DWORD dwBufferSize, dwIndex;
  151. // get all command headers that we're interested in.
  152. // make sure there are no pending operations on member vars (pServerCommands->Set_* functions)
  153. EnterCriticalSection(&g_csServerCommandsVars);
  154. // *********************************
  155. // **** COMMANDHEADER__EXIT: Exit if header is present, else continue.
  156. dwIndex = 0;
  157. dwBufferSize = MAX_URL;
  158. ZeroMemory(szBuffer, sizeof(szBuffer));
  159. if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__EXIT, szBuffer, &dwBufferSize, &dwIndex))
  160. g_objServerCommands.Set_ExitStress(TRUE);
  161. else
  162. g_objServerCommands.Set_ExitStress(FALSE);
  163. // *********************************
  164. // **** COMMANDHEADER__WINHTTP_DLL_URL: valid values: Valid URL
  165. dwIndex = 0;
  166. dwBufferSize = MAX_URL;
  167. ZeroMemory(szBuffer, sizeof(szBuffer));
  168. if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__WINHTTP_DLL_URL, szBuffer, &dwBufferSize, &dwIndex))
  169. g_objServerCommands.Set_WinHttpDllURL(szBuffer, dwBufferSize);
  170. else
  171. bResult = FALSE;
  172. // *********************************
  173. // **** COMMANDHEADER__WINHTTP_PDB_URL: valid values: Valid URL
  174. dwIndex = 0;
  175. dwBufferSize = MAX_URL;
  176. ZeroMemory(szBuffer, sizeof(szBuffer));
  177. if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__WINHTTP_PDB_URL, szBuffer, &dwBufferSize, &dwIndex))
  178. g_objServerCommands.Set_WinHttpPDBURL(szBuffer, dwBufferSize);
  179. else
  180. bResult = FALSE;
  181. // *********************************
  182. // **** COMMANDHEADER__WINHTTP_SYM_URL: valid values: Valid URL
  183. dwIndex = 0;
  184. dwBufferSize = MAX_URL;
  185. ZeroMemory(szBuffer, sizeof(szBuffer));
  186. if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__WINHTTP_SYM_URL, szBuffer, &dwBufferSize, &dwIndex))
  187. g_objServerCommands.Set_WinHttpSYMURL(szBuffer, dwBufferSize);
  188. else
  189. bResult = FALSE;
  190. // *********************************
  191. // **** COMMANDHEADER__COMMANDSERVER_URL: valid values: Valid URL
  192. dwIndex = 0;
  193. dwBufferSize = MAX_URL;
  194. ZeroMemory(szBuffer, sizeof(szBuffer));
  195. if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__COMMANDSERVER_URL, szBuffer, &dwBufferSize, &dwIndex))
  196. g_objServerCommands.Set_CommandServerURL(szBuffer, dwBufferSize);
  197. else
  198. bResult = FALSE;
  199. // *********************************
  200. // **** COMMANDHEADER__BEGIN_TIME_HOUR: valid values: Valid string from 0-23
  201. dwIndex = 0;
  202. dwBufferSize = MAX_URL;
  203. ZeroMemory(szBuffer, sizeof(szBuffer));
  204. if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__BEGIN_TIME_HOUR, szBuffer, &dwBufferSize, &dwIndex))
  205. g_objServerCommands.Set_TimeStressBegins(szBuffer, NULL);
  206. else
  207. bResult = FALSE;
  208. // *********************************
  209. // **** COMMANDHEADER__BEGIN_TIME_MINUTE: valid values: Valid string from 0-59
  210. dwIndex = 0;
  211. dwBufferSize = MAX_URL;
  212. ZeroMemory(szBuffer, sizeof(szBuffer));
  213. if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__BEGIN_TIME_MINUTE, szBuffer, &dwBufferSize, &dwIndex))
  214. g_objServerCommands.Set_TimeStressBegins(NULL, szBuffer);
  215. else
  216. bResult = FALSE;
  217. // *********************************
  218. // **** COMMANDHEADER__END_TIME_HOUR: valid values: Valid string from 0-23
  219. dwIndex = 0;
  220. dwBufferSize = MAX_URL;
  221. ZeroMemory(szBuffer, sizeof(szBuffer));
  222. if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__END_TIME_HOUR, szBuffer, &dwBufferSize, &dwIndex))
  223. g_objServerCommands.Set_TimeStressEnds(szBuffer, NULL);
  224. else
  225. bResult = FALSE;
  226. // *********************************
  227. // **** COMMANDHEADER__END_TIME_MINUTE: valid values: Valid string from 0-59
  228. dwIndex = 0;
  229. dwBufferSize = MAX_URL;
  230. ZeroMemory(szBuffer, sizeof(szBuffer));
  231. if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__END_TIME_MINUTE, szBuffer, &dwBufferSize, &dwIndex))
  232. g_objServerCommands.Set_TimeStressEnds(NULL, szBuffer);
  233. else
  234. bResult = FALSE;
  235. // *********************************
  236. // **** COMMANDHEADER__RUN_FOREVER: valid values: doesn't matter. As long as header is present it gets sent
  237. dwIndex = 0;
  238. dwBufferSize = MAX_URL;
  239. ZeroMemory(szBuffer, sizeof(szBuffer));
  240. if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__RUN_FOREVER, szBuffer, &dwBufferSize, &dwIndex))
  241. g_objServerCommands.Set_RunForever(TRUE);
  242. else
  243. g_objServerCommands.Set_RunForever(FALSE);
  244. // *********************************
  245. // **** COMMANDHEADER__UPDATE_INTERVAL: valid values: Valid string in INTERNET_RFC1123 format
  246. DWORD dwTimeOut;
  247. dwTimeOut = 0;
  248. dwIndex = 0;
  249. dwBufferSize = sizeof(DWORD);
  250. ZeroMemory(szBuffer, sizeof(szBuffer));
  251. if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_NUMBER, COMMANDHEADER__UPDATE_INTERVAL, &dwTimeOut, &dwBufferSize, &dwIndex))
  252. g_objServerCommands.Set_CommandServerUpdateInterval(dwTimeOut);
  253. else
  254. bResult = FALSE;
  255. // *********************************
  256. // *********************************
  257. // **** Query commands for building stress Instance objects
  258. // ****
  259. // **** COMMANDHEADER__STRESS_EXE_URL: valid values: Valid URL
  260. DWORD dwStressExeID;
  261. DWORD dwPageHeapCommandIndex,
  262. dwUMDHCommandIndex,
  263. dwStressPDBIndex,
  264. dwStressSYMIndex,
  265. dwStressMemDmpPathIndex,
  266. dwStressExeIDIndex;
  267. LPTSTR szPageheapCommand,
  268. szUMDHCommand,
  269. szStressPDB_URL,
  270. szStressSYM_URL,
  271. szStressMemDmpPath,
  272. szStressExeID;
  273. szPageheapCommand = new TCHAR[MAX_PATH];
  274. szUMDHCommand = new TCHAR[MAX_PATH];
  275. szStressPDB_URL = new TCHAR[MAX_STRESS_URL];
  276. szStressSYM_URL = new TCHAR[MAX_STRESS_URL];
  277. szStressMemDmpPath = new TCHAR[MAX_PATH];
  278. szStressExeID = new TCHAR[MAX_PATH];
  279. if (!g_objServerCommands.IsStressRunning())
  280. {
  281. // free all old StressExeURLs first - we're replacing it with new URLs anyway
  282. g_objServerCommands.Clear_StressExeURLs();
  283. dwIndex = 0;
  284. dwStressExeIDIndex = 0;
  285. dwPageHeapCommandIndex = 0;
  286. dwUMDHCommandIndex = 0;
  287. dwStressPDBIndex = 0;
  288. dwStressSYMIndex = 0;
  289. dwStressMemDmpPathIndex = 0;
  290. dwBufferSize = MAX_URL;
  291. ZeroMemory(szBuffer, sizeof(szBuffer));
  292. while (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__STRESS_EXE_URL, szBuffer, &dwBufferSize, &dwIndex))
  293. {
  294. // *************************************
  295. // *************************************
  296. // ** COMMANDHEADER__MEMORY_DUMP_PATH: A valid path
  297. ZeroMemory(szStressMemDmpPath, MAX_PATH);
  298. dwBufferSize = MAX_PATH;
  299. WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__MEMORY_DUMP_PATH, szStressMemDmpPath, &dwBufferSize, &dwStressMemDmpPathIndex);
  300. // *************************************
  301. // *************************************
  302. // ** Get COMMANDHEADER__STRESS_PDB_URL if there is one
  303. // **
  304. ZeroMemory(szStressPDB_URL, MAX_STRESS_URL);
  305. dwBufferSize = MAX_STRESS_URL;
  306. WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__STRESS_PDB_URL, szStressPDB_URL, &dwBufferSize, &dwStressPDBIndex);
  307. // *************************************
  308. // *************************************
  309. // ** Get COMMANDHEADER__STRESS_SYM_URL if there is one
  310. // **
  311. ZeroMemory(szStressSYM_URL, MAX_STRESS_URL);
  312. dwBufferSize = MAX_STRESS_URL;
  313. WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__STRESS_SYM_URL, szStressSYM_URL, &dwBufferSize, &dwStressSYMIndex);
  314. // *************************************
  315. // *************************************
  316. // ** Get COMMANDHEADER__STRESS_EXE_PAGEHEAP if there is one
  317. // **
  318. ZeroMemory(szPageheapCommand, MAX_PATH);
  319. dwBufferSize = MAX_PATH;
  320. WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__STRESS_EXE_PAGEHEAP, szPageheapCommand, &dwBufferSize, &dwPageHeapCommandIndex);
  321. // *************************************
  322. // *************************************
  323. // ** Get COMMANDHEADER__STRESS_EXE_UMDH if there is one
  324. // **
  325. ZeroMemory(szUMDHCommand, MAX_PATH);
  326. dwBufferSize = MAX_PATH;
  327. WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__STRESS_EXE_UMDH, szUMDHCommand, &dwBufferSize, &dwUMDHCommandIndex);
  328. // *************************************
  329. // *************************************
  330. // ** Get COMMANDHEADER__STRESS_EXE_INSTANCEID
  331. // For each COMMANDHEADER__STRESS_EXE_URL, there must be an index for the stress instance from the StressADMIN DB table.
  332. // This identifies the stressinstance run. The test case (stressinstance) WILL NOT be added and run without an ID number.
  333. ZeroMemory(szStressExeID, MAX_PATH);
  334. dwBufferSize = MAX_PATH;
  335. if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__STRESS_EXE_INSTANCEID, szStressExeID, &dwBufferSize, &dwStressExeIDIndex))
  336. {
  337. // convert header ID string to a DWORD
  338. dwStressExeID = _ttol(szStressExeID);
  339. // only add valid stressInstances with valid ID's
  340. if (0 < dwStressExeID)
  341. {
  342. g_objServerCommands.Create_StressInstance(
  343. dwStressExeID,
  344. szPageheapCommand,
  345. szUMDHCommand,
  346. szStressPDB_URL,
  347. szStressSYM_URL,
  348. szStressMemDmpPath,
  349. szBuffer);
  350. dwBufferSize = MAX_URL;
  351. ZeroMemory(szBuffer, MAX_URL);
  352. }
  353. }
  354. }
  355. }
  356. delete [] szPageheapCommand;
  357. delete [] szUMDHCommand;
  358. delete [] szStressMemDmpPath;
  359. delete [] szStressPDB_URL;
  360. delete [] szStressSYM_URL;
  361. delete [] szStressExeID;
  362. // *********************************
  363. // **** COMMANDHEADER__ABORT: Abort the stress instance running specified by this header.
  364. dwIndex = 0;
  365. dwBufferSize = MAX_URL;
  366. ZeroMemory(szBuffer, sizeof(szBuffer));
  367. while (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__ABORT, szBuffer, &dwBufferSize, &dwIndex))
  368. g_objServerCommands.AbortStressInstance(_ttol(szBuffer));
  369. LeaveCriticalSection(&g_csServerCommandsVars);
  370. Exit:
  371. if (hRequest)
  372. WinHttpCloseHandle(hRequest);
  373. if (hSession)
  374. WinHttpCloseHandle(hSession);
  375. if (hRoot)
  376. WinHttpCloseHandle(hRoot);
  377. delete [] urlComponents.lpszScheme;
  378. delete [] urlComponents.lpszHostName;
  379. delete [] urlComponents.lpszUrlPath;
  380. delete [] urlComponents.lpszExtraInfo;
  381. delete [] urlComponents.lpszPassword;
  382. delete [] urlComponents.lpszUserName;
  383. ExitThread(bResult);
  384. }
  385. // *******************************************************************
  386. // *******************************************************************
  387. // ****
  388. // **** ServerCommands class member functions
  389. // ****
  390. //////////////////////////////////////////////////////////////////////
  391. // Construction/Destruction
  392. //////////////////////////////////////////////////////////////////////
  393. ServerCommands::ServerCommands()
  394. {
  395. m_dwCommandServerUpdateInternval = STRESS_COMMAND_SERVER_UPDATE_INTERVAL;
  396. m_bExit = FALSE;
  397. m_dwStressInstanceIterator = NULL;
  398. g_hQueryServerForCommands = NULL;
  399. m_szCommandServerURL = new TCHAR[MAX_STRESS_URL];
  400. m_szCommandServerResultsURL = new TCHAR[MAX_STRESS_URL];
  401. m_szWinHttpDLL_DownloadURL = new TCHAR[MAX_STRESS_URL];
  402. m_szWinHttpPDB_DownloadURL = new TCHAR[MAX_STRESS_URL];
  403. m_szWinHttpSYM_DownloadURL = new TCHAR[MAX_STRESS_URL];
  404. m_szWinHttpDLL_FileName = new TCHAR[MAX_PATH];
  405. m_szStressSchedulerCurrentDirectory = new TCHAR[MAX_PATH];
  406. m_szClientMachineName = new CHAR[MAX_PATH];
  407. ZeroMemory(m_szCommandServerURL, MAX_STRESS_URL);
  408. ZeroMemory(m_szCommandServerResultsURL, MAX_STRESS_URL);
  409. ZeroMemory(m_szWinHttpDLL_DownloadURL, MAX_STRESS_URL);
  410. ZeroMemory(m_szWinHttpPDB_DownloadURL, MAX_STRESS_URL);
  411. ZeroMemory(m_szWinHttpSYM_DownloadURL, MAX_STRESS_URL);
  412. ZeroMemory(m_szWinHttpDLL_FileName, MAX_PATH);
  413. ZeroMemory(m_szStressSchedulerCurrentDirectory, MAX_PATH);
  414. ZeroMemory(m_szClientMachineName, MAX_PATH);
  415. // initilize start/end times to -1 so we know that
  416. // there are not valid time and we'll skip the Begin/End stress time check
  417. // until we get real values from the command server
  418. m_iTimeStressBeginsHour = -1;
  419. m_iTimeStressBeginsMinute = -1;
  420. m_iTimeStressEndsHour = -1;
  421. m_iTimeStressEndsMinute = -1;
  422. m_bRunForever = 0;
  423. // Set default URLs
  424. wcsncpy(m_szCommandServerURL, STRESS_COMMAND_SERVER_URL, sizeof(STRESS_COMMAND_SERVER_URL));
  425. wcsncpy(m_szCommandServerResultsURL, STRESS_COMMAND_SERVER_RESULTS_URL, sizeof(STRESS_COMMAND_SERVER_RESULTS_URL));
  426. // Get the current working directory
  427. GetCurrentDirectory(MAX_PATH, m_szStressSchedulerCurrentDirectory);
  428. // Get the client's machine name
  429. GetEnvironmentVariableA("COMPUTERNAME", m_szClientMachineName, MAX_PATH);
  430. InitializeCriticalSection(&g_csServerCommandsVars);
  431. // Tell the client that we are alive and also send system info
  432. RegisterClient();
  433. }
  434. ServerCommands::~ServerCommands()
  435. {
  436. DWORD dwThreadExitCode = 0;
  437. // LOGLOG: stressScheduler has exited
  438. NetworkTools__SendLog(FIELDNAME__LOGTYPE_EXIT, "WinHttpStressScheduler has exited.", NULL, NULL);
  439. // Shut down QueryServer thread
  440. GetExitCodeThread(g_hQueryServerForCommands, &dwThreadExitCode);
  441. if (STILL_ACTIVE == dwThreadExitCode)
  442. WaitForSingleObject(g_hQueryServerForCommands, INFINITE);
  443. // free allocated memory for URLs
  444. Clear_StressExeURLs();
  445. // Free our handles
  446. CloseHandle(g_hQueryServerForCommands);
  447. DeleteCriticalSection(&g_csServerCommandsVars);
  448. delete [] m_szCommandServerURL;
  449. delete [] m_szCommandServerResultsURL;
  450. delete [] m_szWinHttpDLL_DownloadURL;
  451. delete [] m_szWinHttpPDB_DownloadURL;
  452. delete [] m_szWinHttpSYM_DownloadURL;
  453. delete [] m_szWinHttpDLL_FileName;
  454. delete [] m_szStressSchedulerCurrentDirectory;
  455. delete [] m_szClientMachineName;
  456. }
  457. ////////////////////////////////////////////////////////////
  458. // Function: ServerCommands::GetCurrentWorkingDirectory()
  459. //
  460. // Purpose:
  461. // Returns string containing the current working directory for
  462. // this application.
  463. //
  464. ////////////////////////////////////////////////////////////
  465. LPTSTR
  466. ServerCommands::Get_CurrentWorkingDirectory()
  467. {
  468. return m_szStressSchedulerCurrentDirectory;
  469. }
  470. ////////////////////////////////////////////////////////////
  471. // Function: ServerCommands::Get_ClientMachineName()
  472. //
  473. // Purpose:
  474. // Returns string containing the machine's NETBIOS name
  475. //
  476. ////////////////////////////////////////////////////////////
  477. LPSTR
  478. ServerCommands::Get_ClientMachineName()
  479. {
  480. return m_szClientMachineName;
  481. }
  482. ////////////////////////////////////////////////////////////
  483. // Function: ServerCommands::QueryServerForCommands()
  484. //
  485. // Purpose:
  486. // This method sends a request to the command server for instructions
  487. // and saves them in our private vars.
  488. //
  489. ////////////////////////////////////////////////////////////
  490. ServerCommands::QueryServerForCommands()
  491. {
  492. BOOL bResult = TRUE;
  493. DWORD dwThreadID = 0;
  494. DWORD dwTimeOut = 0;
  495. DWORD dwThreadExitCode = 0;
  496. // See if thread is still active before spinning off a new one
  497. GetExitCodeThread(g_hQueryServerForCommands, &dwThreadExitCode);
  498. if (STILL_ACTIVE == dwThreadExitCode)
  499. {
  500. // wait for existing thread to finish
  501. dwTimeOut = 0;
  502. dwTimeOut = WaitForSingleObject(g_hQueryServerForCommands, 500);
  503. if (WAIT_TIMEOUT == dwTimeOut)
  504. bResult = FALSE;
  505. }
  506. else
  507. {
  508. // free handle for previous thread
  509. CloseHandle(g_hQueryServerForCommands);
  510. // spin off thread to query server
  511. g_hQueryServerForCommands = NULL;
  512. g_hQueryServerForCommands = CreateThread(NULL, 0, QueryServerForCommands_ThreadProc, (LPVOID) this, 0, &dwThreadID);
  513. if (!g_hQueryServerForCommands)
  514. bResult = FALSE;
  515. }
  516. return bResult;
  517. }
  518. ////////////////////////////////////////////////////////////
  519. // Function: ServerCommands::Download_WinHttpDLL()
  520. //
  521. // Purpose:
  522. // Downloads the test DLL and symbols.
  523. //
  524. ////////////////////////////////////////////////////////////
  525. BOOL ServerCommands::Download_WinHttpDLL()
  526. {
  527. BOOL bResult = TRUE;
  528. LPTSTR szSymbolFileName = new TCHAR[MAX_PATH];
  529. LPTSTR szBuffer = new TCHAR[MAX_PATH];
  530. // ************************
  531. // ************************
  532. // ** download the file to the system32 directory
  533. // **
  534. if (!GetSystemDirectory(szBuffer, MAX_PATH))
  535. {
  536. bResult = FALSE;
  537. goto Exit;
  538. }
  539. // download DLL if needed
  540. if (_tcsclen(m_szWinHttpDLL_DownloadURL) > 0)
  541. bResult =
  542. NetworkTools__URLDownloadToFile(
  543. m_szWinHttpDLL_DownloadURL,
  544. szBuffer,
  545. m_szWinHttpDLL_FileName);
  546. if (bResult)
  547. {
  548. // download PDB file if needed
  549. if (_tcsclen(m_szWinHttpPDB_DownloadURL) > 0)
  550. {
  551. NetworkTools__GetFileNameFromURL(m_szWinHttpPDB_DownloadURL, szSymbolFileName, MAX_PATH);
  552. if (NetworkTools__URLDownloadToFile(m_szWinHttpPDB_DownloadURL, szBuffer, szSymbolFileName))
  553. NetworkTools__SendLog(FIELDNAME__LOGTYPE_SUCCESS, "PDB symbol file downloaded successfully.", NULL, 0);
  554. else
  555. NetworkTools__SendLog(FIELDNAME__LOGTYPE_ERROR, "PDB symbol file failed to downloaded.", NULL, 0);
  556. }
  557. // download sym file if needed
  558. if (_tcsclen(m_szWinHttpSYM_DownloadURL) > 0)
  559. {
  560. NetworkTools__GetFileNameFromURL(m_szWinHttpSYM_DownloadURL, szSymbolFileName, MAX_PATH);
  561. if (NetworkTools__URLDownloadToFile(m_szWinHttpSYM_DownloadURL, szBuffer, szSymbolFileName))
  562. NetworkTools__SendLog(FIELDNAME__LOGTYPE_SUCCESS, "SYM symbol file downloaded successfully.", NULL, 0);
  563. else
  564. NetworkTools__SendLog(FIELDNAME__LOGTYPE_ERROR, "SYM symbol file failed to downloaded.", NULL, 0);
  565. }
  566. }
  567. // if failed to download DLL, it's probably in use. We'll try to regsvr32 it anyways if it's there.
  568. // ************************
  569. // ************************
  570. // ** regsvr32'ed the dll just downloaded
  571. // **
  572. HINSTANCE hLib;
  573. hLib = LoadLibrary(m_szWinHttpDLL_FileName);
  574. if (hLib < (HINSTANCE)HINSTANCE_ERROR)
  575. {
  576. // unable to load the DLL;
  577. bResult = FALSE;
  578. goto Exit;
  579. }
  580. // **********************
  581. // **********************
  582. // ** Register the DLL
  583. typedef VOID (CALLBACK* LPFNDLLFUNC1)();
  584. LPFNDLLFUNC1 lpDllEntryPoint;
  585. // Find the entry point.
  586. (FARPROC&)lpDllEntryPoint = GetProcAddress(hLib, "DllRegisterServer");
  587. if (lpDllEntryPoint != NULL)
  588. (*lpDllEntryPoint)();
  589. else
  590. {
  591. //unable to locate entry point - regsvr failed
  592. bResult = FALSE;
  593. }
  594. Exit:
  595. if (bResult)
  596. NetworkTools__SendLog(FIELDNAME__LOGTYPE_INFORMATION, "winhttp5.dll downloaded and registered successfully.", NULL, 0);
  597. delete [] szSymbolFileName;
  598. delete [] szBuffer;
  599. return bResult;
  600. }
  601. ////////////////////////////////////////////////////////////
  602. // Function: ServerCommands::Set_RunForever(BOOL)
  603. //
  604. // Purpose:
  605. // Pass in TRUE to run forever ignoring begin/end time, FALSE not to.
  606. //
  607. // Called by: QueryServerForCommands_ThreadProc
  608. //
  609. ////////////////////////////////////////////////////////////
  610. VOID
  611. ServerCommands::Set_RunForever(
  612. BOOL bRunForever // [IN] TRUE to run forever ignoring begin/end time, FALSE not to.
  613. )
  614. {
  615. m_bRunForever = bRunForever;
  616. }
  617. ////////////////////////////////////////////////////////////
  618. // Function: ServerCommands::Set_ExitStress(BOOL)
  619. //
  620. // Purpose:
  621. // Pass in TRUE to exit stress as soon as possible and FALSE
  622. // not to.
  623. //
  624. // Called by: QueryServerForCommands_ThreadProc
  625. //
  626. ////////////////////////////////////////////////////////////
  627. VOID
  628. ServerCommands::Set_ExitStress(
  629. BOOL bExitStress // [IN] TRUE to exit stress, FALSE not to.
  630. )
  631. {
  632. m_bExit = bExitStress;
  633. }
  634. ////////////////////////////////////////////////////////////
  635. // Function: ServerCommands::Set_WinHttpDllURL(LPTSTR, DWORD)
  636. //
  637. // Purpose:
  638. // Pass in an URL and its size and to get the WinHttp DLL from.
  639. //
  640. // Called by: QueryServerForCommands_ThreadProc
  641. //
  642. ////////////////////////////////////////////////////////////
  643. VOID
  644. ServerCommands::Set_WinHttpDllURL(
  645. LPTSTR szBuffer, // [IN] string buffer containing URL to the WINHTTP DLL
  646. DWORD dwBufferSize // [IN] size of the szBuffer in TCHARs
  647. )
  648. {
  649. _tcscpy(m_szWinHttpDLL_DownloadURL, szBuffer);
  650. // Get the full DLL filename from the URL
  651. NetworkTools__GetFileNameFromURL(m_szWinHttpDLL_DownloadURL, m_szWinHttpDLL_FileName, MAX_PATH);
  652. }
  653. ////////////////////////////////////////////////////////////
  654. // Function: ServerCommands::Set_WinHttpPDBURL(LPTSTR, DWORD)
  655. //
  656. // Purpose:
  657. // Pass in an URL and its size and to get the WinHttp PDB file from.
  658. //
  659. // Called by: QueryServerForCommands_ThreadProc
  660. //
  661. ////////////////////////////////////////////////////////////
  662. VOID
  663. ServerCommands::Set_WinHttpPDBURL(
  664. LPTSTR szBuffer, // [IN] string buffer containing URL to the WINHTTP DLL
  665. DWORD dwBufferSize // [IN] size of the szBuffer in TCHARs
  666. )
  667. {
  668. _tcscpy(m_szWinHttpPDB_DownloadURL, szBuffer);
  669. }
  670. ////////////////////////////////////////////////////////////
  671. // Function: ServerCommands::Set_WinHttpSYMURL(LPTSTR, DWORD)
  672. //
  673. // Purpose:
  674. // Pass in an URL and its size and to get the WinHttp SYM file from.
  675. //
  676. // Called by: QueryServerForCommands_ThreadProc
  677. //
  678. ////////////////////////////////////////////////////////////
  679. VOID
  680. ServerCommands::Set_WinHttpSYMURL(
  681. LPTSTR szBuffer, // [IN] string buffer containing URL to the WINHTTP DLL
  682. DWORD dwBufferSize // [IN] size of the szBuffer in TCHARs
  683. )
  684. {
  685. _tcscpy(m_szWinHttpSYM_DownloadURL, szBuffer);
  686. }
  687. ////////////////////////////////////////////////////////////
  688. // Function: ServerCommands::Set_CommandServerURL(LPTSTR)
  689. //
  690. // Purpose:
  691. // Pass in a timeout value in milliseconds to query the
  692. // Command Server for commands.
  693. //
  694. // Called by: QueryServerForCommands_ThreadProc
  695. //
  696. ////////////////////////////////////////////////////////////
  697. VOID
  698. ServerCommands::Set_CommandServerURL(
  699. LPTSTR szBuffer, // [IN] string buffer containing URL to the WINHTTP DLL
  700. DWORD dwBufferSize // [IN] size of the szBuffer in TCHARs
  701. )
  702. {
  703. _tcscpy(m_szCommandServerURL, szBuffer);
  704. }
  705. ////////////////////////////////////////////////////////////
  706. // Function: ServerCommands::Set_CommandServerUpdateInterval(DWORD)
  707. //
  708. // Purpose:
  709. // Pass in a timeout value in milliseconds to query the
  710. // Command Server for commands.
  711. //
  712. // Called by: QueryServerForCommands_ThreadProc
  713. //
  714. ////////////////////////////////////////////////////////////
  715. VOID
  716. ServerCommands::Set_CommandServerUpdateInterval(
  717. DWORD dwUpdateInterval // [IN] time to wait before pinging the Command Server in milliseconds
  718. )
  719. {
  720. // server update interval must be at least greater than the minimum timeout
  721. if (STRESS_COMMAND_SERVER_MINIMUM_UPDATE_INTERVAL < dwUpdateInterval &&
  722. STRESS_COMMAND_SERVER_MAXIMUM_UPDATE_INTERVAL > dwUpdateInterval)
  723. m_dwCommandServerUpdateInternval = dwUpdateInterval;
  724. }
  725. ////////////////////////////////////////////////////////////
  726. // Function: ServerCommands::Set_TimeStressBegins(DWORD, DWORD)
  727. //
  728. // Purpose:
  729. // Pass in a time string to begin stress in 24 hour time.
  730. // Takes two parameters to set the hour and minute. A parameter
  731. // will be ignored if NULL.
  732. //
  733. // Called by: QueryServerForCommands_ThreadProc
  734. //
  735. ////////////////////////////////////////////////////////////
  736. VOID
  737. ServerCommands::Set_TimeStressBegins(
  738. LPTSTR szHour, // [IN] 0-23 parameter ignored if < 0
  739. LPTSTR szMinute // [IN] 0-59 parameter ignored if < 0
  740. )
  741. {
  742. if (szHour)
  743. m_iTimeStressBeginsHour = _ttoi(szHour);
  744. if (szMinute)
  745. m_iTimeStressBeginsMinute = _ttoi(szMinute);
  746. }
  747. ////////////////////////////////////////////////////////////
  748. // Function: ServerCommands::Set_TimeStressEnds(DWORD, DWORD)
  749. //
  750. // Purpose:
  751. // Pass in a time string to end stress in 24 hour time.
  752. // Takes two parameters to set the hour and minute. A parameter
  753. // will be ignored if NULL.
  754. //
  755. // Called by: QueryServerForCommands_ThreadProc
  756. //
  757. ////////////////////////////////////////////////////////////
  758. VOID
  759. ServerCommands::Set_TimeStressEnds(
  760. LPTSTR szHour, // [IN] 0-23 parameter ignored if < 0
  761. LPTSTR szMinute // [IN] 0-59 parameter ignored if < 0
  762. )
  763. {
  764. if (szHour)
  765. m_iTimeStressEndsHour = _ttoi(szHour);
  766. if (szMinute)
  767. m_iTimeStressEndsMinute = _ttoi(szMinute);
  768. }
  769. ////////////////////////////////////////////////////////////
  770. // Function: ServerCommands::Create_StressInstance(LPTSTR)
  771. //
  772. // Purpose:
  773. // Pass in an URL and its size and it will be added to the
  774. // m_arStressInstanceList list. There is no limit on the number of
  775. // URLs that can be added.
  776. //
  777. // Called by: QueryServerForCommands_ThreadProc
  778. //
  779. ////////////////////////////////////////////////////////////
  780. VOID
  781. ServerCommands::Create_StressInstance(
  782. DWORD dwStressInstanceID, // [IN] ID from the stressAdmin DB identifying this stressInstance
  783. LPTSTR szPageHeapCommand, // [IN] string buffer containing the pageheap command line
  784. LPTSTR szUMDHCommand, // [IN] string buffer containing the UMDH command line
  785. LPTSTR szPDB_URL, // [IN] string buffer containing URL to the stress EXE's PDB file
  786. LPTSTR szSYM_URL, // [IN] string buffer containing URL to the stress EXE's SYM file
  787. LPTSTR szMemDumpPath, // [IN] string buffer containing path to create memory dump files
  788. LPTSTR szEXE_URL // [IN] string buffer containing URL to the stress EXE
  789. )
  790. {
  791. PSTRESSINSTANCE pStressInstance = NULL;
  792. // verify params just in case
  793. if (!szEXE_URL)
  794. return;
  795. // allocate memory for the object and put it in the list
  796. pStressInstance = new StressInstance;
  797. pStressInstance->Set_UMDHCommands(szUMDHCommand);
  798. pStressInstance->Set_PageHeapCommands(szPageHeapCommand);
  799. pStressInstance->Set_StressExeID(dwStressInstanceID);
  800. pStressInstance->Set_StressExeURL(szEXE_URL);
  801. pStressInstance->Set_StressExeMemoryDumpPath(szMemDumpPath);
  802. pStressInstance->Set_StressExePdbURL(szPDB_URL);
  803. pStressInstance->Set_StressExeSymURL(szSYM_URL);
  804. m_arStressInstanceList.push_back(pStressInstance);
  805. m_dwStressInstanceIterator = m_arStressInstanceList.begin();
  806. }
  807. ////////////////////////////////////////////////////////////
  808. // Function: ServerCommands::Clear_StressExeURLs()
  809. //
  810. // Purpose:
  811. // Frees memory from the m_arStressExeList vector.
  812. //
  813. // Called by: QueryServerForCommands_ThreadProc and ~ServerCommands
  814. //
  815. ////////////////////////////////////////////////////////////
  816. VOID
  817. ServerCommands::Clear_StressExeURLs()
  818. {
  819. // don't want to delete StressInstances if it's still running
  820. if (IsStressRunning())
  821. return;
  822. /*
  823. // walk the list and delete from the front to back
  824. while (!m_arStressInstanceList.empty())
  825. m_arStressInstanceList.erase(m_arStressInstanceList.begin());
  826. */
  827. StressInstance *pStressInstance = NULL;
  828. for (int iIndex=0; iIndex < m_arStressInstanceList.size(); iIndex++)
  829. {
  830. pStressInstance = m_arStressInstanceList[iIndex];
  831. m_arStressInstanceList.erase(&m_arStressInstanceList[iIndex]);
  832. delete [] pStressInstance;
  833. }
  834. m_dwStressInstanceIterator = NULL;
  835. }
  836. ////////////////////////////////////////////////////////////
  837. // Function: ServerCommands::Get_CommandServerUpdateInterval()
  838. //
  839. // Purpose:
  840. // Returns the current setting for the Command Server Update
  841. // interval.
  842. //
  843. ////////////////////////////////////////////////////////////
  844. DWORD
  845. ServerCommands::Get_CommandServerUpdateInterval()
  846. {
  847. if (STRESS_COMMAND_SERVER_MINIMUM_UPDATE_INTERVAL < m_dwCommandServerUpdateInternval &&
  848. STRESS_COMMAND_SERVER_MAXIMUM_UPDATE_INTERVAL > m_dwCommandServerUpdateInternval)
  849. return m_dwCommandServerUpdateInternval;
  850. else
  851. return STRESS_COMMAND_SERVER_UPDATE_INTERVAL;
  852. }
  853. ////////////////////////////////////////////////////////////
  854. // Function: ServerCommands::BeginStress()
  855. //
  856. // Purpose:
  857. // Queries for commands then starts the StressInstance objects.
  858. //
  859. ////////////////////////////////////////////////////////////
  860. void
  861. ServerCommands::BeginStress()
  862. {
  863. EnterCriticalSection(&g_csServerCommandsVars);
  864. if (!m_arStressInstanceList.empty() && !IsStressRunning())
  865. {
  866. // LOGLOG: Stress is beginning
  867. NetworkTools__SendLog(FIELDNAME__LOGTYPE_BEGIN_STRESS, "Stress is beginning.", NULL, NULL);
  868. // first download and regsvr32 the winhttp dll and symbols
  869. Download_WinHttpDLL();
  870. for(int iIndex = 0; iIndex < m_arStressInstanceList.size(); iIndex++)
  871. m_arStressInstanceList[iIndex]->Begin();
  872. }
  873. else
  874. {
  875. // ping Command Server for list of stress EXE URLs.
  876. QueryServerForCommands();
  877. }
  878. LeaveCriticalSection(&g_csServerCommandsVars);
  879. }
  880. ////////////////////////////////////////////////////////////
  881. // Function: ServerCommands::EndStress()
  882. //
  883. // Purpose:
  884. // Ends stress and posts the results to the Command Server.
  885. //
  886. ////////////////////////////////////////////////////////////
  887. void
  888. ServerCommands::EndStress()
  889. {
  890. EnterCriticalSection(&g_csServerCommandsVars);
  891. if (!m_arStressInstanceList.empty())
  892. {
  893. if (IsStressRunning())
  894. {
  895. // LOGLOG: Stress is ending
  896. NetworkTools__SendLog(FIELDNAME__LOGTYPE_END_STRESS, "Stress is ending.", NULL, NULL);
  897. }
  898. for (int iIndex = 0; iIndex < m_arStressInstanceList.size(); iIndex++)
  899. m_arStressInstanceList[iIndex]->End();
  900. }
  901. // Remove the stress objects that already finished
  902. Clear_StressExeURLs();
  903. LeaveCriticalSection(&g_csServerCommandsVars);
  904. }
  905. ////////////////////////////////////////////////////////////
  906. // Function: ServerCommands::AbortStressInstance(DWORD)
  907. //
  908. // Purpose:
  909. // Aborts a all stress instances that recieved a server abort message.
  910. //
  911. // Called in:
  912. // QueryServerForCommands_ThreadProc
  913. //
  914. ////////////////////////////////////////////////////////////
  915. VOID
  916. ServerCommands::AbortStressInstance(DWORD dwAbortID)
  917. {
  918. // EnterCriticalSection(&g_csServerCommandsVars);
  919. if (!m_arStressInstanceList.empty())
  920. {
  921. for (int iIndex = 0; iIndex < m_arStressInstanceList.size(); iIndex++)
  922. {
  923. if (m_arStressInstanceList[iIndex]->Get_ID() == dwAbortID)
  924. m_arStressInstanceList[iIndex]->End();
  925. }
  926. }
  927. //LeaveCriticalSection(&g_csServerCommandsVars);
  928. }
  929. ////////////////////////////////////////////////////////////
  930. // Function: ServerCommands::IsStressRunning()
  931. //
  932. // Purpose:
  933. // Returns TRUE if any of the stressinstances is running. FALSE if not.
  934. //
  935. ////////////////////////////////////////////////////////////
  936. BOOL
  937. ServerCommands::IsStressRunning()
  938. {
  939. BOOL bIsRunning = FALSE;
  940. EnterCriticalSection(&g_csServerCommandsVars);
  941. if (!m_arStressInstanceList.empty())
  942. {
  943. for (int iIndex = 0; iIndex < m_arStressInstanceList.size(); iIndex++)
  944. {
  945. if (m_arStressInstanceList[iIndex]->IsRunning(STRESSINSTANCE_STRESS_EXE_CLOSE_TIMEOUT))
  946. bIsRunning = TRUE;
  947. }
  948. }
  949. LeaveCriticalSection(&g_csServerCommandsVars);
  950. return bIsRunning;
  951. }
  952. ////////////////////////////////////////////////////////////
  953. // Function: ServerCommands::IsTimeToBeginStress()
  954. //
  955. // Purpose:
  956. // TRUE if it's time to begin stress based on the time returned
  957. // from the Command Server. Will return TRUE if m_sysTimeStressBegins
  958. // is current or in the future. FALSE if not.
  959. //
  960. ////////////////////////////////////////////////////////////
  961. BOOL
  962. ServerCommands::IsTimeToBeginStress()
  963. {
  964. SYSTEMTIME stCurrent, stBeginStress, stEndStress;
  965. FILETIME ftCurrent, ftBeginStress, ftEndStress;
  966. BOOL bResult = FALSE;
  967. EnterCriticalSection(&g_csServerCommandsVars);
  968. // always run stress now if server tells us to
  969. if (m_bRunForever)
  970. {
  971. bResult = TRUE;
  972. goto Exit;
  973. }
  974. // check to see if valid time values have been received. If not, then we always fail.
  975. if (
  976. m_iTimeStressBeginsHour < 0 || m_iTimeStressBeginsMinute < 0 ||
  977. m_iTimeStressEndsHour < 0 || m_iTimeStressEndsMinute < 0
  978. )
  979. {
  980. bResult = FALSE;
  981. goto Exit;
  982. }
  983. GetLocalTime(&stCurrent);
  984. GetLocalTime(&stBeginStress);
  985. GetLocalTime(&stEndStress);
  986. // use the hour and minute time that we got from the command server
  987. stBeginStress.wHour = m_iTimeStressBeginsHour;
  988. stBeginStress.wMinute = m_iTimeStressBeginsMinute;
  989. stEndStress.wHour = m_iTimeStressEndsHour;
  990. stEndStress.wMinute = m_iTimeStressEndsMinute;
  991. // convert to file time so we can compare
  992. SystemTimeToFileTime(&stCurrent, &ftCurrent);
  993. SystemTimeToFileTime(&stBeginStress, &ftBeginStress);
  994. SystemTimeToFileTime(&stEndStress, &ftEndStress);
  995. // If EndTime < BeginTime, then it means stress is running for
  996. // over a day so we have to add 24 hours to the end time.
  997. ULARGE_INTEGER ulEndStress;
  998. ULONGLONG ullNanoSecondsInAFreakingDay;
  999. ulEndStress.LowPart = ftEndStress.dwLowDateTime;
  1000. ulEndStress.HighPart = ftEndStress.dwHighDateTime;
  1001. // stress runs across two days so we wrap around one day
  1002. ullNanoSecondsInAFreakingDay = 24 * 60; // minutes in a day
  1003. ullNanoSecondsInAFreakingDay *= 60; // seconds in a day
  1004. ullNanoSecondsInAFreakingDay *= 1000000000; // number of nanoseconds in a day. 10^9 NS in a second
  1005. ullNanoSecondsInAFreakingDay /= 100; // The FILETIME structure is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601.
  1006. if (m_iTimeStressEndsHour < m_iTimeStressBeginsHour)
  1007. {
  1008. // ********************
  1009. // ********************
  1010. // ** increase by 24 hours
  1011. // **
  1012. ulEndStress.QuadPart += ullNanoSecondsInAFreakingDay;
  1013. // copy back to the original EndStress Date/Time
  1014. ftEndStress.dwHighDateTime = ulEndStress.HighPart;
  1015. ftEndStress.dwLowDateTime = ulEndStress.LowPart;
  1016. FileTimeToSystemTime(&ftEndStress, &stEndStress);
  1017. }
  1018. else
  1019. {
  1020. // stress runs in the same day
  1021. if ((m_iTimeStressEndsHour == m_iTimeStressBeginsHour) &&
  1022. (m_iTimeStressEndsMinute <= m_iTimeStressBeginsMinute))
  1023. {
  1024. // if 7:30 to 7:20 - we wrap around one day.
  1025. ulEndStress.QuadPart += ullNanoSecondsInAFreakingDay;
  1026. // copy back to the original EndStress Date/Time
  1027. ftEndStress.dwHighDateTime = ulEndStress.HighPart;
  1028. ftEndStress.dwLowDateTime = ulEndStress.LowPart;
  1029. FileTimeToSystemTime(&ftEndStress, &stEndStress);
  1030. }
  1031. }
  1032. // Begin stress if:
  1033. // (BeginTime <= CurrentTime <= EndTime)
  1034. if ((0 <= CompareFileTime(&ftCurrent, &ftBeginStress)) && (0 <= CompareFileTime(&ftEndStress, &ftCurrent)))
  1035. bResult = TRUE;
  1036. else
  1037. bResult = FALSE;
  1038. Exit:
  1039. LeaveCriticalSection(&g_csServerCommandsVars);
  1040. return bResult;
  1041. }
  1042. ////////////////////////////////////////////////////////////
  1043. // Function: ServerCommands::IsTimeToExitStress()
  1044. //
  1045. // Purpose:
  1046. // TRUE if it's time to end stress based on the COMMANDHEADER__EXIT headers
  1047. // from the Command Server exists. FALSE if not.
  1048. //
  1049. ////////////////////////////////////////////////////////////
  1050. BOOL
  1051. ServerCommands::IsTimeToExitStress()
  1052. {
  1053. return m_bExit;
  1054. }
  1055. ////////////////////////////////////////////////////////////
  1056. // Function: ServerCommands::Get_CommandServerURL()
  1057. //
  1058. // Purpose:
  1059. // Returns the Command Server URL.
  1060. //
  1061. ////////////////////////////////////////////////////////////
  1062. LPTSTR
  1063. ServerCommands::Get_CommandServerURL()
  1064. {
  1065. return m_szCommandServerURL;
  1066. }
  1067. ////////////////////////////////////////////////////////////
  1068. // Function: ServerCommands::Get_CommandServerResultsURL()
  1069. //
  1070. // Purpose:
  1071. // Returns the Command Server Results URL.
  1072. //
  1073. ////////////////////////////////////////////////////////////
  1074. LPTSTR
  1075. ServerCommands::Get_CommandServerResultsURL()
  1076. {
  1077. return m_szCommandServerResultsURL;
  1078. }
  1079. ////////////////////////////////////////////////////////////
  1080. // Function: ServerCommands::Get_NumberOfStressInstances()
  1081. //
  1082. // Purpose:
  1083. // Returns the number of stressInstances running or pending.
  1084. //
  1085. ////////////////////////////////////////////////////////////
  1086. DWORD
  1087. ServerCommands::Get_NumberOfStressInstances()
  1088. {
  1089. return m_arStressInstanceList.size();
  1090. }
  1091. ////////////////////////////////////////////////////////////
  1092. // Function: ServerCommands::Get_TestDllFileName()
  1093. //
  1094. // Purpose:
  1095. // Returns the name of the test DLL. ex. "winhttp5.dll"
  1096. //
  1097. ////////////////////////////////////////////////////////////
  1098. LPTSTR
  1099. ServerCommands::Get_TestDllFileName()
  1100. {
  1101. // m_szWinHttpDLL_FileName can be NULL in the case that a test DLL is not downloaded
  1102. if (0 < _tcslen(m_szWinHttpDLL_FileName))
  1103. return m_szWinHttpDLL_FileName;
  1104. else
  1105. return _T("winhttp5.dll");
  1106. }
  1107. ////////////////////////////////////////////////////////////
  1108. // Function: ServerCommands::RegisterClient()
  1109. //
  1110. // Purpose:
  1111. // Sends the command server the system info on this client.
  1112. // This lets the command server know that this client is alive.
  1113. //
  1114. // NOTE: This only works in NT because we query
  1115. // environment vars not present in Win9x
  1116. //
  1117. ////////////////////////////////////////////////////////////
  1118. BOOL
  1119. ServerCommands::RegisterClient()
  1120. {
  1121. OSVERSIONINFOA osInfo;
  1122. BOOL bResult = FALSE;
  1123. DWORD dwPostSize = 5000;
  1124. DWORD dwTempSize = MAX_PATH;
  1125. DWORD dwSizeSoFar = 0; // size of string written to szTemp so far.
  1126. LPSTR szPost = new CHAR[dwPostSize];
  1127. LPSTR szTemp = new CHAR[dwTempSize];
  1128. ZeroMemory(szTemp, dwTempSize);
  1129. ZeroMemory(szPost, dwPostSize);
  1130. // *********************
  1131. // *********************
  1132. // ** Get windows version info
  1133. osInfo.dwOSVersionInfoSize = sizeof(osInfo);
  1134. if (!GetVersionExA(&osInfo))
  1135. goto Exit;
  1136. dwSizeSoFar += GetEnvironmentVariableA("OS", szTemp, dwTempSize);
  1137. dwSizeSoFar += sizeof(FIELDNAME__OS_PLATFORM);
  1138. strcat(szPost, FIELDNAME__OS_PLATFORM);
  1139. strcat(szPost, szTemp);
  1140. strcat(szPost, "&" FIELDNAME__OS_BUILD);
  1141. strcat(szPost, _itoa(osInfo.dwBuildNumber, szTemp, 10));
  1142. strcat(szPost, "&" FIELDNAME__OS_MAJORVERSION);
  1143. strcat(szPost, _itoa(osInfo.dwMajorVersion, szTemp, 10));
  1144. strcat(szPost, "&" FIELDNAME__OS_MINORVERSION);
  1145. strcat(szPost, _itoa(osInfo.dwMinorVersion, szTemp, 10));
  1146. strcat(szPost, "&" FIELDNAME__OS_EXTRAINFO);
  1147. strcat(szPost, osInfo.szCSDVersion);
  1148. // *********************
  1149. // *********************
  1150. // ** Get processor info
  1151. GetEnvironmentVariableA("PROCESSOR_ARCHITECTURE", szTemp, dwTempSize);
  1152. strcat(szPost, "&" FIELDNAME__SYSTEMINFO_PROCSSSOR_ARCHITECTURE);
  1153. strcat(szPost, szTemp);
  1154. GetEnvironmentVariableA("PROCESSOR_IDENTIFIER", szTemp, dwTempSize);
  1155. strcat(szPost, "&" FIELDNAME__SYSTEMINFO_PROCSSSOR_ID);
  1156. strcat(szPost, szTemp);
  1157. GetEnvironmentVariableA("PROCESSOR_LEVEL", szTemp, dwTempSize);
  1158. strcat(szPost, "&" FIELDNAME__SYSTEMINFO_PROCSSSOR_LEVEL);
  1159. strcat(szPost, szTemp);
  1160. GetEnvironmentVariableA("PROCESSOR_REVISION", szTemp, dwTempSize);
  1161. strcat(szPost, "&" FIELDNAME__SYSTEMINFO_PROCSSSOR_REVISION);
  1162. strcat(szPost, szTemp);
  1163. GetEnvironmentVariableA("NUMBER_OF_PROCESSORS", szTemp, dwTempSize);
  1164. strcat(szPost, "&" FIELDNAME__SYSTEMINFO_PROCSSSOR_NUMBER_OF);
  1165. strcat(szPost, szTemp);
  1166. // *********************
  1167. // *********************
  1168. // ** Get user info
  1169. GetEnvironmentVariableA("USERNAME", szTemp, dwTempSize);
  1170. strcat(szPost, "&" FIELDNAME__USERINFO_USERALIAS);
  1171. strcat(szPost, szTemp);
  1172. GetEnvironmentVariableA("USERDOMAIN", szTemp, dwTempSize);
  1173. strcat(szPost, "&" FIELDNAME__USERINFO_USERDOMAIN);
  1174. strcat(szPost, szTemp);
  1175. // BUGBUG: someone needs to resolve the user alias to the real full name of the user
  1176. // FIELDNAME__USERINFO_FULLNAME
  1177. // get the client's machine name
  1178. strcat(szPost, "&" FIELDNAME__USERINFO_MACHINENAME);
  1179. strcat(szPost, m_szClientMachineName);
  1180. // Let the Command Server know that this client is alive
  1181. bResult = NetworkTools__POSTResponse(STRESS_COMMAND_SERVER_REGISTERCLIENT_URL, szPost, NULL);
  1182. // LOGLOG: stressScheduler has started
  1183. bResult = NetworkTools__SendLog(FIELDNAME__LOGTYPE_START_UP, "WinHttpStressScheduler has started.", NULL, NULL);
  1184. Exit:
  1185. delete [] szPost;
  1186. delete [] szTemp;
  1187. return bResult;
  1188. }