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.

2254 lines
60 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. secedit.c
  5. Abstract:
  6. Command line tool "secedit" to configure/analyze security
  7. Author:
  8. Jin Huang (jinhuang) 7-Nov-1996
  9. --*/
  10. //
  11. // System header files
  12. //
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <windows.h>
  17. #include <string.h>
  18. #include <shlwapi.h>
  19. #include <winnlsp.h>
  20. //
  21. // CRT header files
  22. //
  23. #include <process.h>
  24. #include <wchar.h>
  25. #include <stddef.h>
  26. #include <stdlib.h>
  27. #include <stdio.h>
  28. #include <time.h>
  29. #include <limits.h>
  30. #include "secedit.h"
  31. #include "scesetup.h"
  32. #include "stringid.h"
  33. //#include <aclapi.h>
  34. #include <io.h>
  35. #include "userenv.h"
  36. #include <locale.h>
  37. #define GPT_EFS_NEW_PATH TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\GPExtensions\\{B1BE8D72-6EAC-11D2-A4EA-00C04F79F83A}")
  38. #define GPT_SCEDLL_NEW_PATH TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\GPExtensions\\{827D319E-6EAC-11D2-A4EA-00C04F79F83A}")
  39. #define SECEDITP_MAX_STRING_LENGTH 50
  40. #define SCE_ENGINE_GENERATE 1
  41. #define SCE_ENGINE_COMPILE 2
  42. #define SCE_ENGINE_REGISTER 3
  43. #define SCE_ENGINE_REFRESH 4
  44. #define SCE_ENGINE_BROWSE 5
  45. #define SCE_ENGINE_IMPORT 6
  46. #define SECEDIT_DETAIL_HELP 1
  47. #define SECEDIT_AREA_HELP 2
  48. #define SECEDIT_OVERWRITE_HELP 4
  49. #define SeceditpArgumentImport TEXT("/import")
  50. #define SeceditpArgumentConfigure TEXT("/configure")
  51. #define SeceditpArgumentAnalyze TEXT("/analyze")
  52. #define SeceditpArgumentRollback TEXT("/GenerateRollback")
  53. #define SeceditpArgumentGenerate TEXT("/export")
  54. #define SeceditpArgumentScpPath TEXT("/CFG")
  55. #define SeceditpArgumentRbkPath TEXT("/RBK")
  56. #define SeceditpArgumentSadPath TEXT("/DB")
  57. #define SeceditpArgumentArea TEXT("/areas")
  58. #define SeceditpArgumentLog TEXT("/log")
  59. #define SeceditpArgumentVerbose TEXT("/verbose")
  60. #define SeceditpArgumentQuiet TEXT("/quiet")
  61. #define SeceditpArgumentAppend TEXT("/overwrite")
  62. #define SeceditpArgumentCompile TEXT("/validate")
  63. #define SeceditpArgumentRegister TEXT("/register")
  64. #define SeceditpArgumentRefresh TEXT("/RefreshPolicy")
  65. #define SeceditpArgumentMerge TEXT("/MergedPolicy")
  66. #define SeceditpArgumentEnforce TEXT("/Enforce")
  67. #define SeceditpAreaPolicy TEXT("SECURITYPOLICY")
  68. #define SeceditpAreaUser TEXT("USER_MGMT")
  69. #define SeceditpAreaGroup TEXT("GROUP_MGMT")
  70. #define SeceditpAreaRight TEXT("USER_RIGHTS")
  71. #define SeceditpAreaDsObject TEXT("DSOBJECTS")
  72. #define SeceditpAreaRegistry TEXT("REGKEYS")
  73. #define SeceditpAreaFile TEXT("FILESTORE")
  74. #define SeceditpAreaService TEXT("SERVICES")
  75. #define SCE_LOCAL_FREE(ptr) if (ptr != NULL) LocalFree(ptr)
  76. HMODULE hMod=NULL;
  77. static DWORD dOptions=0;
  78. static HANDLE hCmdToolLogFile=INVALID_HANDLE_VALUE;
  79. static PWSTR LogFile=NULL;
  80. BOOL
  81. ScepRollbackConfirm();
  82. VOID
  83. ScepPrintHelp(DWORD nLevel);
  84. VOID
  85. ScepPrintCmdLineHelp(
  86. DWORD EngineType
  87. );
  88. WCHAR *
  89. SecEditPConvertToFullPath(
  90. WCHAR *UserFilename,
  91. DWORD *retCode
  92. );
  93. BOOL
  94. ScepCmdToolLogInit(
  95. PWSTR logname
  96. );
  97. VOID
  98. ScepCmdToolLogWrite(
  99. PWSTR pErrString
  100. );
  101. SCESTATUS
  102. ScepCmdToolLogClose(
  103. );
  104. SCESTATUS
  105. SeceditpErrOut(
  106. IN DWORD rc,
  107. IN LPTSTR buf OPTIONAL
  108. );
  109. DWORD
  110. SeceditpSceStatusToDosError(
  111. IN SCESTATUS SceStatus
  112. );
  113. BOOL CALLBACK
  114. SceCmdVerboseCallback(
  115. IN HANDLE CallbackHandle,
  116. IN AREA_INFORMATION Area,
  117. IN DWORD TotalTicks,
  118. IN DWORD CurrentTicks
  119. );
  120. DWORD
  121. pProgressRoutine(
  122. IN PWSTR StringUpdate
  123. );
  124. BOOL
  125. ScepPrintConfigureWarning();
  126. BOOL CALLBACK
  127. pBrowseCallback(
  128. IN LONG ID,
  129. IN PWSTR KeyName OPTIONAL,
  130. IN PWSTR GpoName OPTIONAL,
  131. IN PWSTR Value OPTIONAL,
  132. IN DWORD Len
  133. );
  134. #define SECEDIT_OPTION_DEBUG 0x01L
  135. #define SECEDIT_OPTION_VERBOSE 0x02L
  136. #define SECEDIT_OPTION_QUIET 0x04L
  137. #define SECEDIT_OPTION_OVERWRITE 0x08L
  138. #define SECEDIT_OPTION_MACHINE 0x10L
  139. #define SECEDIT_OPTION_MERGE 0x20L
  140. #define SECEDIT_OPTION_APPEND 0x40L
  141. #define SECEDIT_OPTION_ENFORCE 0x80L
  142. int __cdecl
  143. My_wprintf(
  144. const wchar_t *format,
  145. ...
  146. );
  147. int __cdecl
  148. My_fwprintf(
  149. FILE *str,
  150. const wchar_t *format,
  151. ...
  152. );
  153. int __cdecl
  154. My_vfwprintf(
  155. FILE *str,
  156. const wchar_t *format,
  157. va_list argptr
  158. );
  159. int __cdecl
  160. My_printf(
  161. const char *format,
  162. ...
  163. );
  164. int __cdecl wmain(int argc, WCHAR * argv[])
  165. {
  166. PWSTR InfFile=NULL;
  167. PWSTR InfRollbackFile=NULL;
  168. BOOL bAreaSpecified = FALSE;
  169. // PWSTR LogFile=NULL;
  170. PWSTR SadFile=NULL;
  171. PWSTR pTemp=NULL;
  172. AREA_INFORMATION Area=AREA_ALL;
  173. SCESTATUS rc = SCESTATUS_SUCCESS;
  174. int rCode=0;
  175. DWORD EngineType=0;
  176. LONG i;
  177. DWORD j;
  178. DWORD Len, TotalLen;
  179. BOOL bTest=FALSE;
  180. BOOL bVerbose=TRUE;
  181. BOOL bQuiet=FALSE;
  182. BOOL bAppend=TRUE;
  183. PVOID hProfile=NULL;
  184. PSCE_PROFILE_INFO ProfileInfo=NULL;
  185. PSCE_ERROR_LOG_INFO ErrBuf=NULL;
  186. PSCE_ERROR_LOG_INFO pErr;
  187. DWORD dWarning=0;
  188. WCHAR LineString[256];
  189. WCHAR WarningStr[256];
  190. BOOL bMachine=FALSE, bMerge=FALSE, bEnforce=FALSE;
  191. UINT rId=0;
  192. HKEY hKey=NULL, hKey1=NULL;
  193. UINT ConsoleCP;
  194. char szConsoleCP[6];
  195. SetThreadUILanguage(0);
  196. // check for /quiet and LogFile if any - set relevant flags (need this info immediately to log errors)
  197. for ( i=1; i<argc; i++ ){
  198. if ( _wcsicmp(argv[i], SeceditpArgumentLog ) == 0 ) {
  199. if ( i+1 < argc && argv[i+1][0] != L'/' ) {
  200. LogFile = SecEditPConvertToFullPath(argv[i+1], &rCode);
  201. if (rCode == 2) {
  202. goto Done;
  203. }
  204. } else {
  205. ScepPrintCmdLineHelp(EngineType);
  206. rCode = 1;
  207. goto Done;
  208. }
  209. i++;
  210. continue;
  211. }
  212. if ( _wcsicmp(argv[i], SeceditpArgumentQuiet ) == 0 ) {
  213. bQuiet = TRUE;
  214. dOptions |= SCE_DISABLE_LOG;
  215. }
  216. }
  217. if ( rCode == 0 )
  218. ScepCmdToolLogInit(LogFile);
  219. ConsoleCP = GetConsoleOutputCP();
  220. // szConsoleCP[0] = '.';
  221. // itoa(ConsoleCP, &szConsoleCP[1], 10);
  222. sprintf(szConsoleCP, ".%d", ConsoleCP);
  223. // setlocale(LC_ALL, ".OCP");
  224. setlocale(LC_ALL, szConsoleCP);
  225. hMod = GetModuleHandle(NULL);
  226. if ( hMod == NULL ) {
  227. My_wprintf(L"Cannot find the module handle\n");
  228. return 2; // system error
  229. }
  230. for ( i=1; i<argc; i++ )
  231. if ( _wcsicmp(argv[i], L"/?") == 0 ) {
  232. ScepPrintCmdLineHelp(EngineType);
  233. goto Done;
  234. }
  235. if ( argc < 2 ) {
  236. ScepPrintCmdLineHelp(EngineType);
  237. return 1;
  238. } else {
  239. for ( i=1; i<argc; i++ ) {
  240. SCE_LOCAL_FREE(pTemp);
  241. Len = wcslen(argv[i]);
  242. pTemp = (PWSTR)LocalAlloc( 0, (Len+1)*sizeof(WCHAR));
  243. if ( pTemp == NULL ) {
  244. My_wprintf(L"Not enough memory\n");
  245. rCode=2; //system error
  246. goto Done;
  247. }
  248. wcscpy(pTemp, argv[i]);
  249. //
  250. // configure engine type ?
  251. //
  252. if ( _wcsicmp(pTemp, SeceditpArgumentConfigure) == 0 ) {
  253. if ( EngineType != 0 ) {
  254. ScepPrintCmdLineHelp(EngineType);
  255. rCode = 1; // invalid parameter
  256. goto Done;
  257. }
  258. EngineType = SCE_ENGINE_SCP;
  259. continue;
  260. }
  261. //
  262. // analyze engine type ?
  263. //
  264. if ( _wcsicmp(pTemp, SeceditpArgumentAnalyze) == 0 ) {
  265. if ( EngineType != 0 ) {
  266. ScepPrintCmdLineHelp(EngineType);
  267. rCode = 1; //invalid parameter
  268. goto Done;
  269. }
  270. EngineType = SCE_ENGINE_SAP;
  271. continue;
  272. }
  273. //
  274. // rollback engine type ?
  275. //
  276. if ( _wcsicmp(pTemp, SeceditpArgumentRollback) == 0 ) {
  277. if ( EngineType != 0 ) {
  278. ScepPrintCmdLineHelp(EngineType);
  279. rCode = 1; //invalid parameter
  280. goto Done;
  281. }
  282. EngineType = SCE_ENGINE_RBK;
  283. continue;
  284. }
  285. //
  286. // generate template ?
  287. //
  288. if ( _wcsicmp(pTemp, SeceditpArgumentGenerate) == 0 ) {
  289. if ( EngineType != 0 ) {
  290. ScepPrintCmdLineHelp(EngineType);
  291. rCode = 1;
  292. goto Done;
  293. }
  294. EngineType = SCE_ENGINE_GENERATE;
  295. continue;
  296. }
  297. //
  298. // import template ?
  299. //
  300. if ( _wcsicmp(pTemp, SeceditpArgumentImport) == 0 ) {
  301. if ( EngineType != 0 ){
  302. ScepPrintCmdLineHelp(EngineType);
  303. rCode = 1;
  304. goto Done;
  305. }
  306. EngineType = SCE_ENGINE_IMPORT;
  307. continue;
  308. }
  309. //
  310. // compile a template ?
  311. //
  312. if ( _wcsicmp(pTemp, SeceditpArgumentCompile) == 0 ) {
  313. if ( EngineType != 0 ) {
  314. ScepPrintCmdLineHelp(EngineType);
  315. rCode = 1;
  316. goto Done;
  317. }
  318. EngineType = SCE_ENGINE_COMPILE;
  319. //
  320. // compile requires a INF template name
  321. //
  322. if ( i+1 < argc && argv[i+1][0] != L'/' ) {
  323. InfFile = SecEditPConvertToFullPath(argv[i+1], &rCode);
  324. if (rCode == 2) {
  325. goto Done;
  326. }
  327. } else {
  328. ScepPrintCmdLineHelp(EngineType);
  329. rCode = 1;
  330. goto Done;
  331. }
  332. i++;
  333. continue;
  334. }
  335. //
  336. // register a template for registry values ?
  337. //
  338. if ( _wcsicmp(pTemp, SeceditpArgumentRegister) == 0 ) {
  339. if ( EngineType != 0 ) {
  340. ScepPrintCmdLineHelp(EngineType);
  341. rCode = 1;
  342. goto Done;
  343. }
  344. EngineType = SCE_ENGINE_REGISTER;
  345. //
  346. // register requires a INF template name
  347. //
  348. if ( i+1 < argc && argv[i+1][0] != L'/' ) {
  349. InfFile = SecEditPConvertToFullPath(argv[i+1], &rCode);
  350. if (rCode == 2) {
  351. goto Done;
  352. }
  353. } else {
  354. ScepPrintCmdLineHelp(EngineType);
  355. rCode = 1;
  356. goto Done;
  357. }
  358. i++;
  359. continue;
  360. }
  361. //
  362. // refresh policy
  363. //
  364. if ( _wcsicmp(pTemp, SeceditpArgumentRefresh) == 0 ) {
  365. //
  366. // do not support refresh policy because it's supported by refgp.exe
  367. //
  368. ScepPrintCmdLineHelp(EngineType);
  369. rCode = 1;
  370. goto Done;
  371. /*
  372. if ( EngineType != 0 ) {
  373. ScepPrintHelp(EngineType);
  374. rCode = 1;
  375. goto Done;
  376. }
  377. EngineType = SCE_ENGINE_REFRESH;
  378. //
  379. // next argument is the policy area
  380. //
  381. if ( i+1 < argc && argv[i+1][0] != L'/' ) {
  382. if ( 0 == _wcsicmp(argv[i+1], L"MACHINE_POLICY") ) {
  383. bMachine = TRUE;
  384. } else if ( 0 == _wcsicmp(argv[i+1], L"USER_POLICY") ) {
  385. bMachine = FALSE;
  386. } else {
  387. ScepPrintHelp(EngineType);
  388. rCode = 1;
  389. goto Done;
  390. }
  391. } else {
  392. ScepPrintHelp(EngineType);
  393. rCode = 1;
  394. goto Done;
  395. }
  396. i++;
  397. continue;
  398. */
  399. }
  400. if ( _wcsicmp(pTemp, L"/browse") == 0 ) {
  401. if ( EngineType != 0 ) {
  402. ScepPrintCmdLineHelp(EngineType);
  403. rCode = 1;
  404. goto Done;
  405. }
  406. EngineType = SCE_ENGINE_BROWSE;
  407. //
  408. // next argument is the table
  409. //
  410. if ( i+1 < argc && argv[i+1][0] != L'/' ) {
  411. if ( 0 == _wcsicmp(argv[i+1], L"scp") ) {
  412. dWarning = SCE_ENGINE_SCP;
  413. } else if ( 0 == _wcsicmp(argv[i+1], L"smp") ) {
  414. dWarning = SCE_ENGINE_SMP;
  415. } else if ( 0 == _wcsicmp(argv[i+1], L"sap") ) {
  416. dWarning = SCE_ENGINE_SAP;
  417. } else if ( 0 == _wcsicmp(argv[i+1], L"tattoo") ) {
  418. dWarning = SCE_ENGINE_SAP;
  419. bMerge = TRUE;
  420. } else {
  421. ScepPrintCmdLineHelp(EngineType);
  422. rCode = 1;
  423. goto Done;
  424. }
  425. } else {
  426. ScepPrintCmdLineHelp(EngineType);
  427. rCode = 1;
  428. goto Done;
  429. }
  430. i++;
  431. continue;
  432. }
  433. if ( _wcsicmp(pTemp, L"/debug") == 0 ) {
  434. bTest = TRUE;
  435. continue;
  436. }
  437. if ( _wcsicmp(pTemp, SeceditpArgumentVerbose ) == 0 ) {
  438. bVerbose = TRUE;
  439. continue;
  440. }
  441. if ( _wcsicmp(pTemp, SeceditpArgumentQuiet ) == 0 ) {
  442. bQuiet = TRUE;
  443. continue;
  444. }
  445. if ( _wcsicmp(pTemp, SeceditpArgumentAppend ) == 0 ) {
  446. bAppend = FALSE;
  447. continue;
  448. }
  449. if ( _wcsicmp(pTemp, SeceditpArgumentMerge ) == 0 ) {
  450. bMerge = TRUE;
  451. continue;
  452. }
  453. if ( _wcsicmp(pTemp, SeceditpArgumentEnforce ) == 0 ) {
  454. bEnforce = TRUE;
  455. continue;
  456. }
  457. //
  458. // scp profile name, it may be empty "/scppath"
  459. //
  460. if ( _wcsicmp(pTemp, SeceditpArgumentScpPath) == 0 ) {
  461. if ( i+1 < argc && argv[i+1][0] != L'/' ) {
  462. InfFile = SecEditPConvertToFullPath(argv[i+1], &rCode);
  463. if (rCode == 2 ||
  464. ( EngineType == SCE_ENGINE_IMPORT && (NULL == InfFile || 0xFFFFFFFF == GetFileAttributes(InfFile)))) {
  465. ScepPrintCmdLineHelp(EngineType);
  466. goto Done;
  467. }
  468. } else {
  469. ScepPrintCmdLineHelp(EngineType);
  470. rCode = 1;
  471. goto Done;
  472. }
  473. i++;
  474. continue;
  475. }
  476. //
  477. // rbk profile name
  478. //
  479. if ( _wcsicmp(pTemp, SeceditpArgumentRbkPath) == 0 ) {
  480. if ( i+1 < argc && argv[i+1][0] != L'/' ) {
  481. InfRollbackFile = SecEditPConvertToFullPath(argv[i+1], &rCode);
  482. if (rCode == 2) {
  483. goto Done;
  484. }
  485. } else {
  486. ScepPrintCmdLineHelp(EngineType);
  487. rCode = 1;
  488. goto Done;
  489. }
  490. i++;
  491. continue;
  492. }
  493. //
  494. // sad database name, it may be empty
  495. //
  496. if ( _wcsicmp(pTemp, SeceditpArgumentSadPath) == 0 ) {
  497. if ( i+1 < argc && argv[i+1][0] != L'/' ) {
  498. SadFile = SecEditPConvertToFullPath(argv[i+1], &rCode);
  499. if (rCode == 2) {
  500. goto Done;
  501. }
  502. } else {
  503. ScepPrintCmdLineHelp(EngineType);
  504. rCode = 1;
  505. goto Done;
  506. }
  507. i++;
  508. continue;
  509. }
  510. //
  511. // area(s)
  512. //
  513. if ( _wcsicmp(pTemp, SeceditpArgumentArea ) == 0 ) {
  514. //
  515. //
  516. bAreaSpecified = TRUE;
  517. for ( j=(DWORD)i, Area=0; j+1 < (DWORD)argc && argv[j+1][0] != L'/'; j++ ) {
  518. SCE_LOCAL_FREE(pTemp);
  519. Len = wcslen(argv[j+1]);
  520. pTemp = (PWSTR)LocalAlloc( 0, (Len+1)*sizeof(WCHAR));
  521. if ( pTemp == NULL ) {
  522. My_wprintf(L"Not enough memory\n");
  523. rCode = 2;
  524. goto Done;
  525. }
  526. wcscpy(pTemp, argv[j+1]);
  527. //
  528. // Process all arguments for Areas
  529. //
  530. if ( _wcsicmp( pTemp, SeceditpAreaPolicy) == 0 ) {
  531. // security policy
  532. Area |= AREA_SECURITY_POLICY;
  533. continue;
  534. }
  535. /*
  536. if ( _wcsicmp( pTemp, SeceditpAreaUser) == 0 ) {
  537. // user
  538. Area |= AREA_USER_SETTINGS;
  539. continue;
  540. }
  541. */
  542. if ( _wcsicmp( pTemp, SeceditpAreaGroup) == 0 ) {
  543. // group
  544. Area |= AREA_GROUP_MEMBERSHIP;
  545. continue;
  546. }
  547. if ( _wcsicmp( pTemp, SeceditpAreaRight) == 0 ) {
  548. // privilege rights
  549. Area |= AREA_PRIVILEGES;
  550. continue;
  551. }
  552. #if 0
  553. if ( _wcsicmp( pTemp, SeceditpAreaDsObject) == 0 ) {
  554. // ds objects
  555. Area |= AREA_DS_OBJECTS;
  556. continue;
  557. }
  558. #endif
  559. if ( _wcsicmp( pTemp, SeceditpAreaRegistry) == 0 ) {
  560. // Registry
  561. Area |= AREA_REGISTRY_SECURITY;
  562. continue;
  563. }
  564. if ( _wcsicmp( pTemp, SeceditpAreaFile) == 0 ) {
  565. // file
  566. Area |= AREA_FILE_SECURITY;
  567. continue;
  568. }
  569. if ( _wcsicmp( pTemp, SeceditpAreaService) == 0 ) {
  570. // services
  571. Area |= AREA_SYSTEM_SERVICE;
  572. continue;
  573. }
  574. //
  575. // unrecognized parameter
  576. //
  577. ScepPrintCmdLineHelp(EngineType);
  578. rCode = 1;
  579. goto Done;
  580. }
  581. i = (LONG)j;
  582. continue;
  583. }
  584. //
  585. // ignore if "/log filename" since already processed at the beginning
  586. //
  587. if ( _wcsicmp(pTemp, SeceditpArgumentLog ) == 0 ) {
  588. if ( i+1 < argc && argv[i+1][0] != L'/' ) {
  589. } else {
  590. ScepPrintCmdLineHelp(EngineType);
  591. rCode = 1;
  592. goto Done;
  593. }
  594. i++;
  595. continue;
  596. }
  597. //
  598. // unrecognized argument
  599. //
  600. ScepPrintCmdLineHelp(EngineType);
  601. rCode = 1;
  602. goto Done;
  603. }
  604. }
  605. if ( EngineType == 0 ) {
  606. ScepPrintCmdLineHelp(EngineType);
  607. rCode = 1;
  608. goto Done;
  609. }
  610. SetConsoleCtrlHandler(NULL, TRUE);
  611. //
  612. // Initialize
  613. //
  614. if ( bTest ) {
  615. dOptions |= SCE_DEBUG_LOG;
  616. } else if ( bVerbose ) {
  617. dOptions |= SCE_VERBOSE_LOG;
  618. }
  619. switch ( EngineType ) {
  620. case SCE_ENGINE_SCP:
  621. //
  622. // configure the system
  623. //
  624. if ( (SadFile == NULL) ||
  625. SceIsSystemDatabase(SadFile) ) {
  626. rc = SCESTATUS_INVALID_PARAMETER;
  627. ScepPrintCmdLineHelp(EngineType);
  628. EngineType = 0;
  629. } else {
  630. bMachine = TRUE;
  631. if ( bAppend && InfFile != NULL ) {
  632. dOptions |= SCE_UPDATE_DB;
  633. } else {
  634. dOptions |= SCE_OVERWRITE_DB;
  635. if ( FALSE == bAppend && InfFile != NULL && !bQuiet ) {
  636. //
  637. // will overwrite the database with the new inf file.
  638. // warn users for this serious problem.
  639. // If this is a normal user logon, the operation will fail
  640. // by the server site.
  641. //
  642. bMachine = ScepPrintConfigureWarning(); // temp. use of bMachine
  643. }
  644. }
  645. if ( bMachine ) {
  646. rc = SceConfigureSystem(
  647. NULL,
  648. InfFile,
  649. SadFile,
  650. LogFile,
  651. dOptions,
  652. Area,
  653. (bVerbose || bTest ) ?
  654. (PSCE_AREA_CALLBACK_ROUTINE)SceCmdVerboseCallback : NULL,
  655. NULL,
  656. &dWarning
  657. );
  658. } else {
  659. rc = SCESTATUS_SUCCESS;
  660. dWarning = ERROR_REQUEST_ABORTED;
  661. goto Done;
  662. }
  663. }
  664. break;
  665. case SCE_ENGINE_SAP:
  666. //
  667. // analyze the system
  668. //
  669. if ( !bTest )
  670. Area = AREA_ALL;
  671. // if ( bAppend && InfFile != NULL ) {
  672. // dOptions |= SCE_UPDATE_DB;
  673. // } else {
  674. // dOptions |= SCE_OVERWRITE_DB;
  675. // }
  676. dOptions |= SCE_OVERWRITE_DB;
  677. // if ( InfFile == NULL || SadFile != NULL ) {
  678. if ( (SadFile != NULL) &&
  679. !SceIsSystemDatabase(SadFile) ) {
  680. rc = SceAnalyzeSystem(
  681. NULL,
  682. InfFile,
  683. SadFile,
  684. LogFile,
  685. dOptions,
  686. Area,
  687. (bVerbose || bTest ) ?
  688. (PSCE_AREA_CALLBACK_ROUTINE)SceCmdVerboseCallback : NULL,
  689. NULL,
  690. &dWarning
  691. );
  692. } else {
  693. rc = SCESTATUS_INVALID_PARAMETER;
  694. ScepPrintCmdLineHelp(EngineType);
  695. EngineType = 0;
  696. }
  697. break;
  698. case SCE_ENGINE_RBK:
  699. //
  700. // generate a rollback template
  701. //
  702. if (bAreaSpecified) {
  703. AREA_INFORMATION AreaInvalid = Area &
  704. ~AREA_SECURITY_POLICY &
  705. ~AREA_GROUP_MEMBERSHIP &
  706. ~AREA_PRIVILEGES &
  707. ~AREA_SYSTEM_SERVICE;
  708. if (AreaInvalid) {
  709. //
  710. // the UI should handle this error
  711. //
  712. ScepPrintCmdLineHelp(EngineType);
  713. rCode = 1;
  714. goto Done;
  715. }
  716. }
  717. if (InfFile == NULL ||
  718. InfRollbackFile == NULL ||
  719. (0 == _wcsicmp(InfFile, InfRollbackFile))) {
  720. ScepPrintCmdLineHelp(EngineType);
  721. rCode = 1;
  722. goto Done;
  723. }
  724. if (!bQuiet && !ScepRollbackConfirm()){
  725. rc = SCESTATUS_SUCCESS;
  726. dWarning = ERROR_REQUEST_ABORTED;
  727. goto Done;
  728. }
  729. //
  730. // indicate that rollback is going to be generated
  731. //
  732. LoadString( hMod,
  733. SECEDITP_ROLLBACK_INFORMATION,
  734. LineString,
  735. 256
  736. );
  737. My_wprintf(LineString);
  738. rc = SceGenerateRollback(NULL,
  739. InfFile,
  740. InfRollbackFile,
  741. LogFile,
  742. dOptions,
  743. Area,
  744. &dWarning
  745. );
  746. break;
  747. case SCE_ENGINE_GENERATE:
  748. if ( InfFile != NULL ) {
  749. //
  750. // must have a inf file name
  751. //
  752. if ( SadFile == NULL && !bMerge) {
  753. //
  754. // export local policy from the system database (by admin)
  755. // need to call system query APIs directly
  756. //
  757. rc = SceGetSecurityProfileInfo(NULL,
  758. SCE_ENGINE_SYSTEM,
  759. Area,
  760. &ProfileInfo,
  761. NULL
  762. );
  763. if ( SCESTATUS_SUCCESS == rc ) {
  764. //
  765. // write it to the inf file
  766. //
  767. rc = SceWriteSecurityProfileInfo(InfFile,
  768. Area,
  769. ProfileInfo,
  770. NULL
  771. );
  772. }
  773. //
  774. // free memory
  775. //
  776. if ( ProfileInfo ) {
  777. SceFreeProfileMemory(ProfileInfo);
  778. ProfileInfo = NULL;
  779. }
  780. } else {
  781. rc = SceSetupGenerateTemplate(NULL,
  782. SadFile,
  783. bMerge,
  784. InfFile,
  785. LogFile,
  786. Area);
  787. }
  788. if (ERROR_NOT_ENOUGH_MEMORY == rc ||
  789. ERROR_SERVICE_ALREADY_RUNNING == rc ) {
  790. rCode = 2;
  791. } else if ( rc ) {
  792. rCode = 1;
  793. }
  794. } else {
  795. rCode = 1;
  796. ScepPrintCmdLineHelp(EngineType);
  797. goto Done;
  798. }
  799. break;
  800. case SCE_ENGINE_BROWSE:
  801. //
  802. // must have a inf file name
  803. //
  804. if ( Area == 0 ) {
  805. Area = AREA_ALL;
  806. }
  807. rc = SceBrowseDatabaseTable(SadFile,
  808. (SCETYPE)dWarning,
  809. Area,
  810. bMerge,
  811. (PSCE_BROWSE_CALLBACK_ROUTINE)pBrowseCallback
  812. );
  813. dWarning = 0; // reset the value
  814. if (ERROR_NOT_ENOUGH_MEMORY == rc ||
  815. ERROR_SERVICE_ALREADY_RUNNING == rc ) {
  816. rCode = 2;
  817. } else if ( rc ) {
  818. rCode = 1;
  819. }
  820. break;
  821. case SCE_ENGINE_COMPILE:
  822. rc = 0;
  823. if ( InfFile != NULL ) {
  824. //
  825. // must have a inf file name
  826. //
  827. rc = SceOpenProfile(InfFile,
  828. SCE_INF_FORMAT,
  829. &hProfile);
  830. if ( rc == SCESTATUS_SUCCESS && hProfile ) {
  831. //
  832. // get profile info will parse the template first
  833. //
  834. rc = SceGetSecurityProfileInfo(hProfile,
  835. SCE_ENGINE_SCP,
  836. AREA_ALL,
  837. &ProfileInfo,
  838. &ErrBuf);
  839. if ( SCESTATUS_SUCCESS == rc && ErrBuf ) {
  840. //
  841. // this is a new version template
  842. //
  843. LoadString( hMod,
  844. SECEDITP_TEMPLATE_NEWVERSION,
  845. LineString,
  846. 256
  847. );
  848. SeceditpErrOut(0, LineString);
  849. rc = SCESTATUS_INVALID_DATA;
  850. }
  851. for ( pErr=ErrBuf; pErr != NULL; pErr = pErr->next ) {
  852. if ( pErr->buffer != NULL ) {
  853. SeceditpErrOut( pErr->rc, pErr->buffer );
  854. }
  855. }
  856. SceFreeMemory((PVOID)ErrBuf, SCE_STRUCT_ERROR_LOG_INFO);
  857. ErrBuf = NULL;
  858. if ( ProfileInfo != NULL ) {
  859. SceFreeMemory((PVOID)ProfileInfo, Area);
  860. LocalFree(ProfileInfo);
  861. }
  862. SceCloseProfile(&hProfile);
  863. } else {
  864. if (SCESTATUS_OTHER_ERROR == rc) {
  865. LoadString( hMod,
  866. SECEDITP_FILE_MAY_CORRUPTED,
  867. LineString,
  868. 256
  869. );
  870. }
  871. else {
  872. LoadString( hMod,
  873. SECEDITP_CANNOT_FIND_TEMPLATE,
  874. LineString,
  875. 256
  876. );
  877. }
  878. SeceditpErrOut(SeceditpSceStatusToDosError(rc),
  879. LineString);
  880. }
  881. if (SCESTATUS_NOT_ENOUGH_RESOURCE == rc ||
  882. SCESTATUS_ALREADY_RUNNING == rc ) {
  883. rCode = 2;
  884. } else if ( rc ) {
  885. rCode = 1;
  886. }
  887. } else {
  888. rCode = 1;
  889. ScepPrintCmdLineHelp(EngineType);
  890. goto Done;
  891. }
  892. if ( SCESTATUS_SUCCESS == rc && InfFile) {
  893. LoadString( hMod,
  894. SECEDITP_COMPILE_OK,
  895. LineString,
  896. 256
  897. );
  898. My_wprintf(LineString, InfFile);
  899. }
  900. break;
  901. case SCE_ENGINE_REGISTER:
  902. rc = 0;
  903. if ( InfFile != NULL ) {
  904. rc = SceRegisterRegValues(InfFile);
  905. if (ERROR_NOT_ENOUGH_MEMORY == rc ) {
  906. rCode = 2;
  907. } else if ( rc ) {
  908. rCode = 1;
  909. }
  910. } else {
  911. rCode = 1;
  912. ScepPrintCmdLineHelp(EngineType);
  913. goto Done;
  914. }
  915. if ( SCESTATUS_SUCCESS == rc && InfFile) {
  916. LoadString( hMod,
  917. SECEDITP_REGISTER_OK,
  918. LineString,
  919. 256
  920. );
  921. My_wprintf(LineString, InfFile);
  922. }
  923. break;
  924. case SCE_ENGINE_REFRESH:
  925. break;
  926. case SCE_ENGINE_IMPORT:
  927. if (InfFile && SadFile) {
  928. if ( FALSE == bAppend && !bQuiet ) {
  929. //
  930. // will overwrite the database with the new inf file.
  931. // warn users for this serious problem.
  932. // If this is a normal user logon, the operation will fail
  933. // by the server site.
  934. //
  935. ScepPrintConfigureWarning(); // temp. use of bMachine
  936. }
  937. if ( bAppend ) {
  938. dOptions |= SCE_UPDATE_DB;
  939. } else {
  940. dOptions |= SCE_OVERWRITE_DB;
  941. }
  942. if (Area == 0) {
  943. Area = AREA_ALL;
  944. }
  945. rc = SceConfigureSystem(NULL,
  946. InfFile,
  947. SadFile,
  948. NULL,
  949. ((dOptions & SCE_UPDATE_DB) ? SCE_UPDATE_DB : SCE_OVERWRITE_DB)
  950. | SCE_NO_CONFIG | SCE_VERBOSE_LOG,
  951. Area,
  952. (bVerbose || bTest ) ? (PSCE_AREA_CALLBACK_ROUTINE)SceCmdVerboseCallback : NULL,
  953. NULL,
  954. &dWarning
  955. );
  956. if (ERROR_NOT_ENOUGH_MEMORY == rc ||
  957. ERROR_SERVICE_ALREADY_RUNNING == rc ) {
  958. rCode = 2;
  959. } else if ( rc ) {
  960. rCode = 1;
  961. }
  962. } else {
  963. rCode = 1;
  964. ScepPrintCmdLineHelp(EngineType);
  965. goto Done;
  966. }
  967. break;
  968. default:
  969. rc = 0;
  970. rCode = 1;
  971. ScepPrintCmdLineHelp(EngineType);
  972. break;
  973. }
  974. SetConsoleCtrlHandler(NULL, FALSE);
  975. if ( EngineType == SCE_ENGINE_SCP ||
  976. EngineType == SCE_ENGINE_SAP ||
  977. EngineType == SCE_ENGINE_GENERATE ||
  978. EngineType == SCE_ENGINE_BROWSE ||
  979. EngineType == SCE_ENGINE_RBK) {
  980. My_wprintf(L" \n");
  981. if ( SCESTATUS_SUCCESS == rc ) {
  982. if ( ERROR_SUCCESS == dWarning ) {
  983. rId = SECEDITP_TASK_COMPLETE_NO_ERROR;
  984. } else {
  985. // SeceditpErrOut( dWarning, NULL);
  986. rId = SECEDITP_TASK_COMPLETE_WARNING;
  987. }
  988. } else {
  989. SeceditpErrOut( SeceditpSceStatusToDosError(rc), NULL);
  990. rId = SECEDITP_TASK_COMPLETE_ERROR;
  991. }
  992. LoadString( hMod,
  993. rId,
  994. LineString,
  995. 256
  996. );
  997. if ( rId == SECEDITP_TASK_COMPLETE_WARNING ) {
  998. //
  999. // explain the warnings
  1000. //
  1001. WarningStr[0] = L'\0';
  1002. switch ( dWarning ) {
  1003. case ERROR_FILE_NOT_FOUND:
  1004. case ERROR_PATH_NOT_FOUND:
  1005. LoadString( hMod,
  1006. SECEDITP_WARNING_NOT_FOUND,
  1007. WarningStr,
  1008. 256
  1009. );
  1010. break;
  1011. case ERROR_SHARING_VIOLATION:
  1012. LoadString( hMod,
  1013. SECEDITP_WARNING_IN_USE,
  1014. WarningStr,
  1015. 256
  1016. );
  1017. break;
  1018. default:
  1019. LoadString( hMod,
  1020. SECEDITP_WARNING_OTHER_WARNING,
  1021. WarningStr,
  1022. 256
  1023. );
  1024. break;
  1025. }
  1026. My_wprintf(LineString, WarningStr);
  1027. } else {
  1028. My_wprintf(LineString);
  1029. }
  1030. if (bQuiet == FALSE) {
  1031. if ( LogFile ) {
  1032. LoadString( hMod,
  1033. SECEDITP_TASK_SEE_LOG,
  1034. LineString,
  1035. 256
  1036. );
  1037. My_wprintf(LineString, LogFile);
  1038. } else {
  1039. LoadString( hMod,
  1040. SECEDITP_TASK_SEE_DEF_LOG,
  1041. LineString,
  1042. 256
  1043. );
  1044. My_wprintf(L"%s", LineString);
  1045. }
  1046. }
  1047. }
  1048. Done:
  1049. if ( dOptions & SCE_DISABLE_LOG ){
  1050. ScepCmdToolLogClose();
  1051. }
  1052. SCE_LOCAL_FREE(InfFile);
  1053. SCE_LOCAL_FREE(SadFile);
  1054. SCE_LOCAL_FREE(LogFile);
  1055. SCE_LOCAL_FREE(pTemp);
  1056. SCE_LOCAL_FREE(InfRollbackFile);
  1057. FreeLibrary( hMod );
  1058. if ( rCode )
  1059. return rCode;
  1060. else if ( rc ) {
  1061. if (SCESTATUS_NOT_ENOUGH_RESOURCE == rc ||
  1062. SCESTATUS_ALREADY_RUNNING == rc )
  1063. return 2;
  1064. else
  1065. return 1;
  1066. } else if ( dWarning ) {
  1067. return 3;
  1068. } else
  1069. return 0;
  1070. }
  1071. VOID
  1072. ScepPrintCmdLineHelp(
  1073. DWORD EngineType
  1074. )
  1075. {
  1076. PWSTR pszLineString = NULL;
  1077. DWORD dwErrorId = SECEDITP_SIMPLE_HELP;
  1078. switch(EngineType){
  1079. case SCE_ENGINE_SCP:
  1080. dwErrorId = SECEDITP_CONFIGURE_HELP;
  1081. break;
  1082. case SCE_ENGINE_SAP:
  1083. dwErrorId = SECEDITP_ANALYZE_HELP;
  1084. break;
  1085. case SCE_ENGINE_RBK:
  1086. dwErrorId = SECEDITP_ROLLBACK_HELP;
  1087. break;
  1088. case SCE_ENGINE_GENERATE:
  1089. dwErrorId = SECEDITP_GENERATE_HELP;
  1090. break;
  1091. case SCE_ENGINE_COMPILE:
  1092. dwErrorId = SECEDITP_VALIDATE_HELP;
  1093. break;
  1094. case SCE_ENGINE_REGISTER:
  1095. dwErrorId = SECEDITP_REGISTER_HELP;
  1096. break;
  1097. case SCE_ENGINE_BROWSE:
  1098. dwErrorId = SECEDITP_BROWSE_HELP;
  1099. break;
  1100. case SCE_ENGINE_IMPORT:
  1101. dwErrorId = SECEDITP_IMPORT_HELP;
  1102. break;
  1103. default:
  1104. dwErrorId = SECEDITP_SIMPLE_HELP;
  1105. }
  1106. pszLineString = (PWSTR) LocalAlloc (LMEM_ZEROINIT, 3072*(sizeof(WCHAR)));
  1107. if (pszLineString){
  1108. LoadString( hMod,
  1109. dwErrorId,
  1110. pszLineString,
  1111. 3072
  1112. );
  1113. My_wprintf(pszLineString);
  1114. LocalFree(pszLineString);
  1115. }
  1116. return;
  1117. }
  1118. /*
  1119. VOID
  1120. ScepPrintHelp(DWORD nLevel)
  1121. {
  1122. PROCESS_INFORMATION ProcInfo;
  1123. STARTUPINFOA StartInfo;
  1124. BOOL fOk;
  1125. RtlZeroMemory(&StartInfo,sizeof(StartInfo));
  1126. StartInfo.cb = sizeof(StartInfo);
  1127. StartInfo.dwFlags = STARTF_USESHOWWINDOW;
  1128. StartInfo.wShowWindow = (WORD)SW_SHOWNORMAL;
  1129. fOk = CreateProcessA(NULL, "hh secedit.chm",
  1130. NULL, NULL, FALSE,
  1131. 0,
  1132. NULL,
  1133. NULL,
  1134. &StartInfo,
  1135. &ProcInfo
  1136. );
  1137. if ( fOk ) {
  1138. CloseHandle(ProcInfo.hProcess);
  1139. CloseHandle(ProcInfo.hThread);
  1140. }
  1141. }
  1142. */
  1143. SCESTATUS
  1144. SeceditpErrOut(
  1145. IN DWORD rc,
  1146. IN LPTSTR buf OPTIONAL
  1147. )
  1148. {
  1149. LPVOID lpMsgBuf=NULL;
  1150. if (ERROR_SPECIAL_ACCOUNT == rc) {
  1151. //
  1152. // map to this error since normal user is disallowed from using SCE
  1153. //
  1154. rc = ERROR_PRIVILEGE_NOT_HELD;
  1155. }
  1156. if ( rc != NO_ERROR ) {
  1157. //
  1158. // get error description of rc
  1159. //
  1160. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  1161. NULL,
  1162. rc,
  1163. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  1164. (LPTSTR)&lpMsgBuf,
  1165. 0,
  1166. NULL
  1167. );
  1168. }
  1169. //
  1170. // Display to screen
  1171. //
  1172. if ( buf ) {
  1173. if (lpMsgBuf != NULL )
  1174. My_fwprintf( stdout, L"%s %s\n", (PWSTR)lpMsgBuf, buf );
  1175. else
  1176. My_fwprintf( stdout, L"%s\n", buf );
  1177. } else {
  1178. if (lpMsgBuf != NULL )
  1179. My_fwprintf( stdout, L"%s\n", (PWSTR)lpMsgBuf);
  1180. }
  1181. SCE_LOCAL_FREE(lpMsgBuf);
  1182. return(SCESTATUS_SUCCESS);
  1183. }
  1184. DWORD
  1185. SeceditpSceStatusToDosError(
  1186. IN SCESTATUS SceStatus
  1187. )
  1188. // converts SCESTATUS error code to dos error defined in winerror.h
  1189. {
  1190. switch(SceStatus) {
  1191. case SCESTATUS_SUCCESS:
  1192. return(NO_ERROR);
  1193. case SCESTATUS_OTHER_ERROR:
  1194. return(ERROR_EXTENDED_ERROR);
  1195. case SCESTATUS_INVALID_PARAMETER:
  1196. return(ERROR_INVALID_PARAMETER);
  1197. case SCESTATUS_RECORD_NOT_FOUND:
  1198. return(ERROR_NO_MORE_ITEMS);
  1199. case SCESTATUS_NO_MAPPING:
  1200. return(ERROR_NONE_MAPPED);
  1201. case SCESTATUS_TRUST_FAIL:
  1202. return(ERROR_TRUSTED_DOMAIN_FAILURE);
  1203. case SCESTATUS_INVALID_DATA:
  1204. return(ERROR_INVALID_DATA);
  1205. case SCESTATUS_OBJECT_EXIST:
  1206. return(ERROR_FILE_EXISTS);
  1207. case SCESTATUS_BUFFER_TOO_SMALL:
  1208. return(ERROR_INSUFFICIENT_BUFFER);
  1209. case SCESTATUS_PROFILE_NOT_FOUND:
  1210. return(ERROR_FILE_NOT_FOUND);
  1211. case SCESTATUS_BAD_FORMAT:
  1212. return(ERROR_BAD_FORMAT);
  1213. case SCESTATUS_NOT_ENOUGH_RESOURCE:
  1214. return(ERROR_NOT_ENOUGH_MEMORY);
  1215. case SCESTATUS_ACCESS_DENIED:
  1216. return(ERROR_ACCESS_DENIED);
  1217. case SCESTATUS_CANT_DELETE:
  1218. return(ERROR_CURRENT_DIRECTORY);
  1219. case SCESTATUS_PREFIX_OVERFLOW:
  1220. return(ERROR_BUFFER_OVERFLOW);
  1221. case SCESTATUS_ALREADY_RUNNING:
  1222. return(ERROR_SERVICE_ALREADY_RUNNING);
  1223. case SCESTATUS_SERVICE_NOT_SUPPORT:
  1224. return(ERROR_NOT_SUPPORTED);
  1225. case SCESTATUS_MOD_NOT_FOUND:
  1226. return(ERROR_MOD_NOT_FOUND);
  1227. case SCESTATUS_EXCEPTION_IN_SERVER:
  1228. return(ERROR_EXCEPTION_IN_SERVICE);
  1229. case SCESTATUS_JET_DATABASE_ERROR:
  1230. return(ERROR_DATABASE_FAILURE);
  1231. case SCESTATUS_TIMEOUT:
  1232. return(ERROR_TIMEOUT);
  1233. case SCESTATUS_PENDING_IGNORE:
  1234. return(ERROR_IO_PENDING);
  1235. case SCESTATUS_SPECIAL_ACCOUNT:
  1236. return(ERROR_SPECIAL_ACCOUNT);
  1237. default:
  1238. return(ERROR_EXTENDED_ERROR);
  1239. }
  1240. }
  1241. BOOL CALLBACK
  1242. SceCmdVerboseCallback(
  1243. IN HANDLE CallbackHandle,
  1244. IN AREA_INFORMATION Area,
  1245. IN DWORD TotalTicks,
  1246. IN DWORD CurrentTicks
  1247. )
  1248. {
  1249. LPCTSTR SectionName;
  1250. DWORD nProg;
  1251. WCHAR LineString[256];
  1252. switch ( Area ) {
  1253. case AREA_SECURITY_POLICY:
  1254. SectionName = NULL;
  1255. break;
  1256. case AREA_PRIVILEGES:
  1257. SectionName = szPrivilegeRights;
  1258. break;
  1259. case AREA_GROUP_MEMBERSHIP:
  1260. SectionName = szGroupMembership;
  1261. break;
  1262. case AREA_FILE_SECURITY:
  1263. SectionName = szFileSecurity;
  1264. break;
  1265. case AREA_REGISTRY_SECURITY:
  1266. SectionName = szRegistryKeys;
  1267. break;
  1268. case AREA_DS_OBJECTS:
  1269. SectionName = szDSSecurity;
  1270. break;
  1271. case AREA_SYSTEM_SERVICE:
  1272. SectionName = NULL;
  1273. break;
  1274. default:
  1275. SectionName = NULL;
  1276. break;
  1277. }
  1278. if ( TotalTicks ) {
  1279. nProg = (CurrentTicks+1)*100/TotalTicks;
  1280. if ( nProg > 100 ) {
  1281. nProg = 100;
  1282. }
  1283. } else {
  1284. nProg = 0;
  1285. }
  1286. if ( SectionName ) {
  1287. LoadString( hMod,
  1288. SECEDITP_WITH_SECTIONNAME,
  1289. LineString,
  1290. 256
  1291. );
  1292. My_wprintf(LineString, nProg, CurrentTicks, TotalTicks, SectionName);
  1293. } else if ( Area == AREA_SECURITY_POLICY ) {
  1294. LoadString( hMod,
  1295. SECEDITP_SICURITY_POLICY,
  1296. LineString,
  1297. 256
  1298. );
  1299. My_wprintf(LineString, nProg, CurrentTicks, TotalTicks);
  1300. } else if ( Area == AREA_SYSTEM_SERVICE ) {
  1301. LoadString( hMod,
  1302. SECEDITP_SYSTEM_SERVICE,
  1303. LineString,
  1304. 256
  1305. );
  1306. My_wprintf(LineString, nProg, CurrentTicks, TotalTicks);
  1307. } else {
  1308. LoadString( hMod,
  1309. SECEDITP_NO_SECTIONNAME,
  1310. LineString,
  1311. 256
  1312. );
  1313. My_wprintf(LineString, nProg, CurrentTicks, TotalTicks);
  1314. }
  1315. return TRUE;
  1316. }
  1317. DWORD
  1318. pProgressRoutine(
  1319. IN PWSTR StringUpdate
  1320. )
  1321. {
  1322. if ( StringUpdate ) {
  1323. My_wprintf(L"Process %s\n", StringUpdate);
  1324. }
  1325. return 0;
  1326. }
  1327. BOOL
  1328. ScepPrintConfigureWarning()
  1329. {
  1330. WCHAR LineString[256];
  1331. WCHAR wch;
  1332. LoadString( hMod,
  1333. SECEDITP_CONFIG_WARNING_LINE1,
  1334. LineString,
  1335. 256
  1336. );
  1337. My_wprintf(LineString);
  1338. LoadString( hMod,
  1339. SECEDITP_CONFIG_WARNING_LINE2,
  1340. LineString,
  1341. 256
  1342. );
  1343. My_wprintf(LineString);
  1344. LoadString( hMod,
  1345. SECEDITP_CONFIG_WARNING_LINE3,
  1346. LineString,
  1347. 256
  1348. );
  1349. My_wprintf(LineString);
  1350. //
  1351. // get user input
  1352. //
  1353. LoadString( hMod,
  1354. SECEDITP_CONFIG_WARNING_CONFIRM,
  1355. LineString,
  1356. 256
  1357. );
  1358. My_wprintf(LineString);
  1359. wch = getwc(stdin);
  1360. getwc(stdin);
  1361. //
  1362. // load string for Yes
  1363. //
  1364. LineString[0] = L'\0';
  1365. LoadString( hMod,
  1366. SECEDITP_IDS_YES,
  1367. LineString,
  1368. 256
  1369. );
  1370. if ( towlower(wch) == towlower(LineString[0]) ) {
  1371. return(TRUE);
  1372. } else {
  1373. return(FALSE);
  1374. }
  1375. }
  1376. BOOL
  1377. ScepRollbackConfirm()
  1378. {
  1379. WCHAR LineString[256];
  1380. WCHAR wch;
  1381. LoadString( hMod,
  1382. SECEDITP_ROLLBACK_MSG,
  1383. LineString,
  1384. 256
  1385. );
  1386. My_wprintf(LineString);
  1387. //
  1388. // get user input
  1389. //
  1390. LoadString( hMod,
  1391. SECEDITP_CONFIG_WARNING_CONFIRM,
  1392. LineString,
  1393. 256
  1394. );
  1395. My_wprintf(LineString);
  1396. wch = getwc(stdin);
  1397. getwc(stdin);
  1398. //
  1399. // load string for Yes
  1400. //
  1401. LineString[0] = L'\0';
  1402. LoadString( hMod,
  1403. SECEDITP_IDS_YES,
  1404. LineString,
  1405. 256
  1406. );
  1407. if ( towlower(wch) == towlower(LineString[0]) ) {
  1408. return(TRUE);
  1409. } else {
  1410. return(FALSE);
  1411. }
  1412. }
  1413. BOOL CALLBACK
  1414. pBrowseCallback(
  1415. IN LONG ID,
  1416. IN PWSTR KeyName OPTIONAL,
  1417. IN PWSTR GpoName OPTIONAL,
  1418. IN PWSTR Value OPTIONAL,
  1419. IN DWORD Len
  1420. )
  1421. {
  1422. BYTE *pb=NULL;
  1423. My_wprintf(L"\n");
  1424. if ( ID > 0 ) {
  1425. My_printf("%d\t", ID);
  1426. }
  1427. if (GpoName ) {
  1428. My_wprintf(L"%s ", GpoName);
  1429. }
  1430. if ( KeyName ) {
  1431. My_wprintf(L"%s", KeyName);
  1432. if ( Value && Len > 0 ) {
  1433. if ( Len > 30 ) {
  1434. My_wprintf(L"\n");
  1435. } else {
  1436. My_wprintf(L"\t");
  1437. }
  1438. if ( iswprint(Value[0]) ) {
  1439. My_wprintf(L"%c%s\n", Value[0], (Len>1) ? Value+1 : L"");
  1440. } else {
  1441. pb = (BYTE *)Value;
  1442. My_wprintf(L"%d %d ", pb[1], pb[0]);
  1443. /*
  1444. if ( isprint( pc[0] ) ) {
  1445. My_printf("%c ", pc[0] );
  1446. } else {
  1447. My_printf("%d ", (int)(pc[0]) );
  1448. }
  1449. if ( isprint( pc[1] ) ) {
  1450. My_printf("%c ", pc[1] );
  1451. } else {
  1452. My_printf("%d ", (int)pc[1] );
  1453. }
  1454. */
  1455. if ( Len > 1 && Value[1] != L'\0' ) {
  1456. My_wprintf(L"%s\n", Value+1);
  1457. } else {
  1458. My_wprintf(L"No value\n");
  1459. }
  1460. }
  1461. } else {
  1462. My_wprintf(L"\n");
  1463. }
  1464. } else {
  1465. My_wprintf(L"\n");
  1466. }
  1467. return(TRUE);
  1468. }
  1469. /***
  1470. * My_wprintf(format) - print formatted data
  1471. *
  1472. * Prints Unicode formatted string to console window using WriteConsoleW.
  1473. * Note: This My_wprintf() is used to workaround the problem in c-runtime
  1474. * which looks up LC_CTYPE even for Unicode string.
  1475. *
  1476. */
  1477. int __cdecl
  1478. My_wprintf(
  1479. const wchar_t *format,
  1480. ...
  1481. )
  1482. {
  1483. DWORD cchWChar = 0;
  1484. DWORD dwBytesWritten;
  1485. va_list args;
  1486. va_start( args, format );
  1487. cchWChar = My_vfwprintf(stdout, format, args);
  1488. va_end(args);
  1489. return cchWChar;
  1490. }
  1491. /***
  1492. * My_fwprintf(stream, format) - print formatted data
  1493. *
  1494. * Prints Unicode formatted string to console window using WriteConsoleW.
  1495. * Note: This My_fwprintf() is used to workaround the problem in c-runtime
  1496. * which looks up LC_CTYPE even for Unicode string.
  1497. *
  1498. */
  1499. int __cdecl
  1500. My_fwprintf(
  1501. FILE *str,
  1502. const wchar_t *format,
  1503. ...
  1504. )
  1505. {
  1506. DWORD cchWChar = 0;
  1507. va_list args;
  1508. va_start( args, format );
  1509. cchWChar = My_vfwprintf(str, format, args);
  1510. va_end(args);
  1511. return cchWChar;
  1512. }
  1513. int __cdecl
  1514. My_vfwprintf(
  1515. FILE *str,
  1516. const wchar_t *format,
  1517. va_list argptr
  1518. )
  1519. {
  1520. HANDLE hOut;
  1521. // if the /quiet option is specified, suppress printing to stdout
  1522. // and instead print to the logfile. If logfile not specified
  1523. // don't print at all
  1524. if (dOptions & SCE_DISABLE_LOG){
  1525. DWORD cchWChar = 0;
  1526. LPTSTR szBufferMessage = (LPTSTR) LocalAlloc (LPTR, 4096 * sizeof(TCHAR));
  1527. if (szBufferMessage) {
  1528. vswprintf( szBufferMessage, format, argptr );
  1529. cchWChar = wcslen(szBufferMessage);
  1530. // remove trailing LFs
  1531. if (szBufferMessage[cchWChar-1] == L'\n')
  1532. szBufferMessage[cchWChar-1] = L'\0';
  1533. // remove leading LFs
  1534. if (szBufferMessage[0] == L'\n')
  1535. szBufferMessage[0] = L' ';
  1536. ScepCmdToolLogWrite(szBufferMessage);
  1537. SCE_LOCAL_FREE(szBufferMessage);
  1538. }
  1539. return cchWChar;
  1540. }
  1541. if (str == stderr) {
  1542. hOut = GetStdHandle(STD_ERROR_HANDLE);
  1543. }
  1544. else {
  1545. hOut = GetStdHandle(STD_OUTPUT_HANDLE);
  1546. }
  1547. if ((GetFileType(hOut) & ~FILE_TYPE_REMOTE) == FILE_TYPE_CHAR) {
  1548. DWORD cchWChar = 0;
  1549. LPTSTR szBufferMessage = (LPTSTR) LocalAlloc (LPTR, 4096 * sizeof(TCHAR));
  1550. if (szBufferMessage) {
  1551. vswprintf( szBufferMessage, format, argptr );
  1552. cchWChar = wcslen(szBufferMessage);
  1553. WriteConsoleW(hOut, szBufferMessage, cchWChar, &cchWChar, NULL);
  1554. SCE_LOCAL_FREE(szBufferMessage);
  1555. }
  1556. return cchWChar;
  1557. }
  1558. return vfwprintf(str, format, argptr);
  1559. }
  1560. ///////////////////////////////////////////////////////////////////////////////
  1561. // This function is to suppress printf if the /quiet option is specified
  1562. ///////////////////////////////////////////////////////////////////////////////
  1563. int __cdecl
  1564. My_printf(
  1565. const char *format,
  1566. ...
  1567. )
  1568. {
  1569. int cchChar = 0;
  1570. va_list argptr;
  1571. va_start( argptr, format );
  1572. cchChar = vprintf(format, argptr);
  1573. va_end(argptr);
  1574. return cchChar;
  1575. }
  1576. ///////////////////////////////////////////////////////////////////////////////
  1577. // This function takes the user string that is supplied at the command line
  1578. // and converts it into full path names for eg. it takes ..\%windir%\hisecws.inf
  1579. // and converts it to C:\winnt\security\templates\hisecws.inf
  1580. ///////////////////////////////////////////////////////////////////////////////
  1581. WCHAR *
  1582. SecEditPConvertToFullPath(
  1583. WCHAR *pUserFilename,
  1584. DWORD *pRetCode
  1585. )
  1586. {
  1587. BOOL NeedCurrDirFlag = TRUE;
  1588. SCESTATUS rc;
  1589. DWORD Len;
  1590. DWORD LenCurrDir;
  1591. PWSTR pCurrentDir = NULL;
  1592. PWSTR pAbsolutePath = NULL;
  1593. PWSTR pAbsolutePathDirOnly = NULL;
  1594. PWSTR pToMerge = NULL;
  1595. PWSTR pLastSlash = NULL;
  1596. WCHAR FirstThree[4];
  1597. WCHAR LineString[256];
  1598. if (pUserFilename == NULL) {
  1599. *pRetCode = 2;
  1600. goto ScePathConvertFuncError;
  1601. }
  1602. // PathIsRoot() works only if exact strings
  1603. // such as C:\ are passed - so need to extract
  1604. wcsncpy(FirstThree, pUserFilename, 3);
  1605. FirstThree[3] = L'\0';
  1606. // if pUserFilename C:\ etc. then we do not need the current directory -
  1607. // Note: extraction hack not needed if PathIsRoot() worked as published
  1608. NeedCurrDirFlag = !PathIsRoot(FirstThree);
  1609. if (NeedCurrDirFlag){
  1610. LenCurrDir = GetCurrentDirectory(0, NULL);
  1611. pCurrentDir = (PWSTR)LocalAlloc(LMEM_ZEROINIT, (LenCurrDir+1)*sizeof(WCHAR));
  1612. if ( pCurrentDir == NULL ) {
  1613. rc = GetLastError();
  1614. LoadString( hMod,
  1615. SECEDITP_OUT_OF_MEMORY,
  1616. LineString,
  1617. 256
  1618. );
  1619. SeceditpErrOut(rc, LineString );
  1620. *pRetCode = 2;
  1621. goto ScePathConvertFuncError;
  1622. }
  1623. GetCurrentDirectory(LenCurrDir, pCurrentDir);
  1624. if (pCurrentDir[LenCurrDir - 2] != L'\\')
  1625. wcscat(pCurrentDir, L"\\");
  1626. }
  1627. // allocate space for string that holds the to-be-expanded string
  1628. Len = wcslen(pUserFilename);
  1629. if (NeedCurrDirFlag)
  1630. Len += LenCurrDir;
  1631. pToMerge = (PWSTR)LocalAlloc(LMEM_ZEROINIT, (Len+1)*sizeof(WCHAR));
  1632. if ( pToMerge == NULL ) {
  1633. rc = GetLastError();
  1634. LoadString( hMod,
  1635. SECEDITP_OUT_OF_MEMORY,
  1636. LineString,
  1637. 256
  1638. );
  1639. SeceditpErrOut(rc, LineString );
  1640. *pRetCode = 2;
  1641. goto ScePathConvertFuncError;
  1642. }
  1643. if (NeedCurrDirFlag)
  1644. wcscat(pToMerge, pCurrentDir);
  1645. wcscat(pToMerge, pUserFilename);
  1646. // allocate space for string that holds the final full path - can't be > wcslen(pToMerge)
  1647. #ifdef DBG
  1648. // shlwapi is lame on chk builds and verifies that the dest buffer is MAX_PATH
  1649. pAbsolutePath = (PWSTR)LocalAlloc(LMEM_ZEROINIT, MAX_PATH*sizeof(WCHAR));
  1650. #else
  1651. pAbsolutePath = (PWSTR)LocalAlloc(LMEM_ZEROINIT, (Len+1)*sizeof(WCHAR));
  1652. #endif
  1653. if ( pAbsolutePath == NULL ) {
  1654. rc = GetLastError();
  1655. LoadString( hMod,
  1656. SECEDITP_OUT_OF_MEMORY,
  1657. LineString,
  1658. 256
  1659. );
  1660. SeceditpErrOut(rc, LineString );
  1661. *pRetCode = 2;
  1662. goto ScePathConvertFuncError;
  1663. }
  1664. // canonicalize pToMerge i.e. collapse all ..\, .\ and merge
  1665. if (PathCanonicalize(pAbsolutePath, pToMerge) == FALSE){
  1666. LoadString( hMod,
  1667. SECEDITP_PATH_NOT_CANONICALIZABLE,
  1668. LineString,
  1669. 256
  1670. );
  1671. My_wprintf(LineString);
  1672. SCE_LOCAL_FREE(pAbsolutePath);
  1673. *pRetCode = 2;
  1674. goto ScePathConvertFuncError;
  1675. }
  1676. // allocate string to verify validity of directory
  1677. pAbsolutePathDirOnly = (PWSTR)LocalAlloc(LMEM_ZEROINIT, ((wcslen(pAbsolutePath)+1)*sizeof(WCHAR)));
  1678. if ( pAbsolutePathDirOnly == NULL ) {
  1679. rc = GetLastError();
  1680. LoadString( hMod,
  1681. SECEDITP_OUT_OF_MEMORY,
  1682. LineString,
  1683. 256
  1684. );
  1685. SeceditpErrOut(rc, LineString );
  1686. SCE_LOCAL_FREE(pAbsolutePath);
  1687. *pRetCode = 2;
  1688. goto ScePathConvertFuncError;
  1689. }
  1690. // prepare pAbsolutePathDirOnly to have directory part only
  1691. wcscpy(pAbsolutePathDirOnly, pAbsolutePath);
  1692. pLastSlash = wcsrchr(pAbsolutePathDirOnly, L'\\');
  1693. if (pLastSlash)
  1694. *pLastSlash = L'\0';
  1695. if (PathIsDirectory(pAbsolutePathDirOnly) == FALSE){
  1696. LoadString( hMod,
  1697. SECEDITP_PATH_NOT_VALID,
  1698. LineString,
  1699. 256
  1700. );
  1701. My_wprintf(L"\n%s - %s\n", LineString, pAbsolutePathDirOnly);
  1702. SCE_LOCAL_FREE(pAbsolutePath);
  1703. *pRetCode = 2;
  1704. goto ScePathConvertFuncError;
  1705. }
  1706. ScePathConvertFuncError:
  1707. SCE_LOCAL_FREE(pCurrentDir);
  1708. SCE_LOCAL_FREE(pToMerge);
  1709. SCE_LOCAL_FREE(pAbsolutePathDirOnly);
  1710. return pAbsolutePath;
  1711. }
  1712. ///////////////////////////////////////////////////////////////////////////////
  1713. // This function opens the log file specified and saves the name and its handle
  1714. // in global variables
  1715. ///////////////////////////////////////////////////////////////////////////////
  1716. BOOL
  1717. ScepCmdToolLogInit(
  1718. PWSTR logname
  1719. )
  1720. {
  1721. DWORD rc=NO_ERROR;
  1722. if ( logname && wcslen(logname) > 3 ) {
  1723. hCmdToolLogFile = CreateFile(logname,
  1724. GENERIC_WRITE,
  1725. FILE_SHARE_READ,
  1726. NULL,
  1727. OPEN_ALWAYS,
  1728. FILE_ATTRIBUTE_NORMAL,
  1729. NULL);
  1730. if ( INVALID_HANDLE_VALUE != hCmdToolLogFile ) {
  1731. DWORD dwBytesWritten;
  1732. CHAR TmpBuf[3];
  1733. SetFilePointer (hCmdToolLogFile, 0, NULL, FILE_BEGIN);
  1734. TmpBuf[0] = (CHAR)0xFF;
  1735. TmpBuf[1] = (CHAR)0xFE;
  1736. TmpBuf[2] = '\0';
  1737. WriteFile (hCmdToolLogFile, (LPCVOID)TmpBuf, 2,
  1738. &dwBytesWritten,
  1739. NULL);
  1740. SetFilePointer (hCmdToolLogFile, 0, NULL, FILE_END);
  1741. }
  1742. } else {
  1743. hCmdToolLogFile = INVALID_HANDLE_VALUE;
  1744. }
  1745. if ( hCmdToolLogFile == INVALID_HANDLE_VALUE && (logname != NULL ) ) {
  1746. rc = ERROR_INVALID_NAME;
  1747. }
  1748. if ( INVALID_HANDLE_VALUE != hCmdToolLogFile ) {
  1749. CloseHandle( hCmdToolLogFile );
  1750. }
  1751. hCmdToolLogFile = INVALID_HANDLE_VALUE;
  1752. return(rc);
  1753. }
  1754. VOID
  1755. ScepCmdToolLogWrite(
  1756. PWSTR pErrString
  1757. )
  1758. {
  1759. DWORD cchWChar;
  1760. const TCHAR c_szCRLF[] = TEXT("\r\n");
  1761. if ( LogFile && wcslen(LogFile) > 3 ) {
  1762. hCmdToolLogFile = CreateFile(LogFile,
  1763. GENERIC_WRITE,
  1764. FILE_SHARE_READ,
  1765. NULL,
  1766. OPEN_ALWAYS,
  1767. FILE_ATTRIBUTE_NORMAL,
  1768. NULL);
  1769. if ( INVALID_HANDLE_VALUE != hCmdToolLogFile ) {
  1770. SetFilePointer (hCmdToolLogFile, 0, NULL, FILE_END);
  1771. cchWChar = wcslen( pErrString );
  1772. WriteFile(hCmdToolLogFile,
  1773. (LPCVOID)pErrString,
  1774. sizeof(WCHAR) * cchWChar,
  1775. &cchWChar,
  1776. NULL);
  1777. WriteFile (hCmdToolLogFile, (LPCVOID) c_szCRLF,
  1778. 2 * sizeof(WCHAR),
  1779. &cchWChar,
  1780. NULL);
  1781. // SetFilePointer (hCmdToolLogFile, 0, NULL, FILE_END);
  1782. CloseHandle( hCmdToolLogFile );
  1783. hCmdToolLogFile = INVALID_HANDLE_VALUE;
  1784. return;
  1785. }
  1786. }
  1787. }
  1788. ///////////////////////////////////////////////////////////////////////////////
  1789. // This function closes the log file if there is one opened and
  1790. // clears the log variables
  1791. ///////////////////////////////////////////////////////////////////////////////
  1792. SCESTATUS
  1793. ScepCmdToolLogClose()
  1794. {
  1795. if ( INVALID_HANDLE_VALUE != hCmdToolLogFile ) {
  1796. CloseHandle( hCmdToolLogFile );
  1797. }
  1798. hCmdToolLogFile = INVALID_HANDLE_VALUE;
  1799. return(SCESTATUS_SUCCESS);
  1800. }