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.

937 lines
24 KiB

  1. /*++
  2. Copyright (c) 2002 Microsoft Corporation
  3. Module Name:
  4. perfipsec.c
  5. Abstract:
  6. This file implements the Extensible Objects for the IPsec object type
  7. Created:
  8. Avnish Kumar Chhabra 09 July 2002
  9. Revision History
  10. --*/
  11. //
  12. // Include Files
  13. //
  14. #include <nt.h>
  15. #include <ntrtl.h>
  16. #include <nturtl.h>
  17. #include <ntddser.h>
  18. #include <windows.h>
  19. #include <string.h>
  20. #include <wcstr.h>
  21. #include <winperf.h>
  22. #include <malloc.h>
  23. #include <ntprfctr.h>
  24. #include <winipsec.h>
  25. #include "perfipsec.h"
  26. #include "dataipsec.h"
  27. #include "ipsecnm.h"
  28. //
  29. // Determines whether counter name and help indices have been correctly initialized
  30. // 1) This is set to TRUE after one successful call to UpdateDataDefFromRegistry.
  31. // 2) While this is TRUE ; DwInitializeIPSecCounters need not be called.
  32. //
  33. BOOL g_bInitOK = FALSE; // true = DLL initialized OK
  34. //
  35. // The number of threads that have called open but not called close as yet
  36. // 1) Needed to initialize the critical section g_csPerf when the first client calls open
  37. // 2) Needed to delete the critical section once all clients have called close
  38. //
  39. DWORD g_dwOpenCount = 0; // count of "Open" threads
  40. //
  41. // Critical section used to serialize access t o UpDateDataDefFromRegistry
  42. // This prevents multiple concurrent threads from entering this function
  43. // and adding the base offset to counter indices multiple times .
  44. //
  45. CRITICAL_SECTION g_csPerf;
  46. //
  47. // Contant strings used to identify the nature of the collect request.
  48. //
  49. WCHAR GLOBAL_STRING[] = L"Global";
  50. WCHAR FOREIGN_STRING[] = L"Foreign";
  51. WCHAR COSTLY_STRING[] = L"Costly";
  52. //***
  53. //
  54. // Routine Description:
  55. //
  56. // This routine will initialize the entry points into winipsec.dll
  57. // which will be used to communicate statistics with SPD
  58. // Arguments:
  59. //
  60. // Pointer to object ID of each device to be opened
  61. //
  62. //
  63. // Return Value:
  64. //
  65. // None.
  66. //
  67. //***
  68. DWORD
  69. OpenIPSecPerformanceData(
  70. LPWSTR lpDeviceNames
  71. )
  72. {
  73. //
  74. // Since SCREG is multi-threaded and will call this routine in
  75. // order to service remote performance queries, this library
  76. // must keep track of how many times it has been opened (i.e.
  77. // how many threads have accessed it). the registry routines will
  78. // limit access to the initialization routine to only one thread
  79. // at a time so synchronization (i.e. reentrancy) should not be
  80. // a problem
  81. //
  82. // First call into this function
  83. if (!g_dwOpenCount){
  84. InitializeCriticalSection(&g_csPerf);
  85. }
  86. g_dwOpenCount++;
  87. //
  88. // Do we need to initialize the counter name and help indicess
  89. //
  90. if (!g_bInitOK){
  91. DwInitializeIPSecCounters();
  92. }
  93. return ERROR_SUCCESS;
  94. }
  95. DWORD
  96. DwInitializeIPSecCounters(
  97. VOID
  98. )
  99. {
  100. LONG status = ERROR_SUCCESS;
  101. // Serialize access to index update routine
  102. EnterCriticalSection(&g_csPerf);
  103. if (g_bInitOK){
  104. goto EXIT;
  105. }
  106. //
  107. // Update the IPsec Driver and IKE counter's name and help indices
  108. //
  109. if (UpdateDataDefFromRegistry()){
  110. status = ERROR_SUCCESS; // for successful exit
  111. g_bInitOK = TRUE; // No need to reinitialize indices after this
  112. }
  113. else{
  114. status = ERROR_REGISTRY_IO_FAILED;
  115. }
  116. EXIT:
  117. LeaveCriticalSection(&g_csPerf);
  118. return status;
  119. }
  120. //************
  121. //
  122. // Function: UpdateDataDefFromRegistry
  123. //
  124. // Synopsis: Gets counter and help index base values from registry as follows :
  125. // 1) Open key to registry entry
  126. // 2) Read First Counter and First Help values
  127. // 3) Update static data strucutures gIPSecDriverDataDefnition by adding base to
  128. // offset value in structure.
  129. //
  130. // Arguments: None
  131. //
  132. // Returns: TRUE if succeeds, FALSE otherwise
  133. //
  134. //*************
  135. BOOL UpdateDataDefFromRegistry(
  136. VOID
  137. )
  138. {
  139. HKEY hKeyDriverPerf;
  140. DWORD status;
  141. DWORD type;
  142. DWORD size;
  143. DWORD dwFirstCounter;
  144. DWORD dwFirstHelp;
  145. PERF_COUNTER_DEFINITION *pctr;
  146. DWORD i;
  147. BOOL fRetValue = TRUE, fKeyOpened=FALSE;
  148. status = RegOpenKeyEx (
  149. HKEY_LOCAL_MACHINE,
  150. IPSEC_PERF_REG_KEY,
  151. 0L,
  152. KEY_READ,
  153. &hKeyDriverPerf);
  154. if (status != ERROR_SUCCESS) {
  155. //
  156. // this is fatal, if we can't get the base values of the
  157. // counter or help names, then the names won't be available
  158. // to the requesting application so there's not much
  159. // point in continuing.
  160. //
  161. fRetValue= FALSE;
  162. goto EXIT;
  163. }
  164. fKeyOpened=TRUE;
  165. size = sizeof (DWORD);
  166. status = RegQueryValueEx(
  167. hKeyDriverPerf,
  168. IPSEC_PERF_FIRST_COUNTER,
  169. 0L,
  170. &type,
  171. (LPBYTE)&dwFirstCounter,
  172. &size);
  173. if (status != ERROR_SUCCESS) {
  174. //
  175. // this is fatal, if we can't get the base values of the
  176. // counter or help names, then the names won't be available
  177. // to the requesting application so there's not much
  178. // point in continuing.
  179. //
  180. fRetValue = FALSE;
  181. goto EXIT;
  182. }
  183. size = sizeof (DWORD);
  184. status = RegQueryValueEx(
  185. hKeyDriverPerf,
  186. IPSEC_PERF_FIRST_HELP,
  187. 0L,
  188. &type,
  189. (LPBYTE)&dwFirstHelp,
  190. &size);
  191. if (status != ERROR_SUCCESS) {
  192. //
  193. // this is fatal, if we can't get the base values of the
  194. // counter or help names, then the names won't be available
  195. // to the requesting application so there's not much
  196. // point in continuing.
  197. //
  198. fRetValue = FALSE;
  199. goto EXIT;
  200. }
  201. //
  202. // We can not fail now
  203. //
  204. fRetValue = TRUE;
  205. //
  206. // Initialize counter object indices
  207. //
  208. gIPSecDriverDataDefinition.IPSecObjectType.ObjectNameTitleIndex += dwFirstCounter;
  209. gIPSecDriverDataDefinition.IPSecObjectType.ObjectHelpTitleIndex += dwFirstHelp;
  210. //
  211. // Initialize all IPSec Driver counter's indices
  212. //
  213. pctr = &gIPSecDriverDataDefinition.ActiveSA;
  214. for( i=0; i<NUM_OF_IPSEC_DRIVER_COUNTERS; i++ ){
  215. pctr->CounterNameTitleIndex += dwFirstCounter;
  216. pctr->CounterHelpTitleIndex += dwFirstHelp;
  217. pctr ++;
  218. }
  219. gIKEDataDefinition.IKEObjectType.ObjectNameTitleIndex += dwFirstCounter;
  220. gIKEDataDefinition.IKEObjectType.ObjectHelpTitleIndex += dwFirstHelp;
  221. //
  222. // Initialize all IKE counter's indices
  223. //
  224. pctr = &gIKEDataDefinition.AcquireHeapSize;
  225. for( i=0; i<NUM_OF_IKE_COUNTERS; i++ ){
  226. pctr->CounterNameTitleIndex += dwFirstCounter;
  227. pctr->CounterHelpTitleIndex += dwFirstHelp;
  228. pctr ++;
  229. }
  230. EXIT:
  231. if (fKeyOpened){
  232. //
  233. // close key to registry
  234. //
  235. RegCloseKey (hKeyDriverPerf);
  236. }
  237. return fRetValue;
  238. }
  239. //***
  240. //
  241. // Routine Description:
  242. //
  243. // This routine will return the data for the IPSec counters.
  244. //
  245. // Arguments:
  246. //
  247. // IN OUT LPWSTR lpValueName
  248. // pointer to a wide character string passed by registry.
  249. //
  250. // IN OUT LPVOID *lppData
  251. // IN: pointer to the address of the buffer to receive the completed
  252. // PerfDataBlock and subordinate structures. This routine will
  253. // append its data to the buffer starting at the point referenced
  254. // by *lppData.
  255. // OUT: points to the first byte after the data structure added by this
  256. // routine. This routine updated the value at lppdata after appending
  257. // its data.
  258. //
  259. // IN OUT LPDWORD lpcbTotalBytes
  260. // IN: the address of the DWORD that tells the size in bytes of the
  261. // buffer referenced by the lppData argument
  262. // OUT: the number of bytes added by this routine is written to the
  263. // DWORD pointed to by this argument
  264. //
  265. // IN OUT LPDWORD NumObjectTypes
  266. // IN: the address of the DWORD to receive the number of objects added
  267. // by this routine
  268. // OUT: the number of objects added by this routine is written to the
  269. // DWORD pointed to by this argument
  270. //
  271. // Return Value:
  272. //
  273. // ERROR_MORE_DATA if buffer passed is too small to hold data
  274. // any error conditions encountered are reported to the event log if
  275. // event logging is enabled.
  276. //
  277. // ERROR_SUCCESS if success or any other error. Errors, however are
  278. // also reported to the event log.
  279. //
  280. //***
  281. DWORD CollectIPSecPerformanceData(
  282. IN LPWSTR lpValueName,
  283. IN OUT LPVOID *lppData,
  284. IN OUT LPDWORD lpcbTotalBytes,
  285. IN OUT LPDWORD lpNumObjectTypes
  286. )
  287. {
  288. DWORD dwQueryType;
  289. BOOL IsIPSecDriverObject = FALSE ,IsIKEObject = FALSE;
  290. ULONG SpaceNeeded =0;
  291. DWORD status;
  292. //
  293. // Initialize the counter indices if neccessary
  294. //
  295. if (!g_bInitOK){
  296. DwInitializeIPSecCounters();
  297. }
  298. //
  299. // Make sure that
  300. // (a) Counter indices have been initialized
  301. // (b) IPsec service is presently running
  302. //
  303. if ((!g_bInitOK) || (!FIPSecStarted())){
  304. *lpcbTotalBytes = (DWORD) 0;
  305. *lpNumObjectTypes = (DWORD) 0;
  306. return ERROR_SUCCESS;
  307. }
  308. dwQueryType = GetQueryType (lpValueName);
  309. //
  310. // see if this is a foreign (i.e. non-NT) computer data request
  311. //
  312. if (dwQueryType == QUERY_FOREIGN){
  313. //
  314. // this routine does not service requests for data from
  315. // Non-NT computers
  316. //
  317. *lpcbTotalBytes = (DWORD) 0;
  318. *lpNumObjectTypes = (DWORD) 0;
  319. return ERROR_SUCCESS;
  320. }
  321. else if (dwQueryType == QUERY_ITEMS){
  322. IsIPSecDriverObject = IsNumberInUnicodeList (gIPSecDriverDataDefinition.IPSecObjectType.ObjectNameTitleIndex,
  323. lpValueName);
  324. IsIKEObject = IsNumberInUnicodeList (gIKEDataDefinition.IKEObjectType.ObjectNameTitleIndex,
  325. lpValueName);
  326. if ( !IsIPSecDriverObject && !IsIKEObject )
  327. {
  328. //
  329. // request received for data object not provided by this routine
  330. //
  331. *lpcbTotalBytes = (DWORD) 0;
  332. *lpNumObjectTypes = (DWORD) 0;
  333. return ERROR_SUCCESS;
  334. }
  335. }
  336. else if( dwQueryType == QUERY_GLOBAL )
  337. {
  338. IsIPSecDriverObject = IsIKEObject = TRUE;
  339. }
  340. //
  341. // Now check to see if we have enough space to hold all the data
  342. //
  343. SpaceNeeded = GetSpaceNeeded(IsIPSecDriverObject, IsIKEObject);
  344. if ( *lpcbTotalBytes < SpaceNeeded )
  345. {
  346. *lpcbTotalBytes = (DWORD) 0;
  347. *lpNumObjectTypes = (DWORD) 0;
  348. return ERROR_MORE_DATA;
  349. }
  350. *lpcbTotalBytes = (DWORD) 0;
  351. *lpNumObjectTypes = (DWORD) 0;
  352. //
  353. // Then we fill in the data for object ipsec driver, if needed.
  354. //
  355. if( IsIPSecDriverObject )
  356. {
  357. PIPSEC_DRIVER_DATA_DEFINITION pIPSecDriverDataDefinition;
  358. PVOID pData;
  359. pIPSecDriverDataDefinition = (PIPSEC_DRIVER_DATA_DEFINITION) *lppData;
  360. //
  361. // Copy the (constant, initialized) Object Type and counter definitions
  362. // to the caller's data buffer
  363. //
  364. memcpy( pIPSecDriverDataDefinition,
  365. &gIPSecDriverDataDefinition,
  366. sizeof(IPSEC_DRIVER_DATA_DEFINITION));
  367. //
  368. // Now copy the counter block.
  369. //
  370. pData = (PBYTE) pIPSecDriverDataDefinition + ALIGN8(sizeof(IPSEC_DRIVER_DATA_DEFINITION));
  371. status = GetDriverData( &pData );
  372. if (ERROR_SUCCESS == status){
  373. //
  374. // Set *lppData to the next available byte.
  375. //
  376. *lppData = pData;
  377. (*lpNumObjectTypes)++;
  378. }
  379. }
  380. if (IsIKEObject)
  381. {
  382. PIKE_DATA_DEFINITION pIKEDataDefinition;
  383. PVOID pData;
  384. pIKEDataDefinition = (PIKE_DATA_DEFINITION)*lppData;
  385. //
  386. // Copy the (Constant,initialized) Object Type and counter definitions
  387. // to the callers Datan Buffer
  388. //
  389. memcpy(pIKEDataDefinition,
  390. &gIKEDataDefinition,
  391. sizeof(IKE_DATA_DEFINITION));
  392. //
  393. // Now copy the counter block
  394. //
  395. pData = (PBYTE)pIKEDataDefinition + ALIGN8(sizeof(IKE_DATA_DEFINITION));
  396. status = GetIKEData(&pData);
  397. if (ERROR_SUCCESS == status){
  398. //
  399. // Set *lppData to the next available byte
  400. //
  401. *lppData = pData;
  402. (*lpNumObjectTypes)++;
  403. }
  404. }
  405. if (ERROR_SUCCESS == status){
  406. *lpcbTotalBytes = SpaceNeeded;
  407. }
  408. return ERROR_SUCCESS;
  409. }
  410. //***
  411. //
  412. // Routine Description:
  413. //
  414. // This routine closes the open handles to IPSec device performance
  415. // counters.
  416. //
  417. // Arguments:
  418. //
  419. // None.
  420. //
  421. // Return Value:
  422. //
  423. // ERROR_SUCCESS
  424. //
  425. //***
  426. DWORD
  427. CloseIPSecPerformanceData(
  428. VOID
  429. )
  430. {
  431. if (!(--g_dwOpenCount))
  432. {
  433. //
  434. // when this is the last thread...
  435. //
  436. EnterCriticalSection(&g_csPerf);
  437. DeleteCriticalSection(&g_csPerf);
  438. }
  439. return ERROR_SUCCESS;
  440. }
  441. //***
  442. //
  443. // Routine Description:
  444. //
  445. // This routine closes fetched IKE statistics from SPD and puts it into Perfmon's buffers
  446. //
  447. // Arguments:
  448. //
  449. // IN OUT PVOID * lppData
  450. // IN : Contains the pointer to the location where the counter stats can be placed
  451. // OUT: Contains the pointer to the first byte after the counter stats
  452. // Return Value:
  453. //
  454. // ERROR_SUCCESS
  455. //
  456. //***
  457. DWORD
  458. GetIKEData(
  459. IN OUT PVOID *lppData
  460. )
  461. {
  462. IKE_PM_STATS UNALIGNED * pIKEPMStats;
  463. DWORD status;
  464. IKE_STATISTICS IKEStats;
  465. pIKEPMStats = (IKE_PM_STATS UNALIGNED *)*lppData;
  466. pIKEPMStats->CounterBlock.ByteLength = ALIGN8(SIZEOF_IPSEC_TOTAL_IKE_DATA);
  467. status = QueryIKEStatistics(NULL, 0,&IKEStats, NULL );
  468. if ( status != ERROR_SUCCESS) {
  469. return status;
  470. }
  471. //
  472. // Go to end of PerfCounterBlock to get array of counters
  473. //
  474. pIKEPMStats->AcquireHeapSize = IKEStats.dwAcquireHeapSize;
  475. pIKEPMStats->ReceiveHeapSize = IKEStats.dwReceiveHeapSize;
  476. pIKEPMStats->NegFailure = IKEStats.dwNegotiationFailures;
  477. pIKEPMStats->AuthFailure = IKEStats.dwAuthenticationFailures;
  478. pIKEPMStats->ISADBSize = IKEStats.dwIsadbListSize;
  479. pIKEPMStats->ConnLSize = IKEStats.dwConnListSize;
  480. pIKEPMStats->MmSA = IKEStats.dwOakleyMainModes;
  481. pIKEPMStats->QmSA = IKEStats.dwOakleyQuickModes;
  482. pIKEPMStats->SoftSA = IKEStats.dwSoftAssociations;
  483. //
  484. // Update *lppData to the next available byte.
  485. //
  486. *lppData = (PVOID) ((PBYTE) pIKEPMStats + pIKEPMStats->CounterBlock.ByteLength);
  487. return ERROR_SUCCESS;
  488. }
  489. //***
  490. //
  491. // Routine Description:
  492. //
  493. // This routine closes fetched IPSec driver statistics from SPD and puts it into Perfmon's
  494. // buffers
  495. //
  496. // Arguments:
  497. //
  498. // IN OUT PVOID * lppData
  499. // IN : Contains the pointer to the location where the counter stats can be placed
  500. // OUT: Contains the pointer to the first byte after the counter stats
  501. // Return Value:
  502. //
  503. // ERROR_SUCCESS
  504. //
  505. //***
  506. DWORD
  507. GetDriverData(
  508. PVOID *lppData
  509. )
  510. {
  511. IPSEC_DRIVER_PM_STATS UNALIGNED * pIPSecPMStats;
  512. DWORD status = ERROR_SUCCESS;
  513. PIPSEC_STATISTICS pIPSecStats;
  514. IPSEC_STATISTICS IPSecStats;
  515. pIPSecPMStats = (IPSEC_DRIVER_PM_STATS UNALIGNED *) *lppData;
  516. pIPSecPMStats->CounterBlock.ByteLength = ALIGN8(SIZEOF_IPSEC_TOTAL_DRIVER_DATA);
  517. status = QueryIPSecStatistics(NULL,0,&pIPSecStats,NULL);
  518. if (status != ERROR_SUCCESS) {
  519. return status;
  520. }
  521. IPSecStats = *pIPSecStats;
  522. SPDApiBufferFree(pIPSecStats);
  523. //
  524. // Go to end of PerfCounterBlock to get of array of counters
  525. //
  526. pIPSecPMStats->ActiveSA= IPSecStats.dwNumActiveAssociations;
  527. pIPSecPMStats->OffloadedSA= IPSecStats.dwNumOffloadedSAs;
  528. pIPSecPMStats->PendingKeyOps= IPSecStats.dwNumPendingKeyOps;
  529. pIPSecPMStats->Rekey= IPSecStats.dwNumReKeys;
  530. pIPSecPMStats->BadSPIPackets= IPSecStats.dwNumBadSPIPackets;
  531. pIPSecPMStats->PacketsNotDecrypted= IPSecStats.dwNumPacketsNotDecrypted;
  532. pIPSecPMStats->PacketsNotAuthenticated= IPSecStats.dwNumPacketsNotAuthenticated;
  533. pIPSecPMStats->PacketsWithReplayDetection= IPSecStats.dwNumPacketsWithReplayDetection;
  534. pIPSecPMStats->TptBytesSent= IPSecStats.uTransportBytesSent;
  535. pIPSecPMStats->TptBytesRecv= IPSecStats.uTransportBytesReceived;
  536. pIPSecPMStats->TunBytesSent= IPSecStats.uBytesSentInTunnels;
  537. pIPSecPMStats->TunBytesRecv= IPSecStats.uBytesReceivedInTunnels;
  538. pIPSecPMStats->OffloadedBytesSent= IPSecStats.uOffloadedBytesSent;
  539. pIPSecPMStats->OffloadedBytesRecv= IPSecStats.uOffloadedBytesReceived;
  540. //
  541. // Update *lppData to the next available byte.
  542. //
  543. *lppData = (PVOID) ((PBYTE) pIPSecPMStats + pIPSecPMStats->CounterBlock.ByteLength);
  544. return ERROR_SUCCESS;
  545. }
  546. //***
  547. //
  548. // Routine Description:
  549. //
  550. // This routine will return the number of Bytes needed for all the
  551. // objects requested.
  552. //
  553. // Arguments:
  554. //
  555. // None.
  556. //
  557. // Return Value:
  558. //
  559. // The number of bytes needed to store stats of requested objects
  560. //
  561. //***
  562. ULONG
  563. GetSpaceNeeded(
  564. BOOL IsIPSecDriverObject,
  565. BOOL IsIKEObject
  566. )
  567. {
  568. ULONG Space = 0;
  569. if( IsIPSecDriverObject )
  570. {
  571. Space += gIPSecDriverDataDefinition.IPSecObjectType.TotalByteLength;
  572. }
  573. if( IsIKEObject )
  574. {
  575. Space += gIKEDataDefinition.IKEObjectType.TotalByteLength;
  576. }
  577. return Space;
  578. }
  579. DWORD
  580. GetQueryType (
  581. IN LPWSTR lpValue
  582. )
  583. /*++
  584. GetQueryType
  585. returns the type of query described in the lpValue string so that
  586. the appropriate processing method may be used
  587. Arguments
  588. IN lpValue
  589. string passed to CollectIPSecPerformanceData for processing
  590. Return Value
  591. QUERY_GLOBAL
  592. if lpValue == 0 (null pointer)
  593. lpValue == pointer to Null string
  594. lpValue == pointer to "Global" string
  595. QUERY_FOREIGN
  596. if lpValue == pointer to "Foriegn" string
  597. QUERY_COSTLY
  598. if lpValue == pointer to "Costly" string
  599. otherwise:
  600. QUERY_ITEMS
  601. --*/
  602. {
  603. WCHAR *pwcArgChar, *pwcTypeChar;
  604. BOOL bFound;
  605. if (lpValue == 0) {
  606. return QUERY_GLOBAL;
  607. } else if (*lpValue == 0) {
  608. return QUERY_GLOBAL;
  609. }
  610. // check for "Global" request
  611. pwcArgChar = lpValue;
  612. pwcTypeChar = GLOBAL_STRING;
  613. bFound = TRUE; // assume found until contradicted
  614. // check to the length of the shortest string
  615. while ((*pwcArgChar != 0) && (*pwcTypeChar != 0)) {
  616. if (*pwcArgChar++ != *pwcTypeChar++) {
  617. bFound = FALSE; // no match
  618. break; // bail out now
  619. }
  620. }
  621. if (bFound) return QUERY_GLOBAL;
  622. // check for "Foreign" request
  623. pwcArgChar = lpValue;
  624. pwcTypeChar = FOREIGN_STRING;
  625. bFound = TRUE; // assume found until contradicted
  626. // check to the length of the shortest string
  627. while ((*pwcArgChar != 0) && (*pwcTypeChar != 0)) {
  628. if (*pwcArgChar++ != *pwcTypeChar++) {
  629. bFound = FALSE; // no match
  630. break; // bail out now
  631. }
  632. }
  633. if (bFound) return QUERY_FOREIGN;
  634. // check for "Costly" request
  635. pwcArgChar = lpValue;
  636. pwcTypeChar = COSTLY_STRING;
  637. bFound = TRUE; // assume found until contradicted
  638. // check to the length of the shortest string
  639. while ((*pwcArgChar != 0) && (*pwcTypeChar != 0)) {
  640. if (*pwcArgChar++ != *pwcTypeChar++) {
  641. bFound = FALSE; // no match
  642. break; // bail out now
  643. }
  644. }
  645. if (bFound) return QUERY_COSTLY;
  646. // if not Global and not Foreign and not Costly,
  647. // then it must be an item list
  648. return QUERY_ITEMS;
  649. }
  650. BOOL
  651. IsNumberInUnicodeList (
  652. IN DWORD dwNumber,
  653. IN LPWSTR lpwszUnicodeList
  654. )
  655. /*++
  656. IsNumberInUnicodeList
  657. Arguments:
  658. IN dwNumber
  659. DWORD number to find in list
  660. IN lpwszUnicodeList
  661. Null terminated, Space delimited list of decimal numbers
  662. Return Value:
  663. TRUE:
  664. dwNumber was found in the list of unicode number strings
  665. FALSE:
  666. dwNumber was not found in the list.
  667. --*/
  668. {
  669. DWORD dwThisNumber;
  670. WCHAR *pwcThisChar;
  671. BOOL bValidNumber;
  672. BOOL bNewItem;
  673. BOOL bReturnValue;
  674. WCHAR wcDelimiter; // could be an argument to be more flexible
  675. if (lpwszUnicodeList == 0) return FALSE; // null pointer, # not founde
  676. pwcThisChar = lpwszUnicodeList;
  677. dwThisNumber = 0;
  678. wcDelimiter = (WCHAR)' ';
  679. bValidNumber = FALSE;
  680. bNewItem = TRUE;
  681. while (TRUE) {
  682. switch (EvalThisChar (*pwcThisChar, wcDelimiter)) {
  683. case DIGIT:
  684. // if this is the first digit after a delimiter, then
  685. // set flags to start computing the new number
  686. if (bNewItem) {
  687. bNewItem = FALSE;
  688. bValidNumber = TRUE;
  689. }
  690. if (bValidNumber) {
  691. dwThisNumber *= 10;
  692. dwThisNumber += (*pwcThisChar - (WCHAR)'0');
  693. }
  694. break;
  695. case DELIMITER:
  696. // a delimter is either the delimiter character or the
  697. // end of the string ('\0') if when the delimiter has been
  698. // reached a valid number was found, then compare it to the
  699. // number from the argument list. if this is the end of the
  700. // string and no match was found, then return.
  701. //
  702. if (bValidNumber) {
  703. if (dwThisNumber == dwNumber) return TRUE;
  704. bValidNumber = FALSE;
  705. }
  706. if (*pwcThisChar == 0) {
  707. return FALSE;
  708. } else {
  709. bNewItem = TRUE;
  710. dwThisNumber = 0;
  711. }
  712. break;
  713. case INVALID:
  714. // if an invalid character was encountered, ignore all
  715. // characters up to the next delimiter and then start fresh.
  716. // the invalid number is not compared.
  717. bValidNumber = FALSE;
  718. break;
  719. default:
  720. break;
  721. }
  722. pwcThisChar++;
  723. }
  724. } // IsNumberInUnicodeList
  725. BOOL
  726. FIPSecStarted(VOID)
  727. {
  728. SC_HANDLE schandle = NULL;
  729. SC_HANDLE svchandle = NULL;
  730. BOOL fRet = FALSE;
  731. //
  732. // Check to see if ipsec service is started.
  733. // fail if it isn't.
  734. //
  735. schandle = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  736. if(NULL != schandle)
  737. {
  738. svchandle = OpenService(schandle,
  739. IPSEC_POLAGENT_NAME,
  740. SERVICE_QUERY_STATUS);
  741. if(NULL != svchandle)
  742. {
  743. SERVICE_STATUS status;
  744. if( (QueryServiceStatus(svchandle, &status))
  745. && (status.dwCurrentState == SERVICE_RUNNING))
  746. {
  747. fRet = TRUE;
  748. }
  749. CloseServiceHandle(svchandle);
  750. }
  751. CloseServiceHandle(schandle);
  752. }
  753. return fRet;
  754. }