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.

1975 lines
69 KiB

  1. /*++
  2. Copyright (c) 2002 Microsoft Corporation
  3. Module Name:
  4. SceAnalysisReader.cpp
  5. Abstract:
  6. implementation of class SceAnalysisReader
  7. SceAnalysisReader is a class that facilitates reading
  8. Analysis information from a SCE JET security database
  9. This analysis information can be exported with the help
  10. of an SceXMLLogWriter instance.
  11. Author:
  12. Steven Chan (t-schan) July 2002
  13. --*/
  14. // System header files
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <shlwapi.h>
  19. // COM/XML header files
  20. #include <atlbase.h>
  21. // CRT header files
  22. #include <iostream.h>
  23. // SCE header files
  24. #include "secedit.h"
  25. // SecMan header files
  26. #include "SceXmlLogWriter.h"
  27. #include "resource.h"
  28. #include "table.h"
  29. #include "SceLogException.h"
  30. #include "SceAnalysisReader.h"
  31. #include "w2kstructdefs.h"
  32. #include "SceProfInfoAdapter.h"
  33. SceAnalysisReader::SceAnalysisReader(
  34. HMODULE hModule,
  35. IN PCWSTR szFileName
  36. )
  37. /*++
  38. Routine Description:
  39. Constructor for class SceAnalysisReader
  40. Arguments:
  41. hModule: handle to module
  42. szFileName: File Name for Security Analysis Database to open
  43. Return Value:
  44. none
  45. --*/
  46. {
  47. ppSAPBuffer = NULL;
  48. ppSMPBuffer = NULL;
  49. hProfile = NULL;
  50. LogWriter = NULL;
  51. myModuleHandle=hModule;
  52. try {
  53. //myModuleHandle=GetModuleHandle(L"SecMan");
  54. if (szFileName!=NULL) {
  55. this->szFileName = new WCHAR[wcslen(szFileName)+1];
  56. wcscpy(this->szFileName, szFileName);
  57. }
  58. // determine windows version
  59. OSVERSIONINFO osvi;
  60. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  61. GetVersionEx (&osvi);
  62. if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 0)) {
  63. bIsW2k = TRUE;
  64. SceEngineSAP = (SCETYPE) W2K_SCE_ENGINE_SAP;
  65. SceEngineSMP = (SCETYPE) W2K_SCE_ENGINE_SMP;
  66. } else {
  67. bIsW2k = FALSE;
  68. SceEngineSAP = SCE_ENGINE_SAP;
  69. SceEngineSMP = SCE_ENGINE_SMP;
  70. }
  71. if (osvi.dwMajorVersion < 5) {
  72. throw new SceLogException(SceLogException::SXERROR_OS_NOT_SUPPORTED,
  73. L"bAcceptableOS==FALSE",
  74. NULL,
  75. 0);
  76. }
  77. } catch (...) {
  78. throw new SceLogException(SceLogException::SXERROR_INIT,
  79. L"bInitSuccess==FALSE",
  80. NULL,
  81. 0);
  82. }
  83. }
  84. SceAnalysisReader::~SceAnalysisReader()
  85. /*++
  86. Routine Description:
  87. destructor for SceAnalysisReader
  88. Arguments:
  89. none
  90. Return Value:
  91. none
  92. --*/
  93. {
  94. if (hProfile!=NULL) {
  95. SceCloseProfile(&hProfile);
  96. hProfile=NULL;
  97. }
  98. if (ppSAPBuffer != NULL) {
  99. delete ppSAPBuffer;
  100. ppSAPBuffer = NULL;
  101. }
  102. if (ppSMPBuffer != NULL) {
  103. delete ppSMPBuffer;
  104. ppSMPBuffer = NULL;
  105. }
  106. if (szFileName != NULL) {
  107. delete szFileName;
  108. szFileName = NULL;
  109. }
  110. }
  111. void
  112. SceAnalysisReader::ExportAnalysis(
  113. IN SceXMLLogWriter *LogWriter,
  114. IN HANDLE hLogFile OPTIONAL
  115. )
  116. /*++
  117. Routine Description:
  118. exports the analysis information from this->filename to an outout file
  119. via LogWriter
  120. Arguments:
  121. LogWriter: The LogWriter to use for logging output
  122. hLogFile: Error log file handle
  123. Return Value:
  124. none
  125. Throws:
  126. SceLogException
  127. --*/
  128. {
  129. DWORD dwTmp;
  130. BOOL bTmp;
  131. PWSTR szProfDesc=NULL;
  132. PWSTR szAnalysisTime=NULL;
  133. SCESTATUS rc;
  134. hProfile=NULL;
  135. PSCE_PROFILE_INFO ppSAPPInfo = NULL;
  136. PSCE_PROFILE_INFO ppSMPPInfo = NULL;
  137. try {
  138. if (LogWriter!=NULL) {
  139. this->LogWriter=LogWriter;
  140. } else {
  141. throw new SceLogException(SceLogException::SXERROR_INIT,
  142. L"ExtractAnalysis(ILLEGAL ARG)",
  143. NULL,
  144. 0);
  145. }
  146. //
  147. // Open specified SDB file
  148. //
  149. trace(IDS_LOG_OPEN_DATABASE, hLogFile);
  150. trace(szFileName,hLogFile);
  151. trace(L"\n\r\n\r",hLogFile);
  152. rc = SceOpenProfile(szFileName, SCE_JET_FORMAT, &hProfile);
  153. switch (rc) {
  154. case SCESTATUS_SUCCESS:
  155. break;
  156. case SCESTATUS_PROFILE_NOT_FOUND:
  157. throw new SceLogException(SceLogException::SXERROR_OPEN_FILE_NOT_FOUND,
  158. L"SceOpenProfile(szFileName, SCE_JET_FORMAT, &hProfile)",
  159. NULL,
  160. rc);
  161. break;
  162. default:
  163. throw new SceLogException(SceLogException::SXERROR_OPEN,
  164. L"SceOpenProfile(szFileName, SCE_JET_FORMAT, &hProfile)",
  165. NULL,
  166. rc);
  167. break;
  168. }
  169. //
  170. // extract System Settings to ppSAPBuffer
  171. // and Baseline Settings to ppSMPBuffer
  172. //
  173. rc = SceGetSecurityProfileInfo(hProfile,
  174. SceEngineSAP,
  175. AREA_ALL,
  176. &ppSAPPInfo,
  177. NULL);
  178. if (rc!=SCESTATUS_SUCCESS) {
  179. throw new SceLogException(SceLogException::SXERROR_READ_NO_ANALYSIS_TABLE,
  180. L"SceGetSecurityProfileInfo(...)",
  181. NULL,
  182. rc);
  183. }
  184. ppSAPBuffer = new SceProfInfoAdapter(ppSAPPInfo, bIsW2k); // for w2k compat
  185. rc = SceGetSecurityProfileInfo(hProfile,
  186. SceEngineSMP,
  187. AREA_ALL,
  188. &ppSMPPInfo,
  189. NULL);
  190. if (rc!=SCESTATUS_SUCCESS) {
  191. throw new SceLogException(SceLogException::SXERROR_READ_NO_CONFIGURATION_TABLE,
  192. L"SceGetSecurityProfileInfo(...)",
  193. NULL,
  194. rc);
  195. }
  196. ppSMPBuffer = new SceProfInfoAdapter(ppSMPPInfo, bIsW2k); // for w2k compat
  197. //
  198. // get Profile Description, timestamp and machine name and log these
  199. //
  200. trace(IDS_LOG_PROFILE_DESC, hLogFile);
  201. rc = SceGetScpProfileDescription(hProfile, &szProfDesc);
  202. if (rc!=SCESTATUS_SUCCESS) {
  203. throw new SceLogException(SceLogException::SXERROR_READ,
  204. L"SceGetScpProfileDescription(hProfile, &szProfDesc)",
  205. NULL,
  206. rc);
  207. }
  208. trace(szProfDesc,hLogFile);
  209. trace (L"\n\r\n\r",hLogFile);
  210. trace(IDS_LOG_ANALYSIS_TIME, hLogFile);
  211. rc = SceGetTimeStamp(hProfile,
  212. NULL,
  213. &szAnalysisTime);
  214. if (rc!=SCESTATUS_SUCCESS) {
  215. throw new SceLogException(SceLogException::SXERROR_READ,
  216. L"SceGetTimeStamp(hProfile,NULL,&szAnalysisTime)",
  217. NULL,
  218. rc);
  219. }
  220. trace(szAnalysisTime, hLogFile);
  221. trace (L"\n\r\n\r",hLogFile);
  222. trace(IDS_LOG_MACHINE_NAME, hLogFile);
  223. dwTmp=STRING_BUFFER_SIZE;
  224. bTmp=GetComputerName(szTmpStringBuffer, &dwTmp);
  225. if (!bTmp) {
  226. throw new SceLogException(SceLogException::SXERROR_INTERNAL,
  227. L"GetComputerName(szTmpStringBuffer, &dwTmp",
  228. NULL,
  229. 0);
  230. }
  231. trace(szTmpStringBuffer, hLogFile);
  232. LogWriter->SetDescription(szTmpStringBuffer,
  233. szProfDesc,
  234. szAnalysisTime);
  235. trace(L"\n\r\n\r", hLogFile);
  236. //
  237. // export various areas of settings
  238. //
  239. this->ExportAreaSystemAccess();
  240. this->ExportAreaSystemAudit();
  241. this->ExportAreaKerberos();
  242. this->ExportAreaRegistryValues();
  243. this->ExportAreaServices();
  244. this->ExportAreaGroupMembership();
  245. this->ExportAreaPrivileges();
  246. this->ExportAreaFileSecurity();
  247. this->ExportAreaRegistrySecurity();
  248. // All Analysis Finished!!!
  249. // If We've gotten this far, this was a successful run
  250. } // try
  251. catch(SceLogException *e) {
  252. //
  253. // Cleanup after normal/abnormal termination
  254. //
  255. // Close Profile
  256. if (hProfile!=NULL) {
  257. SceCloseProfile(&hProfile);
  258. hProfile=NULL;
  259. }
  260. // Free Memory
  261. if (szProfDesc!=NULL) {
  262. free(szProfDesc);
  263. szProfDesc=NULL;
  264. }
  265. if (szAnalysisTime!=NULL) {
  266. free(szAnalysisTime);
  267. szAnalysisTime=NULL;
  268. }
  269. if (ppSAPBuffer != NULL) {
  270. delete ppSAPBuffer;
  271. ppSAPBuffer=NULL;
  272. }
  273. if (ppSMPBuffer != NULL) {
  274. delete ppSMPBuffer;
  275. ppSMPBuffer=NULL;
  276. }
  277. if (ppSAPPInfo != NULL ) {
  278. SceFreeProfileMemory(ppSAPPInfo);
  279. ppSAPPInfo=NULL;
  280. }
  281. if (ppSMPPInfo != NULL ) {
  282. SceFreeProfileMemory(ppSMPPInfo);
  283. ppSMPPInfo=NULL;
  284. }
  285. e->AddDebugInfo(L"ExportAnalysis(LogWriter, hLogFile)");
  286. throw e;
  287. }
  288. catch(...){
  289. //
  290. // Cleanup after normal/abnormal termination
  291. //
  292. // Close Profile
  293. if (hProfile!=NULL) {
  294. SceCloseProfile(&hProfile);
  295. hProfile=NULL;
  296. }
  297. // Free Memory
  298. if (szProfDesc!=NULL) {
  299. free(szProfDesc);
  300. szProfDesc=NULL;
  301. }
  302. if (szAnalysisTime!=NULL) {
  303. free(szAnalysisTime);
  304. szAnalysisTime=NULL;
  305. }
  306. if (ppSAPBuffer != NULL) {
  307. delete ppSAPBuffer;
  308. ppSAPBuffer=NULL;
  309. }
  310. if (ppSMPBuffer != NULL) {
  311. delete ppSMPBuffer;
  312. ppSMPBuffer=NULL;
  313. }
  314. if (ppSAPPInfo != NULL ) {
  315. SceFreeProfileMemory(ppSAPPInfo);
  316. ppSAPPInfo=NULL;
  317. }
  318. if (ppSMPPInfo != NULL ) {
  319. SceFreeProfileMemory(ppSMPPInfo);
  320. ppSMPPInfo=NULL;
  321. }
  322. throw new SceLogException(SceLogException::SXERROR_INTERNAL,
  323. L"ExportAnalysis(LogWriter, hLogFile)",
  324. NULL,
  325. 0);
  326. }
  327. //
  328. // Cleanup after normal/abnormal termination
  329. //
  330. // Close Profile
  331. if (hProfile!=NULL) {
  332. SceCloseProfile(&hProfile);
  333. hProfile=NULL;
  334. }
  335. // Free Memory
  336. if (szProfDesc!=NULL) {
  337. free(szProfDesc);
  338. szProfDesc=NULL;
  339. }
  340. if (szAnalysisTime!=NULL) {
  341. free(szAnalysisTime);
  342. szAnalysisTime=NULL;
  343. }
  344. if (ppSAPBuffer != NULL) {
  345. delete ppSAPBuffer;
  346. ppSAPBuffer=NULL;
  347. }
  348. if (ppSMPBuffer != NULL) {
  349. delete ppSMPBuffer;
  350. ppSMPBuffer=NULL;
  351. }
  352. if (ppSAPPInfo != NULL ) {
  353. SceFreeProfileMemory(ppSAPPInfo);
  354. ppSAPPInfo=NULL;
  355. }
  356. if (ppSMPPInfo != NULL ) {
  357. SceFreeProfileMemory(ppSMPPInfo);
  358. ppSMPPInfo=NULL;
  359. }
  360. }
  361. void
  362. SceAnalysisReader::ExportAreaSystemAccess(
  363. )
  364. /*++
  365. Routine Description:
  366. Internal method to export System Access settings.
  367. Should only be called from within ExportAnalysis() after
  368. the necessary global variables have been initialized
  369. Arguments:
  370. none
  371. Return Value:
  372. none
  373. --*/
  374. {
  375. int iTmp;
  376. try {
  377. LogWriter->SetNewArea(TEXT("SystemAccess"));
  378. //
  379. // cycle through settings in table
  380. // system access table size is calculated just once
  381. //
  382. iTmp=sizeof(tableSystemAccess)/sizeof(tableEntry);
  383. for (int i=0; i<iTmp; i++) {
  384. // load description string
  385. LoadString(myModuleHandle,
  386. tableSystemAccess[i].displayNameUID,
  387. szTmpStringBuffer,
  388. STRING_BUFFER_SIZE);
  389. // add setting
  390. LogWriter->AddSetting(tableSystemAccess[i].name,
  391. szTmpStringBuffer,
  392. TYPECAST(DWORD, ppSMPBuffer, tableSystemAccess[i].offset),
  393. TYPECAST(DWORD, ppSAPBuffer, tableSystemAccess[i].offset),
  394. tableSystemAccess[i].displayType);
  395. }
  396. // two additional non-DWORD settings
  397. LoadString(myModuleHandle,
  398. IDS_SETTING_NEW_ADMIN,
  399. szTmpStringBuffer,
  400. STRING_BUFFER_SIZE);
  401. LogWriter->AddSetting(TEXT("NewAdministratorName"),
  402. szTmpStringBuffer,
  403. ppSMPBuffer->NewAdministratorName,
  404. ppSAPBuffer->NewAdministratorName,
  405. SceXMLLogWriter::TYPE_DEFAULT);
  406. LoadString(myModuleHandle,
  407. IDS_SETTING_NEW_GUEST,
  408. szTmpStringBuffer,
  409. STRING_BUFFER_SIZE);
  410. LogWriter->AddSetting(TEXT("NewGuestName"),
  411. szTmpStringBuffer,
  412. ppSMPBuffer->NewGuestName,
  413. ppSAPBuffer->NewGuestName,
  414. SceXMLLogWriter::TYPE_BOOLEAN);
  415. } catch (SceLogException *e) {
  416. e->SetArea(L"SystemAccess");
  417. e->AddDebugInfo(L"SceAnalysisReader::ExportAreaSystemAccess()");
  418. throw e;
  419. } catch (...) {
  420. throw new SceLogException(SceLogException::SXERROR_INTERNAL,
  421. L"SceAnalysisReader::ExportAreaSystemAccess()",
  422. NULL,
  423. 0);
  424. }
  425. }
  426. void
  427. SceAnalysisReader::ExportAreaSystemAudit(
  428. )
  429. /*++
  430. Routine Description:
  431. Internal method to export System Audit settings.
  432. Should only be called from within ExportAnalysis() after
  433. the necessary global variables have been initialized
  434. Arguments:
  435. none
  436. Return Value:
  437. none
  438. --*/
  439. {
  440. int iTmp;
  441. try {
  442. LogWriter->SetNewArea(TEXT("SystemAudit"));
  443. //
  444. // cycle through settings in table\
  445. // system audit table size is calculated just once
  446. //
  447. iTmp=sizeof(tableSystemAudit)/sizeof(tableEntry);
  448. for (int i=0; i<iTmp; i++) {
  449. // load description string
  450. LoadString(myModuleHandle,
  451. tableSystemAudit[i].displayNameUID,
  452. szTmpStringBuffer,
  453. STRING_BUFFER_SIZE);
  454. // add setting
  455. LogWriter->AddSetting(tableSystemAudit[i].name,
  456. szTmpStringBuffer,
  457. TYPECAST(DWORD, ppSMPBuffer, tableSystemAudit[i].offset),
  458. TYPECAST(DWORD, ppSAPBuffer, tableSystemAudit[i].offset),
  459. tableSystemAudit[i].displayType);
  460. }
  461. } catch (SceLogException *e) {
  462. e->SetArea(L"SystemAudit");
  463. e->AddDebugInfo(L"SceAnalysisReader::ExportAreaSystemAudit()");
  464. throw e;
  465. } catch (...) {
  466. throw new SceLogException(SceLogException::SXERROR_INTERNAL,
  467. L"SceAnalysisReader::ExportAreaSystemAudit()",
  468. NULL,
  469. 0);
  470. }
  471. }
  472. void
  473. SceAnalysisReader::ExportAreaGroupMembership(
  474. )
  475. /*++
  476. Routine Description:
  477. Internal method to export Group Membership settings.
  478. Should only be called from within ExportAnalysis() after
  479. the necessary global variables have been initialized
  480. Arguments:
  481. none
  482. Return Value:
  483. none
  484. --*/
  485. {
  486. SceXMLLogWriter::SXMATCH_STATUS match;
  487. INT iTmp;
  488. try {
  489. LogWriter->SetNewArea(TEXT("GroupMembership"));
  490. PSCE_GROUP_MEMBERSHIP pGroupSystem = ppSAPBuffer->pGroupMembership;
  491. PSCE_GROUP_MEMBERSHIP pGroupBase = ppSMPBuffer->pGroupMembership;
  492. PSCE_GROUP_MEMBERSHIP pGroupTBase, pGroupTSystem;
  493. //
  494. // For every group in the Baseline Profile, we attempt to find
  495. // its corresponding group in the Anaylsis Profile
  496. //
  497. pGroupTBase = pGroupBase;
  498. while (pGroupTBase!=NULL) {
  499. PWSTR szGroupName = pGroupTBase->GroupName;
  500. BOOL found = FALSE;
  501. //
  502. // search for group in system
  503. //
  504. pGroupTSystem = pGroupSystem;
  505. while ( (pGroupTSystem!=NULL) && !found ) {
  506. if (_wcsicmp(szGroupName, pGroupTSystem->GroupName)==0) {
  507. //
  508. // found the matching group
  509. //
  510. // determine match status for Group Members
  511. match = LogWriter->MATCH_TRUE;
  512. if (pGroupTSystem->Status & 0x01) {
  513. match = LogWriter->MATCH_FALSE;
  514. } else
  515. if (pGroupTSystem->Status & 0x10) {
  516. match = LogWriter->MATCH_NOT_ANALYZED;
  517. }
  518. if (pGroupTSystem->Status & 0x20) {
  519. match = LogWriter->MATCH_ERROR;
  520. }
  521. //
  522. // check if value read from database makes sense
  523. //
  524. if ((szGroupName==NULL) ||
  525. (wcscmp(szGroupName, L"")==0)) {
  526. throw new SceLogException(SceLogException::SXERROR_READ_ANALYSIS_SUGGESTED,
  527. L"szGroupName==NULL",
  528. NULL,
  529. 0);
  530. }
  531. //
  532. // log setting for Group Members with LogWriter
  533. //
  534. iTmp = wnsprintf(szTmpStringBuffer,
  535. STRING_BUFFER_SIZE,
  536. L"%s %s",
  537. szGroupName,
  538. L"(Members)");
  539. if (iTmp<0) {
  540. //
  541. // negative result from wnsprintf implies failed
  542. //
  543. throw new SceLogException(SceLogException::SXERROR_INTERNAL,
  544. L"wnsprintf(szTmpStringBuffer,...,szGroupName,...)",
  545. NULL,
  546. iTmp);
  547. }
  548. LogWriter->AddSetting(szTmpStringBuffer,
  549. szTmpStringBuffer,
  550. match,
  551. pGroupTBase->pMembers,
  552. pGroupTSystem->pMembers,
  553. SceXMLLogWriter::TYPE_DEFAULT);
  554. // determine match status for Group Member Of
  555. match = LogWriter->MATCH_TRUE;
  556. if (pGroupTSystem->Status & 0x02) {
  557. match = LogWriter->MATCH_FALSE;
  558. }
  559. if (pGroupTSystem->Status & 0x10) {
  560. match = LogWriter->MATCH_NOT_ANALYZED;
  561. }
  562. if (pGroupTSystem->Status & 0x20) {
  563. match = LogWriter->MATCH_ERROR;
  564. }
  565. // log setting for Group Member Of
  566. iTmp = wnsprintf(szTmpStringBuffer,
  567. STRING_BUFFER_SIZE,
  568. L"%s %s",
  569. szGroupName,
  570. L"(Member Of)");
  571. if (iTmp<0) {
  572. //
  573. // negative result from wnsprintf implies failed
  574. //
  575. throw new SceLogException(SceLogException::SXERROR_INTERNAL,
  576. L"wnsprintf(szTmpStringBuffer,...,szGroupName,...)",
  577. NULL,
  578. iTmp);
  579. }
  580. LogWriter->AddSetting(szTmpStringBuffer,
  581. szTmpStringBuffer,
  582. match,
  583. pGroupTBase->pMemberOf,
  584. pGroupTSystem->pMemberOf,
  585. SceXMLLogWriter::TYPE_DEFAULT);
  586. found = TRUE;
  587. }
  588. pGroupTSystem = pGroupTSystem->Next;
  589. } // while{} for system groups
  590. // There should not be any groups that are in baseline but not in SAP
  591. // It seems as though once a group is added to the SMP, then it will exist
  592. // in the SAP even if no analysis is performed -- checked with Vishnu 7/10/02
  593. pGroupTBase = pGroupTBase->Next;
  594. }
  595. // There should not be any groups in SAP but not in baseline
  596. } catch (SceLogException *e) {
  597. e->SetArea(L"GroupMembership");
  598. e->AddDebugInfo(L"SceAnalysisReader::ExportAreaGroupMembership()");
  599. throw e;
  600. } catch (...) {
  601. throw new SceLogException(SceLogException::SXERROR_INTERNAL,
  602. L"SceAnalysisReader::ExportAreaGroupMembership()",
  603. NULL,
  604. 0);
  605. }
  606. }
  607. void
  608. SceAnalysisReader::ExportAreaRegistryValues(
  609. )
  610. /*++
  611. Routine Description:
  612. Internal method to export Registry Value settings.
  613. Should only be called from within ExportAnalysis() after
  614. the necessary global variables have been initialized
  615. Arguments:
  616. none
  617. Return Value:
  618. none
  619. --*/
  620. {
  621. SceXMLLogWriter::SXMATCH_STATUS match;
  622. try {
  623. LogWriter->SetNewArea(TEXT("RegistryValues"));
  624. // For each registry value in the Baseline Profile, we attempt to
  625. // find its matching registry value in the Analysis Profile
  626. // this method of finding matching reg keys is rather inefficient,
  627. // time complexity is O(n^2) in the number of reg values
  628. // can probably do better if necessary
  629. for (DWORD i=0; i<ppSMPBuffer->RegValueCount; i++) {
  630. BOOL found = FALSE;
  631. SceXMLLogWriter::SXTYPE type;
  632. SceXMLLogWriter::SXMATCH_STATUS match;
  633. PWSTR keyName = ppSMPBuffer->aRegValues[i].FullValueName;
  634. // get reg key display name
  635. GetRegKeyDisplayName(ppSMPBuffer->aRegValues[i].FullValueName,
  636. szTmpStringBuffer,
  637. STRING_BUFFER_SIZE);
  638. //
  639. // determine reg value type
  640. //
  641. switch(ppSMPBuffer->aRegValues[i].ValueType){
  642. case REG_BINARY:
  643. type=SceXMLLogWriter::TYPE_REG_BINARY;
  644. break;
  645. case REG_DWORD:
  646. type=SceXMLLogWriter::TYPE_REG_DWORD;
  647. break;
  648. case REG_EXPAND_SZ:
  649. type=SceXMLLogWriter::TYPE_REG_EXPAND_SZ;
  650. break;
  651. case REG_MULTI_SZ:
  652. type=SceXMLLogWriter::TYPE_REG_MULTI_SZ;
  653. break;
  654. case REG_SZ:
  655. type=SceXMLLogWriter::TYPE_REG_SZ;
  656. break;
  657. }
  658. for (DWORD j=0; j<ppSAPBuffer->RegValueCount; j++) {
  659. if (_wcsicmp(keyName, ppSAPBuffer->aRegValues[j].FullValueName)==0) {
  660. //
  661. // found matching reg key
  662. //
  663. found=TRUE;
  664. // determine match status
  665. switch (ppSAPBuffer->aRegValues[j].Status) {
  666. case SCE_STATUS_GOOD:
  667. match=SceXMLLogWriter::MATCH_TRUE;
  668. break;
  669. case SCE_STATUS_MISMATCH:
  670. match=SceXMLLogWriter::MATCH_FALSE;
  671. break;
  672. case SCE_STATUS_NOT_ANALYZED:
  673. match=SceXMLLogWriter::MATCH_NOT_ANALYZED;
  674. break;
  675. default:
  676. match=SceXMLLogWriter::MATCH_ERROR;
  677. break;
  678. }
  679. // log setting
  680. LogWriter->AddSetting(keyName,
  681. szTmpStringBuffer,
  682. match,
  683. ppSMPBuffer->aRegValues[i].Value,
  684. ppSAPBuffer->aRegValues[j].Value,
  685. type);
  686. }
  687. }
  688. if (!found) {
  689. //
  690. // since reg val missing from Analysis Profile,
  691. // this actually implies a match
  692. //
  693. match = SceXMLLogWriter::MATCH_TRUE;
  694. LogWriter->AddSetting(keyName,
  695. szTmpStringBuffer,
  696. match,
  697. ppSMPBuffer->aRegValues[i].Value,
  698. ppSMPBuffer->aRegValues[i].Value,
  699. type);
  700. }
  701. }
  702. //
  703. // some other misc values that are also under the RegistryValues area
  704. //
  705. LogWriter->AddSetting(TEXT("EnableAdminAccount"),
  706. TEXT("EnableAdminAccount"),
  707. ppSMPBuffer->EnableAdminAccount,
  708. ppSAPBuffer->EnableAdminAccount,
  709. SceXMLLogWriter::TYPE_BOOLEAN);
  710. LogWriter->AddSetting(TEXT("EnableGuestAccount"),
  711. TEXT("EnableGuestAccount"),
  712. ppSMPBuffer->EnableGuestAccount,
  713. ppSAPBuffer->EnableGuestAccount,
  714. SceXMLLogWriter::TYPE_BOOLEAN);
  715. } catch (SceLogException *e) {
  716. e->SetArea(L"RegistryValues");
  717. e->AddDebugInfo(L"SceAnalysisReader::ExportAreaRegistryValues()");
  718. throw e;
  719. } catch (...) {
  720. throw new SceLogException(SceLogException::SXERROR_INTERNAL,
  721. L"SceAnalysisReader::ExportAreaRegistryValues()",
  722. NULL,
  723. 0);
  724. }
  725. }
  726. void
  727. SceAnalysisReader::ExportAreaPrivileges(
  728. )
  729. /*++
  730. Routine Description:
  731. Internal method to export Privilege settings.
  732. Should only be called from within ExportAnalysis() after
  733. the necessary global variables have been initialized
  734. Arguments:
  735. none
  736. Return Value:
  737. none
  738. --*/
  739. {
  740. SceXMLLogWriter::SXMATCH_STATUS match;
  741. try {
  742. LogWriter->SetNewArea(TEXT("PrivilegeRights"));
  743. PSCE_PRIVILEGE_ASSIGNMENT pTmpPrivBase = ppSMPBuffer->pPrivilegeAssignedTo;
  744. PSCE_PRIVILEGE_ASSIGNMENT pTmpPrivSys = ppSAPBuffer->pPrivilegeAssignedTo;
  745. //
  746. // for each privilege in the baseline profile, attempt to find its matching
  747. // privilege in the analysis profile
  748. //
  749. while (pTmpPrivBase!=NULL) {
  750. DWORD dwValue = pTmpPrivBase->Value;
  751. BOOL found = FALSE;
  752. BOOL bPrivLookupSuccess;
  753. SceXMLLogWriter::SXMATCH_STATUS match;
  754. PWSTR szPrivDescription=NULL;
  755. GetPrivilegeDisplayName(pTmpPrivBase->Name,
  756. szTmpStringBuffer,
  757. STRING_BUFFER_SIZE);
  758. //
  759. // search for matching privilege in analysis table
  760. //
  761. while (pTmpPrivSys!=NULL&&!found) {
  762. if (dwValue==pTmpPrivSys->Value) {
  763. //
  764. // Found matching privilege
  765. //
  766. // determine match status
  767. switch (pTmpPrivSys->Status) {
  768. case SCE_STATUS_GOOD:
  769. match=SceXMLLogWriter::MATCH_TRUE;
  770. break;
  771. case SCE_STATUS_MISMATCH:
  772. match=SceXMLLogWriter::MATCH_FALSE;
  773. break;
  774. case SCE_STATUS_NOT_CONFIGURED:
  775. match=SceXMLLogWriter::MATCH_NOT_CONFIGURED;
  776. break;
  777. case SCE_STATUS_NOT_ANALYZED:
  778. match=SceXMLLogWriter::MATCH_NOT_ANALYZED;
  779. break;
  780. case SCE_DELETE_VALUE:
  781. match=SceXMLLogWriter::MATCH_OTHER;
  782. break;
  783. default:
  784. match=SceXMLLogWriter::MATCH_OTHER;
  785. break;
  786. }
  787. // log setting
  788. LogWriter->AddSetting(pTmpPrivBase->Name,
  789. szTmpStringBuffer,
  790. match,
  791. pTmpPrivBase->AssignedTo,
  792. pTmpPrivSys->AssignedTo,
  793. SceXMLLogWriter::TYPE_DEFAULT);
  794. found=TRUE;
  795. }
  796. pTmpPrivSys=pTmpPrivSys->Next;
  797. }
  798. if (!found) {
  799. // since settings is absent from analysis profile,
  800. // this implies a match
  801. match=SceXMLLogWriter::MATCH_TRUE;
  802. LogWriter->AddSetting(pTmpPrivBase->Name,
  803. szTmpStringBuffer,
  804. match,
  805. pTmpPrivBase->AssignedTo,
  806. NULL,
  807. SceXMLLogWriter::TYPE_DEFAULT);
  808. }
  809. pTmpPrivBase=pTmpPrivBase->Next;
  810. pTmpPrivSys=ppSAPBuffer->pPrivilegeAssignedTo;
  811. }
  812. } catch (SceLogException *e) {
  813. e->SetArea(L"PrivilegeRights");
  814. e->AddDebugInfo(L"SceAnalysisReader::ExportAreaPrivileges()");
  815. throw e;
  816. } catch (...) {
  817. throw new SceLogException(SceLogException::SXERROR_INTERNAL,
  818. L"SceAnalysisReader::ExportAreaPrivileges()",
  819. NULL,
  820. 0);
  821. }
  822. }
  823. void
  824. SceAnalysisReader::ExportAreaKerberos(
  825. )
  826. /*++
  827. Routine Description:
  828. Internal method to export Kerberos settings.
  829. Should only be called from within ExportAnalysis() after
  830. the necessary global variables have been initialized
  831. Arguments:
  832. none
  833. Return Value:
  834. none
  835. --*/
  836. {
  837. try {
  838. // Kerberos settings will be present only if this machine is a DC
  839. if (ppSAPBuffer->pKerberosInfo!=NULL) {
  840. LogWriter->SetNewArea(TEXT("Kerberos"));
  841. LoadString(myModuleHandle,
  842. IDS_SETTING_KERBEROS_MAX_AGE,
  843. szTmpStringBuffer,
  844. STRING_BUFFER_SIZE);
  845. LogWriter->AddSetting(TEXT("MaxTicketAge"),
  846. szTmpStringBuffer,
  847. ppSAPBuffer->pKerberosInfo->MaxTicketAge,
  848. ppSMPBuffer->pKerberosInfo->MaxTicketAge,
  849. SceXMLLogWriter::TYPE_DEFAULT);
  850. LoadString(myModuleHandle,
  851. IDS_SETTING_KERBEROS_RENEWAL,
  852. szTmpStringBuffer,
  853. STRING_BUFFER_SIZE);
  854. LogWriter->AddSetting(TEXT("MaxRenewAge"),
  855. szTmpStringBuffer,
  856. ppSAPBuffer->pKerberosInfo->MaxRenewAge,
  857. ppSMPBuffer->pKerberosInfo->MaxRenewAge,
  858. SceXMLLogWriter::TYPE_DEFAULT);
  859. LoadString(myModuleHandle,
  860. IDS_SETTING_KERBEROS_MAX_SERVICE,
  861. szTmpStringBuffer,
  862. STRING_BUFFER_SIZE);
  863. LogWriter->AddSetting(TEXT("MaxServiceAge"),
  864. szTmpStringBuffer,
  865. ppSAPBuffer->pKerberosInfo->MaxServiceAge,
  866. ppSMPBuffer->pKerberosInfo->MaxServiceAge,
  867. SceXMLLogWriter::TYPE_DEFAULT);
  868. LoadString(myModuleHandle,
  869. IDS_SETTING_KERBEROS_MAX_CLOCK,
  870. szTmpStringBuffer,
  871. STRING_BUFFER_SIZE);
  872. LogWriter->AddSetting(TEXT("MaxClockSkew"),
  873. szTmpStringBuffer,
  874. ppSAPBuffer->pKerberosInfo->MaxClockSkew,
  875. ppSMPBuffer->pKerberosInfo->MaxClockSkew,
  876. SceXMLLogWriter::TYPE_DEFAULT);
  877. LoadString(myModuleHandle,
  878. IDS_SETTING_KERBEROS_VALIDATE_CLIENT,
  879. szTmpStringBuffer,
  880. STRING_BUFFER_SIZE);
  881. LogWriter->AddSetting(TEXT("TicketValidateClient"),
  882. szTmpStringBuffer,
  883. ppSAPBuffer->pKerberosInfo->TicketValidateClient,
  884. ppSMPBuffer->pKerberosInfo->TicketValidateClient,
  885. SceXMLLogWriter::TYPE_BOOLEAN);
  886. }
  887. } catch (SceLogException *e) {
  888. e->SetArea(L"Kerberos");
  889. e->AddDebugInfo(L"SceAnalysisReader::ExportAreaKerberos()");
  890. throw e;
  891. } catch (...) {
  892. throw new SceLogException(SceLogException::SXERROR_INTERNAL,
  893. L"SceAnalysisReader::ExportAreaKerberos()",
  894. NULL,
  895. 0);
  896. }
  897. }
  898. void
  899. SceAnalysisReader::ExportAreaRegistrySecurity(
  900. )
  901. /*++
  902. Routine Description:
  903. Internal method to export Registry Security settings.
  904. Should only be called from within ExportAnalysis() after
  905. the necessary global variables have been initialized
  906. Arguments:
  907. none
  908. Return Value:
  909. none
  910. --*/
  911. {
  912. SceXMLLogWriter::SXMATCH_STATUS match;
  913. SCESTATUS rc;
  914. WCHAR* FullName;
  915. try {
  916. {
  917. LogWriter->SetNewArea(TEXT("RegistrySecurity"));
  918. PSCE_OBJECT_LIST pTmpObjSys = ppSAPBuffer->pRegistryKeys.pOneLevel;
  919. while(pTmpObjSys!=NULL) {
  920. //
  921. // log settings for children of this object
  922. //
  923. if (pTmpObjSys->IsContainer) {
  924. this->LogObjectChildrenDifferences(AREA_REGISTRY_SECURITY,pTmpObjSys->Name);
  925. }
  926. //
  927. // check match status for parent object to determine whether
  928. // we need to log setting for this object
  929. //
  930. if ((pTmpObjSys->Status&SCE_STATUS_PERMISSION_MISMATCH) ||
  931. (pTmpObjSys->Status&SCE_STATUS_MISMATCH) ||
  932. (pTmpObjSys->Status==SCE_STATUS_GOOD)) {
  933. SceXMLLogWriter::SXMATCH_STATUS match;
  934. if (pTmpObjSys->Status==SCE_STATUS_GOOD){
  935. match=SceXMLLogWriter::MATCH_TRUE;
  936. } else {
  937. match=SceXMLLogWriter::MATCH_FALSE;;
  938. }
  939. // Get object security of baseline and system setting
  940. PSCE_OBJECT_SECURITY pObjSecBase = NULL;
  941. PSCE_OBJECT_SECURITY pObjSecSys = NULL;
  942. // no need trailing '\' behind object name
  943. FullName= new WCHAR[wcslen(pTmpObjSys->Name)+2];
  944. wcscpy(FullName, pTmpObjSys->Name);
  945. rc = SceGetObjectSecurity(hProfile,
  946. SceEngineSMP,
  947. AREA_REGISTRY_SECURITY,
  948. FullName,
  949. &pObjSecBase);
  950. if ((rc!=SCESTATUS_SUCCESS) &&
  951. (rc!=SCESTATUS_RECORD_NOT_FOUND)) {
  952. throw new SceLogException(SceLogException::SXERROR_INTERNAL,
  953. L"SceGetObjectSecurity()",
  954. NULL,
  955. rc);
  956. }
  957. // if match is true, object security will not exist in SAP
  958. if (match!=SceXMLLogWriter::MATCH_TRUE) rc = SceGetObjectSecurity(hProfile,
  959. SceEngineSAP,
  960. AREA_REGISTRY_SECURITY,
  961. FullName,
  962. &pObjSecSys);
  963. if ((rc!=SCESTATUS_SUCCESS) &&
  964. (rc!=SCESTATUS_RECORD_NOT_FOUND)) {
  965. throw new SceLogException(SceLogException::SXERROR_INTERNAL,
  966. L"SceGetObjectSecurity()",
  967. NULL,
  968. rc);
  969. }
  970. // Log Setting
  971. if (match==SceXMLLogWriter::MATCH_TRUE) {
  972. LogWriter->AddSetting(FullName,
  973. FullName,
  974. match,
  975. pObjSecBase,
  976. pObjSecBase,
  977. SceXMLLogWriter::TYPE_DEFAULT);
  978. } else {
  979. LogWriter->AddSetting(FullName,
  980. FullName,
  981. match,
  982. pObjSecBase,
  983. pObjSecSys,
  984. SceXMLLogWriter::TYPE_DEFAULT);
  985. }
  986. }
  987. pTmpObjSys=pTmpObjSys->Next;
  988. }
  989. }
  990. } catch (SceLogException *e) {
  991. if (NULL!=FullName) {
  992. delete (FullName);
  993. FullName=NULL;
  994. }
  995. e->SetArea(L"RegistrySecurity");
  996. e->AddDebugInfo(L"SceAnalysisReader::ExportAreaRegistrySecurity()");
  997. throw e;
  998. } catch (...) {
  999. if (NULL!=FullName) {
  1000. delete (FullName);
  1001. FullName=NULL;
  1002. }
  1003. throw new SceLogException(SceLogException::SXERROR_INTERNAL,
  1004. L"SceAnalysisReader::ExportAreaRegistrySecurity()",
  1005. NULL,
  1006. 0);
  1007. }
  1008. //
  1009. // cleanup
  1010. //
  1011. if (NULL!=FullName) {
  1012. delete (FullName);
  1013. FullName=NULL;
  1014. }
  1015. }
  1016. void
  1017. SceAnalysisReader::ExportAreaFileSecurity(
  1018. )
  1019. /*++
  1020. Routine Description:
  1021. Internal method to export File Security settings.
  1022. Should only be called from within ExportAnalysis() after
  1023. the necessary global variables have been initialized
  1024. Arguments:
  1025. none
  1026. Return Value:
  1027. none
  1028. --*/
  1029. {
  1030. SceXMLLogWriter::SXMATCH_STATUS match;
  1031. SCESTATUS rc;
  1032. WCHAR* FullName;
  1033. try {
  1034. LogWriter->SetNewArea(TEXT("FileSecurity"));
  1035. PSCE_OBJECT_LIST pTmpObjSys = ppSAPBuffer->pFiles.pOneLevel;
  1036. while(pTmpObjSys!=NULL) {
  1037. //
  1038. // log settings for children of this object
  1039. //
  1040. if (pTmpObjSys->IsContainer) {
  1041. this->LogObjectChildrenDifferences(AREA_FILE_SECURITY,pTmpObjSys->Name);
  1042. }
  1043. //
  1044. // check match status for parent object to determine whether
  1045. // we need to log setting for this object
  1046. //
  1047. if ((pTmpObjSys->Status&SCE_STATUS_PERMISSION_MISMATCH) ||
  1048. (pTmpObjSys->Status&SCE_STATUS_MISMATCH) ||
  1049. (pTmpObjSys->Status==SCE_STATUS_GOOD)) {
  1050. SceXMLLogWriter::SXMATCH_STATUS match;
  1051. if (pTmpObjSys->Status==SCE_STATUS_GOOD){
  1052. match=SceXMLLogWriter::MATCH_TRUE;
  1053. } else {
  1054. match=SceXMLLogWriter::MATCH_FALSE;;
  1055. }
  1056. // Get object security of baseline and system setting
  1057. PSCE_OBJECT_SECURITY pObjSecBase = NULL;
  1058. PSCE_OBJECT_SECURITY pObjSecSys = NULL;
  1059. // need trailing '\' behind object name
  1060. FullName= new WCHAR[wcslen(pTmpObjSys->Name)+2];
  1061. wcscpy(FullName, pTmpObjSys->Name);
  1062. wcscat(FullName, TEXT("\\"));
  1063. rc = SceGetObjectSecurity(hProfile,
  1064. SceEngineSMP,
  1065. AREA_FILE_SECURITY,
  1066. FullName,
  1067. &pObjSecBase);
  1068. if ((rc!=SCESTATUS_SUCCESS) &&
  1069. (rc!=SCESTATUS_RECORD_NOT_FOUND)) {
  1070. throw new SceLogException(SceLogException::SXERROR_INTERNAL,
  1071. L"SceGetObjectSecurity()",
  1072. NULL,
  1073. rc);
  1074. }
  1075. // if match is true, object security will not exist in SAP
  1076. if (match!=SceXMLLogWriter::MATCH_TRUE) rc = SceGetObjectSecurity(hProfile,
  1077. SceEngineSAP,
  1078. AREA_FILE_SECURITY,
  1079. FullName,
  1080. &pObjSecSys);
  1081. if ((rc!=SCESTATUS_SUCCESS) &&
  1082. (rc!=SCESTATUS_RECORD_NOT_FOUND)) {
  1083. throw new SceLogException(SceLogException::SXERROR_INTERNAL,
  1084. L"SceGetObjectSecurity()",
  1085. NULL,
  1086. rc);
  1087. }
  1088. // Log Setting
  1089. if (match==SceXMLLogWriter::MATCH_TRUE) {
  1090. LogWriter->AddSetting(FullName,
  1091. FullName,
  1092. match,
  1093. pObjSecBase,
  1094. pObjSecBase,
  1095. SceXMLLogWriter::TYPE_DEFAULT);
  1096. } else {
  1097. LogWriter->AddSetting(FullName,
  1098. FullName,
  1099. match,
  1100. pObjSecBase,
  1101. pObjSecSys,
  1102. SceXMLLogWriter::TYPE_DEFAULT);
  1103. }
  1104. }
  1105. pTmpObjSys=pTmpObjSys->Next;
  1106. }
  1107. } catch (SceLogException *e) {
  1108. if (NULL!=FullName) {
  1109. delete (FullName);
  1110. FullName=NULL;
  1111. }
  1112. e->SetArea(L"FileSecurity");
  1113. e->AddDebugInfo(L"SceAnalysisReader::ExportAreaFileSecurity()");
  1114. throw e;
  1115. } catch (...) {
  1116. if (NULL!=FullName) {
  1117. delete (FullName);
  1118. FullName=NULL;
  1119. }
  1120. throw new SceLogException(SceLogException::SXERROR_INTERNAL,
  1121. L"SceAnalysisReader::ExportAreaFileSecurity()",
  1122. NULL,
  1123. 0);
  1124. }
  1125. if (NULL!=FullName) {
  1126. delete (FullName);
  1127. FullName=NULL;
  1128. }
  1129. }
  1130. void
  1131. SceAnalysisReader::ExportAreaServices(
  1132. )
  1133. /*++
  1134. Routine Description:
  1135. Internal method to export Service settings.
  1136. Should only be called from within ExportAnalysis() after
  1137. the necessary global variables have been initialized
  1138. Arguments:
  1139. none
  1140. Return Value:
  1141. none
  1142. --*/
  1143. {
  1144. SceXMLLogWriter::SXMATCH_STATUS match;
  1145. try {
  1146. LogWriter->SetNewArea(TEXT("ServiceSecurity"));
  1147. PSCE_SERVICES pTmpServBase = ppSMPBuffer->pServices;
  1148. PSCE_SERVICES pTmpServSys = ppSAPBuffer->pServices;
  1149. while (pTmpServBase!=NULL) {
  1150. PWSTR szName = pTmpServBase->ServiceName;
  1151. BOOL found=FALSE;
  1152. SceXMLLogWriter::SXMATCH_STATUS match;
  1153. while (pTmpServSys!=NULL&&!found) {
  1154. if (_wcsicmp(szName, pTmpServSys->ServiceName)==0) {
  1155. // determine match status
  1156. if (!(pTmpServSys->SeInfo & DACL_SECURITY_INFORMATION)) {
  1157. match=SceXMLLogWriter::MATCH_NOT_CONFIGURED;
  1158. } else if (pTmpServSys->Status==0) {
  1159. match=SceXMLLogWriter::MATCH_TRUE;
  1160. } else {
  1161. match=SceXMLLogWriter::MATCH_FALSE;
  1162. }
  1163. // log setting
  1164. LogWriter->AddSetting(pTmpServBase->ServiceName,
  1165. pTmpServBase->DisplayName,
  1166. match,
  1167. pTmpServBase,
  1168. pTmpServSys,
  1169. SceXMLLogWriter::TYPE_DEFAULT);
  1170. found=TRUE;
  1171. }
  1172. pTmpServSys=pTmpServSys->Next;
  1173. }
  1174. if (!found) {
  1175. // settings match
  1176. match = SceXMLLogWriter::MATCH_TRUE;
  1177. // log setting
  1178. LogWriter->AddSetting(pTmpServBase->ServiceName,
  1179. pTmpServBase->DisplayName,
  1180. match,
  1181. pTmpServBase,
  1182. pTmpServBase,
  1183. SceXMLLogWriter::TYPE_DEFAULT);
  1184. }
  1185. pTmpServSys=ppSAPBuffer->pServices;
  1186. pTmpServBase=pTmpServBase->Next;
  1187. }
  1188. } catch (SceLogException *e) {
  1189. e->SetArea(L"ServiceSecurity");
  1190. e->AddDebugInfo(L"SceAnalysisReader::ExportAreaServiceSecurity()");
  1191. throw e;
  1192. } catch (...) {
  1193. throw new SceLogException(SceLogException::SXERROR_INTERNAL,
  1194. L"SceAnalysisReader::ExportAreaServiceSecurity()",
  1195. NULL,
  1196. 0);
  1197. }
  1198. }
  1199. void
  1200. SceAnalysisReader::GetRegKeyDisplayName(
  1201. IN PCWSTR szName,
  1202. OUT PWSTR szDisplayName,
  1203. IN DWORD dwDisplayNameSize
  1204. )
  1205. /*++
  1206. Routine Description:
  1207. Maps known registry keys to their display name
  1208. The implementation of this function is definitely far from optimal
  1209. which is potentially bad since it is called for every registry key found
  1210. in the template.This code was copied from the wssecmgr snapin.
  1211. On the other hand, practical results seem like the additional time taken
  1212. is negligible, for now. Ideally should use a hash table.
  1213. Arguments:
  1214. szName: Reg key name to lookup
  1215. dwDisplayNameSize: Size of buffer of szDisplayName in WCHARs
  1216. Return Value:
  1217. szDisplayName: display name of the reg key
  1218. --*/
  1219. {
  1220. DWORD dwSize;
  1221. UINT uID;
  1222. dwSize=dwDisplayNameSize;
  1223. // find match for reg key name
  1224. if( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Services\\NTDS\\Parameters\\LDAPServerIntegrity") == 0 ) {
  1225. uID = IDS_REGKEY_LDAPSERVERINTEGRITY;
  1226. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Services\\Netlogon\\Parameters\\SignSecureChannel") == 0 ) {
  1227. uID = IDS_REGKEY_SIGNSECURECHANNEL;
  1228. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Services\\Netlogon\\Parameters\\SealSecureChannel") == 0 ) {
  1229. uID = IDS_REGKEY_SEALSECURECHANNEL;
  1230. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Services\\Netlogon\\Parameters\\RequireStrongKey") == 0 ){
  1231. uID = IDS_REGKEY_REQUIRESTRONGKEY;
  1232. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Services\\Netlogon\\Parameters\\RequireSignOrSeal") == 0 ) {
  1233. uID = IDS_REGKEY_REQUIRESIGNORSEAL;
  1234. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Services\\Netlogon\\Parameters\\RefusePasswordChange") == 0 ){
  1235. uID = IDS_REGKEY_REFUSEPASSWORDCHANGE;
  1236. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Services\\Netlogon\\Parameters\\MaximumPasswordAge") == 0 ){
  1237. uID = IDS_REGKEY_MAXIMUMPASSWORDAGE;
  1238. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Services\\Netlogon\\Parameters\\DisablePasswordChange") == 0 ){
  1239. uID = IDS_REGKEY_DISABLEPASSWORDCHANGE;
  1240. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Services\\LDAP\\LDAPClientIntegrity") == 0 ){
  1241. uID = IDS_REGKEY_LDAPCLIENTINTEGRITY;
  1242. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters\\RequireSecuritySignature") == 0 ){
  1243. uID = IDS_REGKEY_REQUIRESECURITYSIGNATURE;
  1244. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters\\EnableSecuritySignature") == 0 ){
  1245. uID = IDS_REGKEY_ENABLESECURITYSIGNATURE;
  1246. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters\\EnablePlainTextPassword") == 0 ){
  1247. uID = IDS_REGKEY_ENABLEPLAINTEXTPASSWORD;
  1248. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Services\\LanManServer\\Parameters\\RestrictNullSessAccess") == 0 ){
  1249. uID = IDS_REGKEY_RESTRICTNULLSESSACCESS;
  1250. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Services\\LanManServer\\Parameters\\RequireSecuritySignature") == 0 ){
  1251. uID = IDS_REGKEY_SERREQUIRESECURITYSIGNATURE;
  1252. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Services\\LanManServer\\Parameters\\NullSessionShares") == 0 ){
  1253. uID = IDS_REGKEY_NULLSESSIONSHARES;
  1254. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Services\\LanManServer\\Parameters\\NullSessionPipes") == 0 ){
  1255. uID = IDS_REGKEY_NULLSESSIONPIPES;
  1256. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Services\\LanManServer\\Parameters\\EnableSecuritySignature") == 0 ){
  1257. uID = IDS_REGKEY_SERENABLESECURITYSIGNATURE;
  1258. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Services\\LanManServer\\Parameters\\EnableForcedLogOff") == 0 ){
  1259. uID = IDS_REGKEY_ENABLEFORCEDLOGOFF;
  1260. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Services\\LanManServer\\Parameters\\AutoDisconnect") == 0 ){
  1261. uID = IDS_REGKEY_AUTODISCONNECT;
  1262. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\ProtectionMode") == 0 ){
  1263. uID = IDS_REGKEY_PROTECTIONMODE;
  1264. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\Memory Management\\ClearPageFileAtShutdown") == 0 ){
  1265. uID = IDS_REGKEY_CLEARPAGEFILEATSHUTDOWN;
  1266. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\Kernel\\ObCaseInsensitive") == 0 ){
  1267. uID = IDS_REGKEY_OBCASEINSENSITIVE;
  1268. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Control\\SecurePipeServers\\Winreg\\AllowedPaths\\Machine") == 0 ){
  1269. uID = IDS_REGKEY_MACHINE;
  1270. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Control\\Print\\Providers\\LanMan Print Services\\Servers\\AddPrinterDrivers") == 0 ){
  1271. uID = IDS_REGKEY_ADDPRINTERDRIVERS;
  1272. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Control\\Lsa\\SubmitControl") == 0 ){
  1273. uID = IDS_REGKEY_SUBMITCONTROL;
  1274. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Control\\Lsa\\RestrictAnonymousSAM") == 0 ){
  1275. uID = IDS_REGKEY_RESTRICTANONYMOUSSAM;
  1276. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Control\\Lsa\\RestrictAnonymous") == 0 ){
  1277. uID = IDS_REGKEY_RESTRICTANONYMOUS;
  1278. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Control\\Lsa\\NoLMHash") == 0 ){
  1279. uID = IDS_REGKEY_NOLMHASH;
  1280. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Control\\Lsa\\NoDefaultAdminOwner") == 0 ){
  1281. uID = IDS_REGKEY_NODEFAULTADMINOWNER;
  1282. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Control\\Lsa\\MSV1_0\\NTLMMinServerSec") == 0 ){
  1283. uID = IDS_REGKEY_NTLMMINSERVERSEC;
  1284. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Control\\Lsa\\MSV1_0\\NTLMMinClientSec") == 0 ){
  1285. uID = IDS_REGKEY_NTLMMINCLIENTSEC;
  1286. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Control\\Lsa\\LmCompatibilityLevel") == 0 ){
  1287. uID = IDS_REGKEY_LMCOMPATIBILITYLEVEL;
  1288. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Control\\Lsa\\LimitBlankPasswordUse") == 0 ){
  1289. uID = IDS_REGKEY_LIMITBLANKPASSWORDUSE;
  1290. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Control\\Lsa\\FullPrivilegeAuditing") == 0 ){
  1291. uID = IDS_REGKEY_FULLPRIVILEGEAUDITING;
  1292. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Control\\Lsa\\ForceGuest") == 0 ){
  1293. uID = IDS_REGKEY_FORCEGUEST;
  1294. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Control\\Lsa\\FIPSAlgorithmPolicy") == 0 ){
  1295. uID = IDS_REGKEY_FIPSALGORITHMPOLICY;
  1296. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Control\\Lsa\\EveryoneIncludesAnonymous") == 0 ){
  1297. uID = IDS_REGKEY_EVERYONEINCLUDESANONYMOUS;
  1298. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Control\\Lsa\\DisableDomainCreds") == 0 ){
  1299. uID = IDS_REGKEY_DISABLEDOMAINCREDS;
  1300. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Control\\Lsa\\CrashOnAuditFail") == 0 ){
  1301. uID = IDS_REGKEY_CRASHONAUDITFAIL;
  1302. } else if ( _wcsicmp(szName, L"MACHINE\\System\\CurrentControlSet\\Control\\Lsa\\AuditBaseObjects") == 0 ){
  1303. uID = IDS_REGKEY_AUDITBASEOBJECTS;
  1304. } else if ( _wcsicmp(szName, L"MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\UndockWithoutLogon") == 0 ){
  1305. uID = IDS_REGKEY_UNDOCKWITHOUTLOGON;
  1306. } else if ( _wcsicmp(szName, L"MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\ShutdownWithoutLogon") == 0 ){
  1307. uID = IDS_REGKEY_SHUTDOWNWITHOUTLOGON;
  1308. } else if ( _wcsicmp(szName, L"MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\ScForceOption") == 0 ){
  1309. uID = IDS_REGKEY_SCFORCEOPTION;
  1310. } else if ( _wcsicmp(szName, L"MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\LegalNoticeText") == 0 ){
  1311. uID = IDS_REGKEY_LEGALNOTICETEXT;
  1312. } else if ( _wcsicmp(szName, L"MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\LegalNoticeCaption") == 0 ){
  1313. uID = IDS_REGKEY_LEGALNOTICECAPTION;
  1314. } else if ( _wcsicmp(szName, L"MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\DontDisplayLastUserName") == 0 ){
  1315. uID = IDS_REGKEY_DONTDISPLAYLASTUSERNAME;
  1316. } else if ( _wcsicmp(szName, L"MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\DisableCAD") == 0 ){
  1317. uID = IDS_REGKEY_DISABLECAD;
  1318. } else if ( _wcsicmp(szName, L"MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\ScRemoveOption") == 0 ){
  1319. uID = IDS_REGKEY_SCREMOVEOPTION;
  1320. } else if ( _wcsicmp(szName, L"MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\PasswordExpiryWarning") == 0 ){
  1321. uID = IDS_REGKEY_PASSWORDEXPIRYWARNING;
  1322. } else if ( _wcsicmp(szName, L"MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\ForceUnlockLogon") == 0 ){
  1323. uID = IDS_REGKEY_FORCEUNLOCKLOGON;
  1324. } else if ( _wcsicmp(szName, L"MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\CachedLogonsCount") == 0 ){
  1325. uID = IDS_REGKEY_CACHEDLOGONSCOUNT;
  1326. } else if ( _wcsicmp(szName, L"MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\AllocateFloppies") == 0 ){
  1327. uID = IDS_REGKEY_ALLOCATEFLOPPIES;
  1328. } else if ( _wcsicmp(szName, L"MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\AllocateDASD") == 0 ){
  1329. uID = IDS_REGKEY_ALLOCATEDASD;
  1330. } else if ( _wcsicmp(szName, L"MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\AllocateCDRoms") == 0 ){
  1331. uID = IDS_REGKEY_ALLOCATECDROMS;
  1332. } else if ( _wcsicmp(szName, L"MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Setup\\RecoveryConsole\\SetCommand") == 0 ){
  1333. uID = IDS_REGKEY_SETCOMMAND;
  1334. } else if ( _wcsicmp(szName, L"MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Setup\\RecoveryConsole\\SecurityLevel") == 0 ){
  1335. uID = IDS_REGKEY_SECURITYLEVEL;
  1336. } else if ( _wcsicmp(szName, L"MACHINE\\Software\\Microsoft\\Driver Signing\\Policy") == 0 ){
  1337. uID = IDS_REGKEY_REGPOLICY;
  1338. } else {
  1339. uID = IDS_REGKEY_ERROR_DETERMINE_REGNAME;
  1340. }
  1341. // load string
  1342. LoadString(myModuleHandle,
  1343. uID,
  1344. szDisplayName,
  1345. dwDisplayNameSize);
  1346. }
  1347. void
  1348. SceAnalysisReader::GetPrivilegeDisplayName(
  1349. IN PCWSTR szName,
  1350. OUT PWSTR szDisplayName,
  1351. IN DWORD dwDisplayNameSize
  1352. )
  1353. /*++
  1354. Routine Description:
  1355. Attempts to do a Lookup on the local system for privilege name
  1356. szName. If that fails, then attempts to match it to cerain known
  1357. privilege names. If this too fails, then assigns it an error string
  1358. Arguments:
  1359. szName: Privilege name to lookup
  1360. dwDisplayNameSize: Size of buffer of szDisplayName in WCHARs
  1361. Return Value:
  1362. szDisplayName: Display Name of the privilege
  1363. --*/
  1364. {
  1365. DWORD dwLanguage, dwSize;
  1366. BOOL bPrivLookupSuccess;
  1367. UINT uID;
  1368. dwSize=dwDisplayNameSize;
  1369. bPrivLookupSuccess = LookupPrivilegeDisplayName(NULL,
  1370. szName,
  1371. szDisplayName,
  1372. &dwSize,
  1373. &dwLanguage);
  1374. if(!bPrivLookupSuccess) {
  1375. // determine uID
  1376. if (_wcsicmp(szName, L"senetworklogonright")==0) {
  1377. uID=IDS_PRIVNAME_SE_NETWORK_LOGON_RIGHT;
  1378. } else if (_wcsicmp(szName, L"seinteractivelogonright")==0) {
  1379. uID=IDS_PRIVNAME_SE_INTERACTIVE_LOGON_RIGHT;
  1380. } else if (_wcsicmp(szName, L"sebatchlogonright")==0) {
  1381. uID=IDS_PRIVNAME_SE_BATCH_LOGON_RIGHT;
  1382. } else if (_wcsicmp(szName, L"seservicelogonright")==0) {
  1383. uID=IDS_PRIVNAME_SE_SERVICE_LOGON_RIGHT;
  1384. } else if (_wcsicmp(szName, L"sedenyinteractivelogonright")==0) {
  1385. uID=IDS_PRIVNAME_DENY_LOGON_LOCALLY;
  1386. } else if (_wcsicmp(szName, L"sedenynetworklogonright")==0) {
  1387. uID=IDS_PRIVNAME_DENY_LOGON_NETWORK;
  1388. } else if (_wcsicmp(szName, L"sedenyservicelogonright")==0) {
  1389. uID=IDS_PRIVNAME_DENY_LOGON_BATCH;
  1390. } else if (_wcsicmp(szName, L"sedenyremoteinteractivelogonright")==0) {
  1391. uID=IDS_PRIVNAME_DENY_REMOTE_INTERACTIVE_LOGON;
  1392. } else if (_wcsicmp(szName, L"seremoteinteractivelogonright")==0) {
  1393. uID=IDS_PRIVNAME_REMOTE_INTERACTIVE_LOGON;
  1394. } else {
  1395. uID=IDS_ERROR_DETERMINE_PRIVNAME;
  1396. }
  1397. // load string
  1398. LoadString(myModuleHandle,
  1399. uID,
  1400. szDisplayName,
  1401. dwDisplayNameSize);
  1402. }
  1403. }
  1404. void
  1405. SceAnalysisReader::LogObjectChildrenDifferences(
  1406. IN AREA_INFORMATION Area,
  1407. IN PWSTR ObjectName
  1408. )
  1409. /*++
  1410. Routine Description:
  1411. This is a recursive function that finds the children of ObjectName
  1412. and logs all objects that have a match/mismatch in the anaylsis
  1413. table
  1414. Arguments:
  1415. hProfile: The handle of the SCE database for this object
  1416. Area: The area that the object resides in, as defined in secedit.h
  1417. ObjectName: Name of object to check and log
  1418. LogWriter: The instance of LogWriter to use for logging differences
  1419. Return Value:
  1420. none
  1421. --*/
  1422. {
  1423. SCESTATUS rc;
  1424. // Find Object's Children
  1425. PSCE_OBJECT_CHILDREN pChildren=NULL;
  1426. rc = SceGetObjectChildren(hProfile,
  1427. SceEngineSAP,
  1428. Area,
  1429. ObjectName,
  1430. &pChildren,
  1431. NULL);
  1432. if (rc!=SCESTATUS_SUCCESS) {
  1433. throw new SceLogException(SceLogException::SXERROR_READ_ANALYSIS_SUGGESTED,
  1434. L"SceGetObjectChildren()",
  1435. NULL,
  1436. rc);
  1437. }
  1438. //
  1439. // cycle through the children of this object
  1440. //
  1441. PSCE_OBJECT_CHILDREN_NODE *pObjNode=&(pChildren->arrObject);
  1442. for (DWORD i=0; i<pChildren->nCount; i++) {
  1443. // construct full name of child node
  1444. // allocating memory for size of parentname, size of childname, null termination char and '\'
  1445. // hence the '+2'
  1446. WCHAR* ChildFullName= new WCHAR[(wcslen(ObjectName)+wcslen(pObjNode[i]->Name)+2)];
  1447. wcscpy(ChildFullName, ObjectName);
  1448. wcscat(ChildFullName, TEXT("\\"));
  1449. wcscat(ChildFullName, pObjNode[i]->Name);
  1450. // only need to log or recurse deeper if children configured
  1451. if (pObjNode[i]->Status&SCE_STATUS_CHILDREN_CONFIGURED) {
  1452. this->LogObjectChildrenDifferences(Area,ChildFullName);
  1453. }
  1454. // check match status to determine whether we need to log setting for this object
  1455. if ((pObjNode[i]->Status&SCE_STATUS_PERMISSION_MISMATCH) ||
  1456. (pObjNode[i]->Status&SCE_STATUS_MISMATCH) ||
  1457. (pObjNode[i]->Status==SCE_STATUS_GOOD)) {
  1458. SceXMLLogWriter::SXMATCH_STATUS match;
  1459. if (pObjNode[i]->Status==SCE_STATUS_GOOD){
  1460. match=SceXMLLogWriter::MATCH_TRUE;
  1461. } else {
  1462. match=SceXMLLogWriter::MATCH_FALSE;;
  1463. }
  1464. // Get object security of baseline and system setting
  1465. PSCE_OBJECT_SECURITY pObjSecBase = NULL;
  1466. PSCE_OBJECT_SECURITY pObjSecSys = NULL;
  1467. rc = SceGetObjectSecurity(hProfile,
  1468. SceEngineSMP,
  1469. Area,
  1470. ChildFullName,
  1471. &pObjSecBase);
  1472. if ((rc!=SCESTATUS_SUCCESS) &&
  1473. (rc!=SCESTATUS_RECORD_NOT_FOUND)) {
  1474. throw new SceLogException(SceLogException::SXERROR_INTERNAL,
  1475. L"SceGetObjectSecurity()",
  1476. NULL,
  1477. rc);
  1478. }
  1479. // if match is true, object security will not exist in SAP
  1480. if (match!=SceXMLLogWriter::MATCH_TRUE) rc = SceGetObjectSecurity(hProfile,
  1481. SceEngineSAP,
  1482. Area,
  1483. ChildFullName,
  1484. &pObjSecSys);
  1485. if ((rc!=SCESTATUS_SUCCESS)&&
  1486. (rc!=SCESTATUS_RECORD_NOT_FOUND)) {
  1487. throw new SceLogException(SceLogException::SXERROR_INTERNAL,
  1488. L"SceGetObjectSecurity()",
  1489. NULL,
  1490. rc);
  1491. }
  1492. // Log Setting
  1493. if (match==SceXMLLogWriter::MATCH_TRUE) {
  1494. LogWriter->AddSetting(ChildFullName,
  1495. ChildFullName,
  1496. match,
  1497. pObjSecBase,
  1498. pObjSecBase,
  1499. SceXMLLogWriter::TYPE_DEFAULT);
  1500. } else {
  1501. LogWriter->AddSetting(ChildFullName,
  1502. ChildFullName,
  1503. match,
  1504. pObjSecBase,
  1505. pObjSecSys,
  1506. SceXMLLogWriter::TYPE_DEFAULT);
  1507. }
  1508. }
  1509. //free(ChildFullName);
  1510. delete ChildFullName;
  1511. ChildFullName=NULL;
  1512. }
  1513. SceFreeMemory((PVOID)pChildren, SCE_STRUCT_OBJECT_CHILDREN);
  1514. }
  1515. void
  1516. SceAnalysisReader::trace(
  1517. IN PCWSTR szBuffer,
  1518. IN HANDLE hLogFile
  1519. )
  1520. /*++
  1521. Routine Description:
  1522. Internal method to trace info to an error log.
  1523. Arguments:
  1524. szBuffer: string to be added to log
  1525. hLogFile: handle of error log file
  1526. Return Value:
  1527. none
  1528. --*/
  1529. {
  1530. DWORD dwNumWritten;
  1531. if ((NULL!=hLogFile) && (NULL!=szBuffer)) {
  1532. WriteFile(hLogFile,
  1533. szBuffer,
  1534. wcslen(szBuffer)*sizeof(WCHAR),
  1535. &dwNumWritten,
  1536. NULL);
  1537. }
  1538. }
  1539. void
  1540. SceAnalysisReader::trace(
  1541. IN UINT uID,
  1542. IN HANDLE hLogFile
  1543. )
  1544. /*++
  1545. Routine Description:
  1546. Internal method to trace info to an error log.
  1547. Arguments:
  1548. uID: id of string to be added to log
  1549. hLogFile: handle of error log file
  1550. Return Value:
  1551. none
  1552. --*/
  1553. {
  1554. DWORD dwNumWritten;
  1555. if (NULL!=hLogFile) {
  1556. LoadString(myModuleHandle,
  1557. uID,
  1558. szTmpStringBuffer,
  1559. STRING_BUFFER_SIZE);
  1560. WriteFile(hLogFile,
  1561. szTmpStringBuffer,
  1562. wcslen(szTmpStringBuffer)*sizeof(WCHAR),
  1563. &dwNumWritten,
  1564. NULL);
  1565. }
  1566. }