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.

620 lines
18 KiB

  1. //
  2. // Foreign computer support needs more work (a-robw)
  3. //
  4. #ifdef FOREIGN_COMPUTER_SUPPORT
  5. #undef FOREIGN_COMPUTER_SUPPORT
  6. #endif
  7. #include "perfmon.h"
  8. #include "system.h" // external declarations for this file
  9. #include "perfdata.h"
  10. #include "perfmops.h"
  11. #include "playback.h" // for PlayingBackLog
  12. #include "pmemory.h"
  13. #include "utils.h" // for strsame, et al
  14. #include "sizes.h"
  15. DWORD
  16. SystemCount(
  17. PPERFSYSTEM pSystemFirst
  18. )
  19. {
  20. PPERFSYSTEM pSystem ;
  21. DWORD iNumSystems ;
  22. iNumSystems = 0 ;
  23. for (pSystem = pSystemFirst ;
  24. pSystem ;
  25. pSystem = pSystem->pSystemNext) {
  26. iNumSystems++ ;
  27. }
  28. return iNumSystems ;
  29. }
  30. BOOL
  31. SystemSetupThread (PPERFSYSTEM pSystem)
  32. {
  33. DWORD dwThreadID ;
  34. HANDLE hThread ;
  35. HANDLE hStateDataMutex ;
  36. HANDLE hPerfDataEvent ;
  37. SECURITY_ATTRIBUTES SecAttr ;
  38. PPERFDATA pSystemPerfData ;
  39. SecAttr.nLength = sizeof (SecAttr) ;
  40. SecAttr.bInheritHandle = TRUE ;
  41. SecAttr.lpSecurityDescriptor = NULL ;
  42. hThread = CreateThread (&SecAttr, 1024L,
  43. (LPTHREAD_START_ROUTINE)PerfDataThread, (LPVOID)(pSystem), 0L, &dwThreadID);
  44. if (!hThread) {
  45. SystemFree (pSystem, TRUE);
  46. return (FALSE) ;
  47. }
  48. // create a State Data Lock mutex
  49. hStateDataMutex = CreateMutex (&SecAttr, FALSE, NULL);
  50. if (!hStateDataMutex) {
  51. CloseHandle (hThread) ;
  52. SystemFree (pSystem, TRUE);
  53. return (FALSE);
  54. }
  55. hPerfDataEvent = CreateEvent (&SecAttr, TRUE, 0L, NULL) ;
  56. if (!hPerfDataEvent) {
  57. CloseHandle (hStateDataMutex) ;
  58. CloseHandle (hThread) ;
  59. SystemFree (pSystem, TRUE);
  60. return (FALSE);
  61. }
  62. // allocate Perfdata
  63. pSystemPerfData = (PPERFDATA) MemoryAllocate (4096L) ;
  64. if (!pSystemPerfData) {
  65. CloseHandle (hPerfDataEvent) ;
  66. CloseHandle (hStateDataMutex) ;
  67. CloseHandle (hThread) ;
  68. SystemFree (pSystem, TRUE);
  69. return (FALSE);
  70. }
  71. // now setup the pSystem..
  72. pSystem->dwThreadID = dwThreadID ;
  73. pSystem->hThread = hThread ;
  74. pSystem->hPerfDataEvent = hPerfDataEvent ;
  75. pSystem->pSystemPerfData = pSystemPerfData ;
  76. pSystem->hStateDataMutex = hStateDataMutex ;
  77. return (TRUE) ;
  78. }
  79. PPERFSYSTEM
  80. SystemCreate (
  81. LPCTSTR lpszSystemName
  82. )
  83. {
  84. PPERFSYSTEM pSystem ;
  85. PPERFDATA pLocalPerfData = NULL;
  86. DWORD Status ;
  87. DWORD dwMemSize;
  88. TCHAR GlobalValueBuffer[] = L"Global" ;
  89. TCHAR ForeignValueBuffer[8+MAX_SYSTEM_NAME_LENGTH+1] =
  90. L"Foreign " ;
  91. // attempt to allocate system data structure
  92. pSystem = MemoryAllocate (sizeof (PERFSYSTEM)) ;
  93. if (!pSystem) {
  94. SetLastError (ERROR_OUTOFMEMORY) ;
  95. return (NULL) ;
  96. }
  97. // initialize name and help table pointers
  98. pSystem->CounterInfo.pNextTable = NULL;
  99. pSystem->CounterInfo.dwLangId = 0;
  100. pSystem->CounterInfo.dwLastId = 0;
  101. pSystem->CounterInfo.TextString = NULL;
  102. lstrcpy (pSystem->sysName, lpszSystemName) ;
  103. // try to open key to registry, error code is in GetLastError()
  104. pSystem->sysDataKey = OpenSystemPerfData(lpszSystemName);
  105. // if a Null Key was returned then:
  106. // a) there's no such computer
  107. // b) the system is a foreign computer
  108. //
  109. // before giving up, then see if it's a foreign computer
  110. if (!pSystem->sysDataKey) {
  111. // build foreign computer string
  112. lstrcat(ForeignValueBuffer, lpszSystemName) ;
  113. // assign System value name pointer to the local variable for trial
  114. pSystem->lpszValue = ForeignValueBuffer;
  115. // try to get data from the computer to see if it's for real
  116. // otherwise, give up and return NULL
  117. pLocalPerfData = MemoryAllocate (STARTING_SYSINFO_SIZE);
  118. if (pLocalPerfData == NULL) { // no mem so give up
  119. pSystem->lpszValue = NULL;
  120. SystemFree (pSystem, TRUE);
  121. SetLastError (ERROR_OUTOFMEMORY);
  122. return (NULL);
  123. } else {
  124. pSystem->sysDataKey = HKEY_PERFORMANCE_DATA; // local machine
  125. bCloseLocalMachine = TRUE ;
  126. dwMemSize = STARTING_SYSINFO_SIZE;
  127. Status = GetSystemPerfData (
  128. pSystem->sysDataKey,
  129. pSystem->lpszValue,
  130. pLocalPerfData,
  131. &dwMemSize);
  132. // success means a valid buffer came back
  133. // more data means someone tried (so it's probably good (?)
  134. if ((Status == ERROR_MORE_DATA) || (Status == ERROR_SUCCESS)) {
  135. if (Status == ERROR_SUCCESS) {
  136. // see if a perf buffer was returned
  137. if ((dwMemSize > 0) &&
  138. pLocalPerfData->Signature[0] == (WCHAR)'P' &&
  139. pLocalPerfData->Signature[1] == (WCHAR)'E' &&
  140. pLocalPerfData->Signature[2] == (WCHAR)'R' &&
  141. pLocalPerfData->Signature[3] == (WCHAR)'F' ) {
  142. // valid buffer so continue
  143. } else {
  144. // invalid so unable to connect to that machine
  145. pSystem->lpszValue = NULL;
  146. SystemFree (pSystem, TRUE);
  147. SetLastError (ERROR_BAD_NET_NAME); // unable to find name
  148. return (NULL);
  149. }
  150. } else {
  151. // assume that if MORE_DATA is returned that SOME
  152. // data was attempted so the buffer must be valid
  153. // (we hope)
  154. }
  155. MemoryFree ((LPMEMORY)pLocalPerfData) ;
  156. pLocalPerfData = NULL;
  157. // if we are reading from a setting file, let this pass thru'
  158. if (bDelayAddAction == TRUE) {
  159. pSystem->sysDataKey = NULL ;
  160. pSystem->FailureTime = GetTickCount();
  161. pSystem->dwSystemState = SYSTEM_DOWN;
  162. // Free any memory that may have created
  163. SystemFree (pSystem, FALSE) ;
  164. pSystem->lpszValue = MemoryAllocate (TEMP_BUF_LEN*sizeof(WCHAR));
  165. if (!pSystem->lpszValue) {
  166. // unable to allocate memory
  167. SystemFree (pSystem, TRUE);
  168. SetLastError (ERROR_OUTOFMEMORY);
  169. return (NULL) ;
  170. } else {
  171. lstrcpy (pSystem->lpszValue, GlobalValueBuffer);
  172. }
  173. // Setup the thread's stuff
  174. if (SystemSetupThread (pSystem))
  175. return (pSystem) ;
  176. else
  177. return NULL;
  178. }
  179. } else {
  180. // some other error was returned so pack up and leave
  181. pSystem->lpszValue = NULL;
  182. SystemFree (pSystem, TRUE);
  183. SetLastError (ERROR_BAD_NET_NAME); // unable to find name
  184. return (NULL);
  185. }
  186. if (pLocalPerfData != NULL) {
  187. MemoryFree ((LPMEMORY)pLocalPerfData); // don't really need anything from it
  188. }
  189. // ok, so we've established that a foreign data provider
  190. // exists, now to finish the initialization.
  191. // change system name in structure to get counter names
  192. lstrcpy (pSystem->sysName, LocalComputerName);
  193. Status = GetSystemNames(pSystem); // get counter names & explain text
  194. if (Status != ERROR_SUCCESS) {
  195. // unable to get names so bail out
  196. pSystem->lpszValue = NULL;
  197. SystemFree (pSystem, TRUE);
  198. SetLastError (Status);
  199. return (NULL) ;
  200. }
  201. // restore computer name for displays, etc.
  202. lstrcpy (pSystem->sysName, lpszSystemName);
  203. // allocate value string buffer
  204. pSystem->lpszValue = MemoryAllocate (TEMP_BUF_LEN*sizeof(WCHAR));
  205. if (!pSystem->lpszValue) {
  206. // unable to allocate memory
  207. SystemFree (pSystem, TRUE);
  208. SetLastError (ERROR_OUTOFMEMORY);
  209. return (NULL) ;
  210. } else {
  211. lstrcpy (pSystem->lpszValue, ForeignValueBuffer);
  212. }
  213. }
  214. } else {
  215. // if here, then a connection to the system's registry was established
  216. // so continue with the system data structure initialization
  217. // get counter names & explain text from local computer
  218. Status = GetSystemNames(pSystem);
  219. if (Status != ERROR_SUCCESS) {
  220. // unable to get names so bail out
  221. SystemFree (pSystem, TRUE);
  222. SetLastError (Status);
  223. return (NULL) ;
  224. }
  225. // allocate value string buffer
  226. pSystem->lpszValue = MemoryAllocate(TEMP_BUF_LEN*sizeof(WCHAR));
  227. if (!pSystem->lpszValue) {
  228. // unable to allocate memory
  229. SystemFree (pSystem, TRUE);
  230. SetLastError (ERROR_OUTOFMEMORY);
  231. return (NULL) ;
  232. } else {
  233. SetSystemValueNameToGlobal (pSystem);
  234. }
  235. }
  236. // initialize remaining system pointers
  237. pSystem->pSystemNext = NULL ;
  238. pSystem->FailureTime = 0;
  239. // setup data for thread data collection
  240. if (!PlayingBackLog()) {
  241. // create a thread for data collection
  242. if (!SystemSetupThread (pSystem))
  243. return (NULL) ;
  244. }
  245. SetLastError (ERROR_SUCCESS);
  246. return (pSystem) ;
  247. } // SystemCreate
  248. PPERFSYSTEM
  249. SystemGet (
  250. PPERFSYSTEM pSystemFirst,
  251. LPCTSTR lpszSystemName
  252. )
  253. {
  254. PPERFSYSTEM pSystem ;
  255. if (!pSystemFirst) {
  256. return (NULL) ;
  257. }
  258. for (pSystem = pSystemFirst ;
  259. pSystem ;
  260. pSystem = pSystem->pSystemNext) {
  261. if (strsamei (pSystem->sysName, lpszSystemName)) {
  262. return (pSystem) ;
  263. }
  264. } // for
  265. return (NULL) ;
  266. }
  267. PPERFSYSTEM
  268. SystemAdd (
  269. PPPERFSYSTEM ppSystemFirst,
  270. LPCTSTR lpszSystemName,
  271. HWND hDlg // owner window for error messages
  272. )
  273. {
  274. PPERFSYSTEM pSystem ;
  275. PPERFSYSTEM pSystemPrev = NULL;
  276. TCHAR szMessage[256];
  277. DWORD dwLastError;
  278. if (!*ppSystemFirst) {
  279. *ppSystemFirst = SystemCreate (lpszSystemName) ;
  280. dwLastError = GetLastError();
  281. // save return value
  282. pSystem = *ppSystemFirst;
  283. } else {
  284. for (pSystem = *ppSystemFirst ;
  285. pSystem ;
  286. pSystem = pSystem->pSystemNext) {
  287. pSystemPrev = pSystem ;
  288. if (strsamei (pSystem->sysName, lpszSystemName)) {
  289. return (pSystem) ;
  290. }
  291. } // for
  292. pSystemPrev->pSystemNext = SystemCreate (lpszSystemName) ;
  293. // save return value
  294. pSystem = pSystemPrev->pSystemNext;
  295. }
  296. // display message box here if an error occured trying to add
  297. // this system
  298. if (pSystem == NULL) {
  299. dwLastError = GetLastError();
  300. if (dwLastError == ERROR_ACCESS_DENIED) {
  301. DlgErrorBox (hDlg, ERR_ACCESS_DENIED);
  302. } else {
  303. DlgErrorBox (hDlg, ERR_UNABLE_CONNECT);
  304. }
  305. SetLastError (dwLastError); // to propogate up to caller
  306. }
  307. return (pSystem);
  308. }
  309. void
  310. SystemFree (
  311. PPERFSYSTEM pSystem,
  312. BOOL bDeleteTheSystem
  313. )
  314. { // SystemFree
  315. PCOUNTERTEXT pCounter, pNextCounter;
  316. if (!pSystem) {
  317. // can't proceed
  318. return ;
  319. }
  320. if (pSystem->sysDataKey && pSystem->sysDataKey != HKEY_PERFORMANCE_DATA) {
  321. // close the remote computer key
  322. RegCloseKey (pSystem->sysDataKey);
  323. pSystem->sysDataKey = 0 ;
  324. }
  325. for (pCounter = pSystem->CounterInfo.pNextTable, pNextCounter = NULL;
  326. pCounter;
  327. pCounter = pNextCounter) {
  328. pNextCounter = pCounter->pNextTable;
  329. MemoryFree (pCounter);
  330. }
  331. pSystem->CounterInfo.pNextTable = NULL ;
  332. if (pSystem->CounterInfo.TextString) {
  333. MemoryFree (pSystem->CounterInfo.TextString);
  334. pSystem->CounterInfo.TextString = NULL ;
  335. }
  336. if (pSystem->CounterInfo.HelpTextString) {
  337. MemoryFree (pSystem->CounterInfo.HelpTextString);
  338. pSystem->CounterInfo.HelpTextString = NULL ;
  339. }
  340. pSystem->CounterInfo.dwLastId = 0 ;
  341. pSystem->CounterInfo.dwHelpSize = 0 ;
  342. pSystem->CounterInfo.dwCounterSize = 0 ;
  343. if (bDeleteTheSystem) {
  344. #if 0
  345. // cleanup all the data collection variables
  346. if (pSystem->hPerfDataEvent)
  347. CloseHandle (pSystem->hPerfDataEvent) ;
  348. if (pSystem->hStateDataMutex)
  349. CloseHandle (pSystem->hStateDataMutex) ;
  350. if (pSystem->hThread)
  351. CloseHandle (pSystem->hThread) ;
  352. if (pSystem->pSystemPerfData)
  353. MemoryFree (pSystem->pSystemPerfData);
  354. if (pSystem->lpszValue) {
  355. MemoryFree (pSystem->lpszValue);
  356. pSystem->lpszValue = NULL ;
  357. }
  358. MemoryFree (pSystem) ;
  359. #endif
  360. if (pSystem->hThread) {
  361. // let the thread clean up memory
  362. PostThreadMessage (
  363. pSystem->dwThreadID,
  364. WM_FREE_SYSTEM,
  365. (WPARAM)0,
  366. (LPARAM)0) ;
  367. } else {
  368. // if no thread, clean up memory here.
  369. // Should not happen.
  370. if (pSystem->pSystemPerfData)
  371. MemoryFree ((LPMEMORY)pSystem->pSystemPerfData);
  372. if (pSystem->lpszValue) {
  373. MemoryFree (pSystem->lpszValue);
  374. pSystem->lpszValue = NULL ;
  375. }
  376. MemoryFree (pSystem) ;
  377. }
  378. }
  379. }
  380. void
  381. DeleteUnusedSystems (
  382. PPPERFSYSTEM ppSystemFirst ,
  383. int iNoUseSystems
  384. )
  385. {
  386. PPERFSYSTEM pPrevSys, pCurrentSys, pNextSys ;
  387. // delete all the marked system from the list header until
  388. // we hit one that is not marked
  389. while ((*ppSystemFirst)->bSystemNoLongerNeeded) {
  390. // delect from the list header
  391. pCurrentSys = *ppSystemFirst ;
  392. *ppSystemFirst = pCurrentSys->pSystemNext ;
  393. SystemFree (pCurrentSys, TRUE) ;
  394. iNoUseSystems-- ;
  395. if (iNoUseSystems <= 0 || !(*ppSystemFirst)) {
  396. // done
  397. break ;
  398. }
  399. }
  400. if (iNoUseSystems <= 0 || !(*ppSystemFirst)) {
  401. return ;
  402. }
  403. // now walk the list and delete each marked system
  404. for (pPrevSys = *ppSystemFirst, pCurrentSys = pPrevSys->pSystemNext ;
  405. pCurrentSys && iNoUseSystems > 0 ;
  406. pCurrentSys = pNextSys) {
  407. if (pCurrentSys->bSystemNoLongerNeeded) {
  408. // the current system is marked, updated the list and free
  409. // this system. No need to change pPrevSys here
  410. pNextSys = pPrevSys->pSystemNext = pCurrentSys->pSystemNext ;
  411. SystemFree (pCurrentSys, TRUE) ;
  412. iNoUseSystems-- ;
  413. } else {
  414. // pCurrentSys is OK, update the 2 list pointers and
  415. // carry on looping
  416. pPrevSys = pCurrentSys ;
  417. pNextSys = pCurrentSys->pSystemNext ;
  418. }
  419. }
  420. }
  421. void
  422. FreeSystems (
  423. PPERFSYSTEM pSystemFirst
  424. )
  425. {
  426. PPERFSYSTEM pSystem, pSystemNext ;
  427. for (pSystem = pSystemFirst;
  428. pSystem;
  429. pSystem = pSystemNext) {
  430. pSystemNext = pSystem->pSystemNext ;
  431. SystemFree (pSystem, TRUE) ;
  432. }
  433. } // FreeSystems
  434. PPERFSYSTEM
  435. GetComputer (
  436. HDLG hDlg,
  437. WORD wControlID,
  438. BOOL bWarn,
  439. PPERFDATA *ppPerfData,
  440. PPERFSYSTEM *ppSystemFirst
  441. )
  442. /*
  443. Effect: Attempt to set the current computer to the one in the
  444. hWndComputers dialog edit box. If this computer system
  445. can be found, load the objects, etc. for the computer
  446. and set pSystem and ppPerfdata to the values for this
  447. system.
  448. */
  449. { // GetComputer
  450. TCHAR szComputer [MAX_SYSTEM_NAME_LENGTH + 1] ;
  451. PPERFSYSTEM pSystem;
  452. TCHAR tempBuffer [LongTextLen] ;
  453. DWORD dwBufferSize = 0;
  454. LPTSTR pBuffer = NULL ;
  455. DWORD dwLastError;
  456. DialogText (hDlg, wControlID, szComputer) ;
  457. // If necessary, add the system to the lists for this view.
  458. pSystem = SystemGet (*ppSystemFirst, szComputer) ;
  459. if (!pSystem) {
  460. pSystem = SystemAdd (ppSystemFirst, szComputer, hDlg) ;
  461. }
  462. if (!pSystem && bWarn) {
  463. dwLastError = GetLastError();
  464. EditSetModified (GetDlgItem(hDlg, wControlID), FALSE) ;
  465. // unable to get specified computer so set to:
  466. // the first computer in the system list if present
  467. // -- or --
  468. // set he local machine if not.
  469. pSystem = *ppSystemFirst; // set to first in list
  470. if (pSystem == NULL) {
  471. // this would mean the user can't access the local
  472. // system since normally that would be the first one
  473. // so the machine name will be restored to the
  474. // local machine (for lack of a better one) but the
  475. // system won't be added unless they want to explicitly
  476. DialogSetString (hDlg, wControlID, LocalComputerName) ;
  477. } else {
  478. // set to name in system structure
  479. DialogSetString (hDlg, wControlID, pSystem->sysName);
  480. }
  481. if (dwLastError != ERROR_ACCESS_DENIED) {
  482. DlgErrorBox (hDlg, ERR_COMPUTERNOTFOUND) ;
  483. } else {
  484. // the appropriate error message has already been displayed
  485. }
  486. SetFocus (DialogControl(hDlg, wControlID)) ;
  487. }
  488. if (pSystem) {
  489. if (PlayingBackLog ()) {
  490. *ppPerfData =
  491. LogDataFromPosition (pSystem, &(PlaybackLog.StartIndexPos)) ;
  492. } else {
  493. if (pSystem->lpszValue) {
  494. // save the previous lpszValue string before
  495. // SetSystemValueNameToGlobal mess it up
  496. dwBufferSize = MemorySize (pSystem->lpszValue) ;
  497. if (dwBufferSize <= sizeof(tempBuffer)) {
  498. pBuffer = tempBuffer ;
  499. } else {
  500. pBuffer = MemoryAllocate (dwBufferSize) ;
  501. }
  502. memcpy (pBuffer, pSystem->lpszValue, dwBufferSize) ;
  503. }
  504. SetSystemValueNameToGlobal (pSystem);
  505. UpdateSystemData (pSystem, ppPerfData) ;
  506. if (pSystem->lpszValue) {
  507. // retore the previous lpszValue string
  508. memcpy (pSystem->lpszValue, pBuffer, dwBufferSize) ;
  509. if (pBuffer != tempBuffer) {
  510. MemoryFree (pBuffer) ;
  511. }
  512. }
  513. }
  514. }
  515. return (pSystem) ;
  516. } // GetComputer
  517.