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.

1409 lines
46 KiB

  1. //+------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1995, Microsoft Corporation.
  4. //
  5. // File: t2.cxx
  6. //
  7. // Contents:
  8. //
  9. // Classes:
  10. //
  11. // History: Nov-93 DaveMont Created.
  12. //
  13. //-------------------------------------------------------------------
  14. #include <t2.hxx>
  15. #include <filesec.hxx>
  16. #include <fileenum.hxx>
  17. #include <dumpsec.hxx>
  18. #include "caclsmsg.h"
  19. #include <locale.h>
  20. #include <string.h>
  21. #include <winnlsp.h>
  22. #include <tchar.h>
  23. #if DBG
  24. ULONG Debug;
  25. #endif
  26. //+----------------------------------------------------------------------------
  27. //
  28. // local prototypes
  29. //
  30. //+----------------------------------------------------------------------------
  31. BOOLEAN OpenToken(PHANDLE ph);
  32. void printfsid(SID *psid, ULONG *outputoffset);
  33. void printface(ACE_HEADER *paceh, BOOL fdir, ULONG outputoffset);
  34. void printfmask(ULONG mask, UCHAR acetype, BOOL fdir, ULONG outputoffset);
  35. WCHAR *mbstowcs(char *aname );
  36. BOOL GetUserAndAccess(TCHAR *arg, WCHAR **user, ULONG *access);
  37. #if DBG
  38. ULONG DebugEnumerate(TCHAR *filename, ULONG option);
  39. #endif
  40. ULONG DisplayAces(TCHAR *filename, ULONG option);
  41. ULONG ModifyAces(TCHAR *filename,
  42. MODE emode,
  43. ULONG option,
  44. TCHAR *argv[],
  45. LONG astart[], LONG aend[] );
  46. ULONG GetCmdLineArgs(INT argc, TCHAR *argv[],
  47. ULONG *option,
  48. LONG astart[], LONG aend[],
  49. MODE *emode
  50. #if DBG
  51. ,ULONG *debug
  52. #endif
  53. );
  54. ULONG
  55. __cdecl
  56. printmessage (FILE* fp, DWORD messageID, ...);
  57. //+----------------------------------------------------------------------------
  58. //
  59. // Function: vfcprintf
  60. //
  61. // Synopsis: prints formatted text to [pOut]. This function will call the
  62. // defulat c printf functions if it can not call WriteConsole().
  63. // We are calling WriteConsole() because it will display extended
  64. // characters, were as fprintf, printf ..., functions do not display
  65. // multi linguel strings.
  66. //
  67. // Arguments: [pOut] - Must be stdout, stderr, otherwise the function will just
  68. // call standard c functions.
  69. // [pszFormate] - Format string
  70. // [argList] - variable length argument list.
  71. //
  72. //----------------------------------------------------------------------------
  73. void vfcprintf(FILE *pOut, LPCTSTR pszFormat, va_list argList)
  74. {
  75. HANDLE handle;
  76. //
  77. // Get the standard handles for output. This assumes that the callers is calling with
  78. // either stdout or stderr, if it's anything else then just use normal sprintf.
  79. //
  80. TCHAR szText[2048];
  81. if(pOut == stdout){
  82. handle = GetStdHandle(STD_OUTPUT_HANDLE);
  83. } else if(pOut == stderr ){
  84. handle = GetStdHandle(STD_ERROR_HANDLE);
  85. } else {
  86. do_normal:
  87. #if defined(_UNICODE) || defined(UNICODE)
  88. vswprintf( szText, pszFormat, argList );
  89. fwprintf(pOut, szText );
  90. #else
  91. vsprintf( szText, pszFormat, argList );
  92. fprintf(pOut, szText );
  93. #endif
  94. return;
  95. }
  96. //
  97. // If we can't get the output handle then just send it to standard fprintf functions
  98. //
  99. if(INVALID_HANDLE_VALUE == handle){
  100. goto do_normal;
  101. }
  102. //
  103. // Format the text using standard C functions.
  104. //
  105. #if defined(_UNICODE) || defined(UNICODE)
  106. vswprintf( szText, pszFormat, argList );
  107. #else
  108. vsprintf( szText, pszFormat, argList );
  109. #endif
  110. DWORD cRead = 0;
  111. //
  112. // If we can't get the console mode from this handle, then it is being piped somewhere else
  113. // and we must use sprintf to write, because WriteConsole only works with a console
  114. // output handle.
  115. //
  116. if(!GetConsoleMode( handle, &cRead ))
  117. {
  118. DWORD cchBuffer = lstrlen(szText);
  119. LPSTR lpAnsiBuffer = (LPSTR) LocalAlloc(LMEM_FIXED, (cchBuffer+1)*sizeof(WCHAR));
  120. if (lpAnsiBuffer != NULL)
  121. {
  122. cchBuffer = WideCharToMultiByte(CP_OEMCP,
  123. 0,
  124. szText,
  125. cchBuffer + 1,
  126. lpAnsiBuffer,
  127. (cchBuffer +1) * sizeof(WCHAR),
  128. NULL,
  129. NULL);
  130. if (cchBuffer != 0)
  131. {
  132. fprintf(pOut,"%s",lpAnsiBuffer);
  133. }
  134. LocalFree(lpAnsiBuffer);
  135. }
  136. } else {
  137. WriteConsole( handle, szText, lstrlen(szText), &cRead, NULL);
  138. }
  139. }
  140. //+----------------------------------------------------------------------------
  141. //
  142. // Function: fcprintf
  143. //
  144. // synopsis: Same as fprintf, except this will call vfcprintf, which
  145. // prints to the console use WriteConsole.
  146. //
  147. // Arguments: [pOut] - FILE stream to output to.
  148. // [pszFormate] - Format string
  149. // [...] - variable length argument list.
  150. //
  151. //----------------------------------------------------------------------------
  152. void
  153. __cdecl
  154. fcprintf( FILE *pOut, LPCTSTR pszFormat, ...)
  155. {
  156. va_list marker;
  157. va_start(marker, pszFormat);
  158. vfcprintf( pOut, pszFormat, marker);
  159. va_end(marker);
  160. }
  161. //+----------------------------------------------------------------------------
  162. //
  163. // Function: fcprintf
  164. //
  165. // synopsis: Same as printf, except this will call vfcprintf, which
  166. // prints to the console use WriteConsole.
  167. //
  168. // Arguments: [pszFormate] - Format string
  169. // [...] - variable length argument list.
  170. //
  171. //----------------------------------------------------------------------------
  172. void
  173. __cdecl
  174. cprintf( LPCTSTR pszFormat, ...)
  175. {
  176. va_list marker;
  177. va_start(marker, pszFormat);
  178. vfcprintf( stdout, pszFormat, marker);
  179. va_end(marker);
  180. }
  181. //+----------------------------------------------------------------------------
  182. //
  183. // Function: Usage
  184. //
  185. // Synopsis: prints usage functionality
  186. //
  187. // Arguments: none
  188. //
  189. //----------------------------------------------------------------------------
  190. VOID usage()
  191. {
  192. printmessage(stdout, MSG_CACLS_USAGE, NULL);
  193. #if DBG
  194. if (Debug)
  195. {
  196. printf("\n /B deBug <[#]>\n");
  197. printf(" default is display error returned\n");
  198. printf(" in /B '#' is a mask: 1 display SIDS values\n");
  199. printf(" 2 display access masks\n");
  200. printf(" 4 display error returned\n");
  201. printf(" 8 display error location\n");
  202. printf(" 0x10 verbose\n");
  203. printf(" 0x20 verboser\n");
  204. printf(" 0x40 enumerate names\n");
  205. printf(" 0x80 enumerate failures\n");
  206. printf(" 0x100 enumerate starts and returns\n");
  207. printf(" 0x200 enumerate extra data\n");
  208. printf(" 0x400 size allocation data\n");
  209. printf(" 0x800 display enumeration of files\n");
  210. }
  211. #endif
  212. }
  213. BOOL
  214. IsAclSupported(LPCWSTR lpszFileName)
  215. {
  216. BOOL bReturn = TRUE;
  217. WCHAR szVolumePathName[MAX_PATH+1];
  218. if(GetVolumePathName(lpszFileName,
  219. szVolumePathName,
  220. MAX_PATH))
  221. {
  222. int nLen = wcslen(szVolumePathName);
  223. if((WCHAR)szVolumePathName[nLen -1] != L'\\')
  224. {
  225. szVolumePathName[nLen] = L'\\';
  226. szVolumePathName[nLen++] = L'\0';
  227. }
  228. DWORD dwFlags = 0;
  229. if(GetVolumeInformation(szVolumePathName,
  230. NULL,
  231. NULL,
  232. NULL,
  233. NULL,
  234. &dwFlags,
  235. NULL,
  236. 0))
  237. {
  238. if(!(FS_PERSISTENT_ACLS & dwFlags))
  239. {
  240. printmessage(stdout,MSG_CACLS_NOT_NTFS);
  241. return FALSE;
  242. }
  243. }
  244. }
  245. return bReturn;
  246. }
  247. //+----------------------------------------------------------------------------
  248. //
  249. // Function: Main, Public
  250. //
  251. // Synopsis: main!!
  252. //
  253. // Arguments: IN [argc] - cmdline arguement count
  254. // IN [argv] - input cmdline arguements
  255. //
  256. //----------------------------------------------------------------------------
  257. #if defined( __cplusplus )
  258. extern "C" {
  259. #endif
  260. VOID _cdecl wmain(int argc, wchar_t *argvw[])
  261. {
  262. char lBuf[6];
  263. //
  264. // Set the local to system OEM code page.
  265. //
  266. setlocale(LC_ALL, ".OCP" );
  267. SetThreadUILanguage(0);
  268. //
  269. // Convert the wide character set to string array.
  270. //
  271. LONG astart[MAX_OPTIONS], aend[MAX_OPTIONS];
  272. MODE emode;
  273. LONG ret = 0;
  274. ULONG option;
  275. if (ERROR_SUCCESS != (ret = GetCmdLineArgs(argc, argvw,
  276. &option,
  277. astart, aend,
  278. &emode
  279. #if DBG
  280. ,&Debug
  281. #endif
  282. )))
  283. {
  284. usage();
  285. exit(ret);
  286. }
  287. if(!IsAclSupported(argvw[1]))
  288. exit(1);
  289. switch (emode)
  290. {
  291. case MODE_DISPLAY:
  292. ret = DisplayAces(argvw[1], option);
  293. break;
  294. case MODE_REPLACE:
  295. case MODE_MODIFY:
  296. ret = ModifyAces(argvw[1], emode, option, argvw, astart, aend );
  297. break;
  298. #if DBG
  299. case MODE_DEBUG_ENUMERATE:
  300. ret = DebugEnumerate(argvw[1], option);
  301. break;
  302. #endif
  303. default:
  304. {
  305. usage();
  306. exit(1);
  307. }
  308. }
  309. if (ERROR_SUCCESS != ret)
  310. {
  311. LAST_ERROR((stderr, "Cacls failed, %ld\n",ret))
  312. if( ret == ERROR_BAD_ARGUMENTS )
  313. ret = MSG_CACLS_INVALID_ARGUMENT;
  314. printmessage(stderr, ret, NULL);
  315. if( ret == MSG_CACLS_INVALID_ARGUMENT )
  316. usage();
  317. }
  318. exit(ret);
  319. }
  320. #if defined( __cplusplus )
  321. }
  322. #endif
  323. //---------------------------------------------------------------------------
  324. //
  325. // Function: GetCmdLineArgs
  326. //
  327. // Synopsis: gets and parses command line arguments into commands
  328. // recognized by this program
  329. //
  330. // Arguments: IN [argc] - cmdline arguement count
  331. // IN [argv] - input cmdline arguements
  332. // OUT [option] - requested option
  333. // OUT [astart] - start of arguments for each option
  334. // OUT [aend] - end of arguments for each option
  335. // OUT [emode] - mode of operation
  336. // OUT [debug] - debug mask
  337. //
  338. //
  339. //----------------------------------------------------------------------------
  340. ULONG GetCmdLineArgs(INT argc, TCHAR *argv[],
  341. ULONG *option,
  342. LONG astart[], LONG aend[],
  343. MODE *emode
  344. #if DBG
  345. ,ULONG *debug
  346. #endif
  347. )
  348. {
  349. ARG_MODE_INDEX am = ARG_MODE_INDEX_NEED_OPTION;
  350. #if DBG
  351. *debug = 0;
  352. #endif
  353. *emode = MODE_DISPLAY;
  354. *option = 0;
  355. for (LONG j=0; j < MAX_OPTIONS ;j++ )
  356. {
  357. astart[j] = 0;
  358. aend[j] = 0;
  359. }
  360. if ( (argc < 2) || (argv[1][0] == '/') )
  361. {
  362. #if DBG
  363. // do this so debug args are printed out
  364. if (argc >= 2)
  365. {
  366. if ( (CompareString(LOCALE_INVARIANT,NORM_IGNORECASE,
  367. &argv[1][1], -1, TEXT("deBug"),-1) == CSTR_EQUAL) ||
  368. (CompareString(LOCALE_INVARIANT,NORM_IGNORECASE,
  369. &argv[1][1], -1, TEXT("b"),-1) == CSTR_EQUAL))
  370. {
  371. *debug = DEBUG_LAST_ERROR;
  372. }
  373. }
  374. #endif
  375. return(ERROR_BAD_ARGUMENTS);
  376. }
  377. for (LONG k = 2; k < argc ; k++ )
  378. {
  379. if (argv[k][0] == '/')
  380. {
  381. switch (am)
  382. {
  383. case ARG_MODE_INDEX_NEED_OPTION:
  384. #if DBG
  385. case ARG_MODE_INDEX_DEBUG:
  386. #endif
  387. break;
  388. case ARG_MODE_INDEX_DENY:
  389. case ARG_MODE_INDEX_REVOKE:
  390. case ARG_MODE_INDEX_GRANT:
  391. case ARG_MODE_INDEX_REPLACE:
  392. if (astart[am] == k)
  393. return(ERROR_BAD_ARGUMENTS);
  394. break;
  395. default:
  396. return(ERROR_BAD_ARGUMENTS);
  397. }
  398. if ( (0 == lstrcmpi(&argv[k][1], TEXT("Tree"))) ||
  399. (0 == lstrcmpi(&argv[k][1], TEXT("t"))) )
  400. {
  401. if (*option & OPTION_TREE)
  402. return(ERROR_BAD_ARGUMENTS);
  403. *option |= OPTION_TREE;
  404. am = ARG_MODE_INDEX_NEED_OPTION;
  405. continue;
  406. }
  407. if ( (0 == lstrcmpi(&argv[k][1], TEXT("Continue"))) ||
  408. (0 == lstrcmpi(&argv[k][1], TEXT("c"))) )
  409. {
  410. if (*option & OPTION_CONTINUE_ON_ERROR)
  411. return(ERROR_BAD_ARGUMENTS);
  412. *option |= OPTION_CONTINUE_ON_ERROR;
  413. am = ARG_MODE_INDEX_NEED_OPTION;
  414. continue;
  415. }
  416. if ( (0 == lstrcmpi(&argv[k][1], TEXT("Edit"))) ||
  417. (0 == lstrcmpi(&argv[k][1], TEXT("E"))) )
  418. {
  419. if (*emode != MODE_DISPLAY)
  420. return(ERROR_BAD_ARGUMENTS);
  421. *emode = MODE_MODIFY;
  422. am = ARG_MODE_INDEX_NEED_OPTION;
  423. continue;
  424. }
  425. #if DBG
  426. if ( (0 == lstrcmpi(&argv[k][1], TEXT("deBug"))) ||
  427. (0 == lstrcmpi(&argv[k][1], TEXT("b"))) )
  428. {
  429. if (*debug)
  430. return(ERROR_BAD_ARGUMENTS);
  431. am = ARG_MODE_INDEX_DEBUG;
  432. *debug = DEBUG_LAST_ERROR;
  433. continue;
  434. }
  435. #endif
  436. if ( (0 == lstrcmpi(&argv[k][1], TEXT("Deny"))) ||
  437. (0 == lstrcmpi(&argv[k][1], TEXT("D"))) )
  438. {
  439. am = ARG_MODE_INDEX_DENY;
  440. *option |= OPTION_DENY;
  441. } else if ( (0 == lstrcmpi(&argv[k][1], TEXT("Revoke"))) ||
  442. (0 == lstrcmpi(&argv[k][1], TEXT("R"))) )
  443. {
  444. am = ARG_MODE_INDEX_REVOKE;
  445. *option |= OPTION_REVOKE;
  446. } else if ( (0 == lstrcmpi(&argv[k][1], TEXT("Grant"))) ||
  447. (0 == lstrcmpi(&argv[k][1], TEXT("G"))) )
  448. {
  449. am = ARG_MODE_INDEX_GRANT;
  450. *option |= OPTION_GRANT;
  451. } else if ( (0 == lstrcmpi(&argv[k][1], TEXT("rePlace"))) ||
  452. (0 == lstrcmpi(&argv[k][1], TEXT("P"))) )
  453. {
  454. *option |= OPTION_REPLACE;
  455. am = ARG_MODE_INDEX_REPLACE;
  456. } else
  457. return(ERROR_BAD_ARGUMENTS);
  458. if (astart[am] != 0)
  459. return(ERROR_BAD_ARGUMENTS);
  460. astart[am] = k+1;
  461. } else
  462. {
  463. switch (am)
  464. {
  465. case ARG_MODE_INDEX_NEED_OPTION:
  466. return(ERROR_BAD_ARGUMENTS);
  467. #if DBG
  468. case ARG_MODE_INDEX_DEBUG:
  469. *debug = _wtol(argv[k]);
  470. if (*debug & DEBUG_ENUMERATE)
  471. if (*emode == MODE_DISPLAY)
  472. *emode = MODE_DEBUG_ENUMERATE;
  473. else
  474. return(ERROR_BAD_ARGUMENTS);
  475. am = ARG_MODE_INDEX_NEED_OPTION;
  476. break;
  477. #endif
  478. case ARG_MODE_INDEX_DENY:
  479. case ARG_MODE_INDEX_REVOKE:
  480. case ARG_MODE_INDEX_GRANT:
  481. case ARG_MODE_INDEX_REPLACE:
  482. aend[am] = k+1;
  483. break;
  484. default:
  485. return(ERROR_BAD_ARGUMENTS);
  486. }
  487. }
  488. }
  489. if ( ( (*option & OPTION_DENY) && (aend[ARG_MODE_INDEX_DENY] == 0) ) ||
  490. ( (*option & OPTION_REVOKE) && (aend[ARG_MODE_INDEX_REVOKE] == 0) ) ||
  491. ( (*option & OPTION_GRANT) && (aend[ARG_MODE_INDEX_GRANT] == 0) ) ||
  492. ( (*option & OPTION_REPLACE) && (aend[ARG_MODE_INDEX_REPLACE] == 0) ) )
  493. {
  494. return(ERROR_BAD_ARGUMENTS);
  495. } else if ( (*option & OPTION_DENY) ||
  496. (*option & OPTION_REVOKE) ||
  497. (*option & OPTION_GRANT) ||
  498. (*option & OPTION_REPLACE) )
  499. {
  500. if (*emode == MODE_DISPLAY)
  501. {
  502. if (*option & OPTION_REVOKE)
  503. {
  504. return(ERROR_BAD_ARGUMENTS);
  505. }
  506. *emode = MODE_REPLACE;
  507. }
  508. }
  509. return(ERROR_SUCCESS);
  510. }
  511. //---------------------------------------------------------------------------
  512. //
  513. // Function: DisplayAces
  514. //
  515. // Synopsis: displays ACL from specified file
  516. //
  517. // Arguments: IN [filename] - file name
  518. // IN [option] - display option
  519. //
  520. //----------------------------------------------------------------------------
  521. ULONG DisplayAces(TCHAR *filename, ULONG option)
  522. {
  523. CFileEnumerate cfe(option & OPTION_TREE);
  524. WCHAR *pwfilename;
  525. BOOL fdir;
  526. ULONG ret;
  527. if (NO_ERROR == (ret = cfe.Init(filename, &pwfilename, &fdir)))
  528. {
  529. while ( (NO_ERROR == ret) ||
  530. ( ( (ERROR_ACCESS_DENIED == ret ) || (ERROR_SHARING_VIOLATION == ret) )&&
  531. (option & OPTION_CONTINUE_ON_ERROR) ) )
  532. {
  533. #if DBG
  534. if (fdir)
  535. DISPLAY((stderr, "processing file: "))
  536. else
  537. DISPLAY((stderr, "processing dir: "))
  538. #endif
  539. cprintf( TEXT("%s"), pwfilename);
  540. if (ERROR_ACCESS_DENIED == ret)
  541. {
  542. printmessage(stdout,MSG_CACLS_ACCESS_DENIED, NULL);
  543. } else if (ERROR_SHARING_VIOLATION == ret)
  544. {
  545. printmessage(stdout,MSG_CACLS_SHARING_VIOLATION, NULL);
  546. } else
  547. {
  548. DISPLAY((stderr, "\n"))
  549. VERBOSE((stderr, "\n"))
  550. CDumpSecurity cds(pwfilename);
  551. if (NO_ERROR == (ret = cds.Init()))
  552. {
  553. #if DBG
  554. if (Debug & DEBUG_VERBOSE)
  555. {
  556. SID *psid;
  557. ULONG oo;
  558. if (NO_ERROR == (ret = cds.GetSDOwner(&psid)))
  559. {
  560. printf(" Owner = ");
  561. printfsid(psid, &oo);
  562. if (NO_ERROR == (ret = cds.GetSDGroup(&psid)))
  563. {
  564. printf(" Group = ");
  565. printfsid(psid, &oo);
  566. }
  567. else
  568. ERRORS((stderr, "GetSDGroup failed, %d\n",ret))
  569. }
  570. else
  571. ERRORS((stderr, "GetSDOwner failed, %d\n",ret))
  572. }
  573. #endif
  574. ACE_HEADER *paceh;
  575. if(cds.IsDaclNull())
  576. {
  577. printmessage(stdout,MSG_NULL_DACL, NULL);
  578. }
  579. else
  580. {
  581. LONG retace;
  582. if (NO_ERROR == ret)
  583. for (retace = cds.GetNextAce(&paceh); retace >= 0; )
  584. {
  585. printface(paceh, fdir, wcslen(pwfilename));
  586. retace = cds.GetNextAce(&paceh);
  587. if (retace >= 0)
  588. printf("%*s",
  589. WideCharToMultiByte(CP_ACP, 0,
  590. pwfilename, -1,
  591. NULL, 0,
  592. NULL, NULL)-1," ");
  593. }
  594. }
  595. }
  596. #if DBG
  597. else
  598. ERRORS((stderr, "cds.init failed, %d\n",ret))
  599. #endif
  600. }
  601. fprintf(stdout, "\n");
  602. if ( (NO_ERROR == ret) ||
  603. ( ( (ERROR_ACCESS_DENIED == ret ) || (ERROR_SHARING_VIOLATION == ret) )&&
  604. (option & OPTION_CONTINUE_ON_ERROR) ) )
  605. ret = cfe.Next(&pwfilename, &fdir);
  606. }
  607. switch (ret)
  608. {
  609. case ERROR_NO_MORE_FILES:
  610. ret = ERROR_SUCCESS;
  611. break;
  612. case ERROR_ACCESS_DENIED:
  613. case ERROR_SHARING_VIOLATION:
  614. break;
  615. case ERROR_SUCCESS:
  616. break;
  617. default:
  618. break;
  619. }
  620. } else
  621. {
  622. ERRORS((stderr, "cfe.init failed, %d\n",ret))
  623. }
  624. return(ret);
  625. }
  626. //---------------------------------------------------------------------------
  627. //
  628. // Function: ModifyAces
  629. //
  630. // Synopsis: modifies the aces for the specified file(s)
  631. //
  632. // Arguments: IN [filename] - name of file(s) to modify the aces on
  633. // IN [emode] - mode of operation
  634. // IN [option] - requested option
  635. // IN [astart] - start of arguments for each option
  636. // IN [aend] - end of arguments for each option
  637. //
  638. //----------------------------------------------------------------------------
  639. ULONG ModifyAces(TCHAR *filename,
  640. MODE emode,
  641. ULONG option,
  642. TCHAR *argv[],
  643. LONG astart[], LONG aend[])
  644. {
  645. CDaclWrap cdw;
  646. CFileEnumerate cfe(option & OPTION_TREE);
  647. WCHAR *user = NULL;
  648. ULONG access;
  649. ULONG ret = ERROR_SUCCESS;
  650. WCHAR *pwfilename;
  651. ULONG curoption;
  652. VERBOSERW((stderr, TEXT("user:permission pairs\n") ))
  653. // first proces the command line args to build up the new ace
  654. for (ULONG j = 0, k = 1;j < MAX_OPTIONS ; k <<= 1, j++ )
  655. {
  656. curoption = k;
  657. if (option & k)
  658. {
  659. for (LONG q = astart[j];
  660. q < aend[j] ; q++ )
  661. {
  662. VERBOSERW((stderr, TEXT(" %s\n"),argv[q] ))
  663. if ((k & OPTION_GRANT) || (k & OPTION_REPLACE))
  664. {
  665. if (!GetUserAndAccess(argv[q], &user, &access))
  666. {
  667. #if !defined(UNICODE) || !defined(_UNICODE)
  668. if (user)
  669. LocalFree(user);
  670. #endif
  671. return(ERROR_BAD_ARGUMENTS);
  672. }
  673. if (GENERIC_NONE == access)
  674. {
  675. if (!(k & OPTION_REPLACE))
  676. {
  677. #if !defined(UNICODE) || !defined(_UNICODE)
  678. if (user)
  679. LocalFree(user);
  680. #endif
  681. return(ERROR_BAD_ARGUMENTS);
  682. }
  683. }
  684. } else
  685. {
  686. #if !defined(UNICODE) || !defined(_UNICODE)
  687. user = mbstowcs(argv[q]);
  688. #else
  689. user = argv[q];
  690. #endif
  691. access = GENERIC_NONE;
  692. }
  693. VERBOSERW((stderr, TEXT("OPTION = %d, USER = %ws, ACCESS = %lx\n"),
  694. option,
  695. user,
  696. access))
  697. if (ERROR_SUCCESS != (ret = cdw.SetAccess(curoption,
  698. user,
  699. NULL,
  700. access)))
  701. {
  702. ERRORS((stderr, "SetAccess for %ws:%lx failed, %d\n",
  703. user,
  704. access,
  705. ret))
  706. #if !defined(UNICODE) || !defined(_UNICODE)
  707. LocalFree(user);
  708. #endif
  709. return(ret);
  710. }
  711. #if !defined(UNICODE) || !defined(_UNICODE)
  712. LocalFree(user);
  713. #endif
  714. user = NULL;
  715. }
  716. }
  717. }
  718. BOOL fdir;
  719. if (emode == MODE_REPLACE)
  720. {
  721. CHAR well[MAX_PATH];
  722. CHAR msgbuf[MAX_PATH];
  723. printmessage(stdout,MSG_CACLS_ARE_YOU_SURE, NULL);
  724. FormatMessageA(FORMAT_MESSAGE_FROM_HMODULE, NULL, MSG_CACLS_Y, 0,
  725. msgbuf, MAX_PATH, NULL);
  726. if(!fgets(well,MAX_PATH,stdin))
  727. {
  728. int err = 0;
  729. if((err = ferror(stdin)))
  730. return err;
  731. return ERROR_INVALID_PARAMETER;
  732. }
  733. // remove the trailing return
  734. if ('\n' == well[strlen(well) - sizeof(CHAR)])
  735. well[strlen(well) - sizeof(CHAR)] = '\0';
  736. if (0 != _stricmp(well, msgbuf))
  737. {
  738. FormatMessageA(FORMAT_MESSAGE_FROM_HMODULE, NULL, MSG_CACLS_YES, 0,
  739. msgbuf, MAX_PATH, NULL);
  740. if (0 != _stricmp(well, msgbuf))
  741. return(ERROR_SUCCESS);
  742. }
  743. }
  744. if (NO_ERROR == (ret = cfe.Init(filename, &pwfilename, &fdir)))
  745. {
  746. while ( (NO_ERROR == ret) ||
  747. ( ( (ERROR_ACCESS_DENIED == ret ) || (ERROR_SHARING_VIOLATION == ret) )&&
  748. (option & OPTION_CONTINUE_ON_ERROR) ) )
  749. {
  750. CFileSecurity cfs(pwfilename);
  751. if (NO_ERROR == (ret = cfs.Init()))
  752. {
  753. if (NO_ERROR != (ret = cfs.SetFS(emode == MODE_REPLACE ? FALSE : TRUE, &cdw, fdir)))
  754. {
  755. if (!(((ERROR_ACCESS_DENIED == ret) || (ERROR_SHARING_VIOLATION == ret)) &&
  756. (option & OPTION_CONTINUE_ON_ERROR)))
  757. {
  758. ERRORS((stderr, "SetFS on %ws failed %ld\n",pwfilename, ret))
  759. return(ret);
  760. }
  761. }
  762. }
  763. else
  764. {
  765. //
  766. // If the error is access denied or sharing violation and we are to continue on error,
  767. // then keep going. Otherwise bail out here.
  768. //
  769. if (!(((ERROR_ACCESS_DENIED == ret) || (ERROR_SHARING_VIOLATION == ret)) &&
  770. (option & OPTION_CONTINUE_ON_ERROR))) {
  771. ERRORS((stderr, "init failed, %d\n",ret))
  772. return(ret);
  773. }
  774. }
  775. if (NO_ERROR == ret)
  776. {
  777. if (fdir)
  778. {
  779. printmessage(stdout, MSG_CACLS_PROCESSED_DIR, NULL);
  780. cprintf(L"%s\n", pwfilename);
  781. }
  782. else
  783. {
  784. printmessage(stdout, MSG_CACLS_PROCESSED_FILE, NULL);
  785. cprintf(L"%s\n", pwfilename);
  786. }
  787. }
  788. else if (ERROR_ACCESS_DENIED == ret)
  789. {
  790. printmessage(stdout, MSG_CACLS_ACCESS_DENIED, NULL);
  791. cprintf(L"%s\n", pwfilename);
  792. }
  793. else if (ret == ERROR_SHARING_VIOLATION)
  794. {
  795. printmessage(stdout, MSG_CACLS_SHARING_VIOLATION, NULL);
  796. cprintf(L"%s\n", pwfilename);
  797. }
  798. if ( (NO_ERROR == ret) ||
  799. ( ( (ERROR_ACCESS_DENIED == ret ) || (ERROR_SHARING_VIOLATION == ret) ) &&
  800. (option & OPTION_CONTINUE_ON_ERROR) ) )
  801. ret = cfe.Next(&pwfilename, &fdir);
  802. }
  803. switch (ret)
  804. {
  805. case ERROR_NO_MORE_FILES:
  806. ret = ERROR_SUCCESS;
  807. break;
  808. case ERROR_ACCESS_DENIED:
  809. case ERROR_SHARING_VIOLATION:
  810. break;
  811. case ERROR_SUCCESS:
  812. break;
  813. default:
  814. DISPLAY((stderr, "%ws failed: %d\n", pwfilename, ret))
  815. break;
  816. }
  817. } else
  818. ERRORS((stderr, "file enumeration failed to initialize %ws, %ld\n",pwfilename, ret))
  819. if (ret == ERROR_NO_MORE_FILES)
  820. {
  821. ret = ERROR_SUCCESS;
  822. }
  823. if (ret != ERROR_SUCCESS)
  824. {
  825. ERRORS((stderr, "Enumeration failed, %d\n",ret))
  826. }
  827. return(ret);
  828. }
  829. #if DBG
  830. //---------------------------------------------------------------------------
  831. //
  832. // Function: DebugEnumerate
  833. //
  834. // Synopsis: debug function
  835. //
  836. // Arguments: IN [filename] - file name
  837. // IN [option] - option
  838. //
  839. //----------------------------------------------------------------------------
  840. ULONG DebugEnumerate(TCHAR *filename, ULONG option)
  841. {
  842. CFileEnumerate cfe(option & OPTION_TREE);
  843. WCHAR *pwfilename;
  844. BOOL fdir;
  845. ULONG ret;
  846. ret = cfe.Init(filename, &pwfilename, &fdir);
  847. while ( (ERROR_SUCCESS == ret) ||
  848. ( (ERROR_ACCESS_DENIED == ret ) &&
  849. (option & OPTION_CONTINUE_ON_ERROR) ) )
  850. {
  851. if (fdir)
  852. printf("dir name = %ws%ws\n",pwfilename,
  853. ERROR_ACCESS_DENIED == ret ? L"ACCESS DENIED" : L"");
  854. else
  855. printf("file name = %ws%ws\n",pwfilename,
  856. ERROR_ACCESS_DENIED == ret ? L"ACCESS DENIED" : L"");
  857. ret = cfe.Next(&pwfilename, &fdir);
  858. }
  859. if (ret == ERROR_ACCESS_DENIED)
  860. {
  861. if (fdir)
  862. printf("dir name = %ws%ws\n",pwfilename,
  863. ERROR_ACCESS_DENIED == ret ? L"ACCESS DENIED" : L"");
  864. else
  865. printf("file name = %ws%ws\n",pwfilename,
  866. ERROR_ACCESS_DENIED == ret ? L"ACCESS DENIED" : L"");
  867. }
  868. if (ret != ERROR_NO_MORE_FILES)
  869. printf("Enumeration failed, %d\n",ret);
  870. return(ret);
  871. }
  872. #endif
  873. //---------------------------------------------------------------------------
  874. //
  875. // Function: GetUserAccess
  876. //
  877. // Synopsis: parses an input string for user:access
  878. //
  879. // Arguments: IN [arg] - input string to parse
  880. // OUT [user] - user if found
  881. // OUT [access] - access if found
  882. //
  883. //----------------------------------------------------------------------------
  884. BOOL GetUserAndAccess(TCHAR *arg, WCHAR **user, ULONG *access)
  885. {
  886. TCHAR *saccess = wcschr(arg,':');
  887. if (saccess)
  888. {
  889. *saccess = NULL;
  890. saccess++;
  891. if (wcschr(saccess,':'))
  892. return(FALSE);
  893. #if defined(UNICODE) || defined(_UNICODE)
  894. *user = arg;
  895. #else
  896. *user = mbstowcs(arg);
  897. #endif
  898. if (0 == lstrcmpi(saccess, TEXT("F") ))
  899. {
  900. *access = ( STANDARD_RIGHTS_ALL |
  901. FILE_READ_DATA |
  902. FILE_WRITE_DATA |
  903. FILE_APPEND_DATA |
  904. FILE_READ_EA |
  905. FILE_WRITE_EA |
  906. FILE_EXECUTE |
  907. FILE_DELETE_CHILD |
  908. FILE_READ_ATTRIBUTES |
  909. FILE_WRITE_ATTRIBUTES );
  910. }
  911. else if (0 == lstrcmpi(saccess,TEXT("R") ))
  912. {
  913. *access = FILE_GENERIC_READ | FILE_EXECUTE;
  914. }
  915. else if (0 == lstrcmpi(saccess, TEXT("C") ))
  916. {
  917. *access = FILE_GENERIC_WRITE | FILE_GENERIC_READ | FILE_EXECUTE | DELETE;
  918. }
  919. else if (0 == lstrcmpi(saccess, TEXT("N") ))
  920. {
  921. *access = GENERIC_NONE;
  922. }
  923. else if (0 == lstrcmpi(saccess, TEXT("W") ))
  924. {
  925. *access = FILE_GENERIC_WRITE | FILE_EXECUTE;
  926. }
  927. else
  928. return(FALSE);
  929. return(TRUE);
  930. }
  931. return(FALSE);
  932. }
  933. //---------------------------------------------------------------------------
  934. //
  935. // Function: mbstowcs
  936. //
  937. // Synopsis: converts char to wchar, allocates space for wchar
  938. //
  939. // Arguments: IN [aname] - char string
  940. //
  941. //----------------------------------------------------------------------------
  942. WCHAR *mbstowcs(char *aname )
  943. {
  944. if (aname)
  945. {
  946. WCHAR *pwname = NULL;
  947. pwname = (WCHAR *)LocalAlloc(LMEM_FIXED, sizeof(WCHAR) * (strlen(aname)+1));
  948. if (NULL == pwname)
  949. return(NULL);
  950. WCHAR *prwname = pwname;
  951. if (MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
  952. aname, -1,
  953. prwname, sizeof(WCHAR)*(strlen(aname)+1)) == 0)
  954. return(NULL);
  955. return(pwname);
  956. } else
  957. return(NULL);
  958. }
  959. //----------------------------------------------------------------------------
  960. //
  961. // Function:
  962. //
  963. // Synopsis:
  964. //
  965. // Arguments:
  966. //
  967. //----------------------------------------------------------------------------
  968. BOOLEAN OpenToken(PHANDLE ph)
  969. {
  970. HANDLE hprocess;
  971. hprocess = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
  972. if (hprocess == NULL)
  973. return(FALSE);
  974. if (OpenProcessToken(hprocess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ph))
  975. {
  976. CloseHandle(hprocess);
  977. return(TRUE);
  978. }
  979. CloseHandle(hprocess);
  980. return(FALSE);
  981. }
  982. //----------------------------------------------------------------------------
  983. //
  984. // Function: printfsid
  985. //
  986. // Synopsis: prints a NT SID
  987. //
  988. // Arguments: IN [psid] - pointer to the sid to print
  989. //
  990. //----------------------------------------------------------------------------
  991. void printfsid(SID *psid, ULONG *outputoffset)
  992. {
  993. #if DBG
  994. if ((Debug & DEBUG_VERBOSE) || (Debug & DEBUG_DISPLAY_SIDS))
  995. {
  996. printf("S-%lx",psid->Revision);
  997. if ( (psid->IdentifierAuthority.Value[0] != 0) ||
  998. (psid->IdentifierAuthority.Value[1] != 0) )
  999. {
  1000. printf("0x%02hx%02hx%02hx%02hx%02hx%02hx",
  1001. (USHORT)psid->IdentifierAuthority.Value[0],
  1002. (USHORT)psid->IdentifierAuthority.Value[1],
  1003. (USHORT)psid->IdentifierAuthority.Value[2],
  1004. (USHORT)psid->IdentifierAuthority.Value[3],
  1005. (USHORT)psid->IdentifierAuthority.Value[4],
  1006. (USHORT)psid->IdentifierAuthority.Value[5] );
  1007. } else
  1008. {
  1009. printf("-%lu",
  1010. (ULONG)psid->IdentifierAuthority.Value[5] +
  1011. (ULONG)(psid->IdentifierAuthority.Value[4] << 8) +
  1012. (ULONG)(psid->IdentifierAuthority.Value[3] << 16) +
  1013. (ULONG)(psid->IdentifierAuthority.Value[2] << 24) );
  1014. }
  1015. if ( 0 < psid->SubAuthorityCount )
  1016. {
  1017. for (int k = 0; k < psid->SubAuthorityCount; k++ )
  1018. {
  1019. printf("-%d",psid->SubAuthority[k]);
  1020. }
  1021. }
  1022. }
  1023. #endif
  1024. ULONG ret;
  1025. CAccount ca(psid, NULL);
  1026. WCHAR *domain = NULL;
  1027. WCHAR *user;
  1028. if (NO_ERROR == ( ret = ca.GetAccountDomain(&domain) ) )
  1029. {
  1030. if ( (NULL == domain) || (0 == wcslen(domain)) )
  1031. {
  1032. fprintf(stdout, " ");
  1033. *outputoffset +=1;
  1034. }
  1035. else
  1036. {
  1037. fprintf(stdout, " ");
  1038. wprintf(L"%s", domain);
  1039. fprintf(stdout, "\\");
  1040. *outputoffset += 2 + wcslen( domain );;
  1041. }
  1042. if (NO_ERROR == ( ret = ca.GetAccountName(&user) ) )
  1043. {
  1044. wprintf(L"%s", user);
  1045. fprintf(stdout, ":");
  1046. *outputoffset += 1 + wcslen(user);
  1047. } else
  1048. {
  1049. *outputoffset += printmessage(stdout, MSG_CACLS_NAME_NOT_FOUND, NULL);
  1050. ERRORS((stderr, "(%lx)",ret))
  1051. }
  1052. } else
  1053. {
  1054. *outputoffset+= printmessage(stdout, MSG_CACLS_DOMAIN_NOT_FOUND, NULL);
  1055. ERRORS((stderr, "(%lx)",ret))
  1056. }
  1057. VERBOSE((stderr, "\n"))
  1058. }
  1059. //----------------------------------------------------------------------------
  1060. //
  1061. // Function: printface
  1062. //
  1063. // Synopsis: prints the specifed ace
  1064. //
  1065. // Arguments: IN [paceh] - input ace (header)
  1066. // IN [fdir] - TRUE = directory (different display options)
  1067. //
  1068. //----------------------------------------------------------------------------
  1069. void printface(ACE_HEADER *paceh, BOOL fdir, ULONG outputoffset)
  1070. {
  1071. VERBOSE((stderr, " "))
  1072. VERBOSER((stderr, "\npaceh->AceType = %x\n",paceh->AceType ))
  1073. VERBOSER((stderr, "paceh->AceFlags = %x\n",paceh->AceFlags ))
  1074. VERBOSER((stderr, "paceh->AceSize = %x\n",paceh->AceSize ))
  1075. ACCESS_ALLOWED_ACE *paaa = (ACCESS_ALLOWED_ACE *)paceh;
  1076. printfsid((SID *)&(paaa->SidStart),&outputoffset);
  1077. if (paceh->AceFlags & OBJECT_INHERIT_ACE )
  1078. {
  1079. outputoffset+= printmessage(stdout, MSG_CACLS_OBJECT_INHERIT, NULL);
  1080. }
  1081. if (paceh->AceFlags & CONTAINER_INHERIT_ACE )
  1082. {
  1083. outputoffset+= printmessage(stdout, MSG_CACLS_CONTAINER_INHERIT, NULL);
  1084. }
  1085. if (paceh->AceFlags & NO_PROPAGATE_INHERIT_ACE)
  1086. {
  1087. outputoffset+= printmessage(stdout, MSG_CACLS_NO_PROPAGATE_INHERIT, NULL);
  1088. }
  1089. if (paceh->AceFlags & INHERIT_ONLY_ACE )
  1090. {
  1091. outputoffset+= printmessage(stdout, MSG_CACLS_INHERIT_ONLY, NULL);
  1092. }
  1093. if (paceh->AceType == ACCESS_DENIED_ACE_TYPE)
  1094. {
  1095. DISPLAY_MASK((stderr, "(DENIED)"))
  1096. VERBOSE((stderr, "(DENIED)"))
  1097. }
  1098. printfmask(paaa->Mask, paceh->AceType, fdir, outputoffset);
  1099. fprintf(stdout, "\n");
  1100. }
  1101. //----------------------------------------------------------------------------
  1102. //
  1103. // Function: printfmask
  1104. //
  1105. // Synopsis: prints the access mask
  1106. //
  1107. // Arguments: IN [mask] - the access mask
  1108. // IN [acetype] - allowed/denied
  1109. // IN [fdir] - TRUE = directory
  1110. //
  1111. //----------------------------------------------------------------------------
  1112. CHAR *aRightsStr[] = { "STANDARD_RIGHTS_ALL",
  1113. "DELETE",
  1114. "READ_CONTROL",
  1115. "WRITE_DAC",
  1116. "WRITE_OWNER",
  1117. "SYNCHRONIZE",
  1118. "STANDARD_RIGHTS_REQUIRED",
  1119. "SPECIFIC_RIGHTS_ALL",
  1120. "ACCESS_SYSTEM_SECURITY",
  1121. "MAXIMUM_ALLOWED",
  1122. "GENERIC_READ",
  1123. "GENERIC_WRITE",
  1124. "GENERIC_EXECUTE",
  1125. "GENERIC_ALL",
  1126. "FILE_GENERIC_READ",
  1127. "FILE_GENERIC_WRITE",
  1128. "FILE_GENERIC_EXECUTE",
  1129. "FILE_READ_DATA",
  1130. //FILE_LIST_DIRECTORY
  1131. "FILE_WRITE_DATA",
  1132. //FILE_ADD_FILE
  1133. "FILE_APPEND_DATA",
  1134. //FILE_ADD_SUBDIRECTORY
  1135. "FILE_READ_EA",
  1136. "FILE_WRITE_EA",
  1137. "FILE_EXECUTE",
  1138. //FILE_TRAVERSE
  1139. "FILE_DELETE_CHILD",
  1140. "FILE_READ_ATTRIBUTES",
  1141. "FILE_WRITE_ATTRIBUTES" };
  1142. #define NUMRIGHTS 26
  1143. ULONG aRights[NUMRIGHTS] = { STANDARD_RIGHTS_ALL ,
  1144. DELETE ,
  1145. READ_CONTROL ,
  1146. WRITE_DAC ,
  1147. WRITE_OWNER ,
  1148. SYNCHRONIZE ,
  1149. STANDARD_RIGHTS_REQUIRED ,
  1150. SPECIFIC_RIGHTS_ALL ,
  1151. ACCESS_SYSTEM_SECURITY ,
  1152. MAXIMUM_ALLOWED ,
  1153. GENERIC_READ ,
  1154. GENERIC_WRITE ,
  1155. GENERIC_EXECUTE ,
  1156. GENERIC_ALL ,
  1157. FILE_GENERIC_READ ,
  1158. FILE_GENERIC_WRITE ,
  1159. FILE_GENERIC_EXECUTE ,
  1160. FILE_READ_DATA ,
  1161. //FILE_LIST_DIRECTORY ,
  1162. FILE_WRITE_DATA ,
  1163. //FILE_ADD_FILE ,
  1164. FILE_APPEND_DATA ,
  1165. //FILE_ADD_SUBDIRECTORY ,
  1166. FILE_READ_EA ,
  1167. FILE_WRITE_EA ,
  1168. FILE_EXECUTE ,
  1169. //FILE_TRAVERSE ,
  1170. FILE_DELETE_CHILD ,
  1171. FILE_READ_ATTRIBUTES ,
  1172. FILE_WRITE_ATTRIBUTES };
  1173. void printfmask(ULONG mask, UCHAR acetype, BOOL fdir, ULONG outputoffset)
  1174. {
  1175. ULONG savmask = mask;
  1176. VERBOSER((stderr, "mask = %08lx ", mask))
  1177. DISPLAY_MASK((stderr, "mask = %08lx\n", mask))
  1178. VERBOSE((stderr, " "))
  1179. #if DBG
  1180. if (!(Debug & (DEBUG_VERBOSE | DEBUG_DISPLAY_MASK)))
  1181. {
  1182. #endif
  1183. if ((acetype == ACCESS_ALLOWED_ACE_TYPE) &&
  1184. (mask == (FILE_GENERIC_READ | FILE_EXECUTE)))
  1185. {
  1186. printmessage(stdout, MSG_CACLS_READ, NULL);
  1187. } else if ((acetype == ACCESS_ALLOWED_ACE_TYPE) &&
  1188. (mask == (FILE_GENERIC_WRITE | FILE_GENERIC_READ | FILE_EXECUTE | DELETE)))
  1189. {
  1190. printmessage(stdout, MSG_CACLS_CHANGE, NULL);
  1191. } else if ((acetype == ACCESS_ALLOWED_ACE_TYPE) &&
  1192. (mask == (GENERIC_WRITE | GENERIC_READ | GENERIC_EXECUTE | DELETE)))
  1193. {
  1194. printmessage(stdout, MSG_CACLS_CHANGE, NULL);
  1195. } else if ((acetype == ACCESS_ALLOWED_ACE_TYPE) &&
  1196. (mask == ( STANDARD_RIGHTS_ALL |
  1197. FILE_READ_DATA |
  1198. FILE_WRITE_DATA |
  1199. FILE_APPEND_DATA |
  1200. FILE_READ_EA |
  1201. FILE_WRITE_EA |
  1202. FILE_EXECUTE |
  1203. FILE_DELETE_CHILD |
  1204. FILE_READ_ATTRIBUTES |
  1205. FILE_WRITE_ATTRIBUTES )) )
  1206. {
  1207. printmessage(stdout, MSG_CACLS_FULL_CONTROL, NULL);
  1208. } else if ((acetype == ACCESS_ALLOWED_ACE_TYPE) &&
  1209. (mask == GENERIC_ALL))
  1210. {
  1211. printmessage(stdout, MSG_CACLS_FULL_CONTROL, NULL);
  1212. } else if ((acetype == ACCESS_DENIED_ACE_TYPE) &&
  1213. (mask == GENERIC_ALL))
  1214. {
  1215. printmessage(stdout, MSG_CACLS_NONE, NULL);
  1216. } else if ((acetype == ACCESS_DENIED_ACE_TYPE) &&
  1217. (mask == ( STANDARD_RIGHTS_ALL |
  1218. FILE_READ_DATA |
  1219. FILE_WRITE_DATA |
  1220. FILE_APPEND_DATA |
  1221. FILE_READ_EA |
  1222. FILE_WRITE_EA |
  1223. FILE_EXECUTE |
  1224. FILE_DELETE_CHILD |
  1225. FILE_READ_ATTRIBUTES |
  1226. FILE_WRITE_ATTRIBUTES )) )
  1227. {
  1228. printmessage(stdout, MSG_CACLS_NONE, NULL);
  1229. } else
  1230. {
  1231. if (acetype == ACCESS_DENIED_ACE_TYPE)
  1232. printmessage(stdout, MSG_CACLS_DENY, NULL);
  1233. printmessage(stdout, MSG_CACLS_SPECIAL_ACCESS, NULL);
  1234. for (int k = 0; k<NUMRIGHTS ; k++ )
  1235. {
  1236. if ((mask & aRights[k]) == aRights[k])
  1237. {
  1238. fprintf(stdout, "%*s%s\n",outputoffset, " ", aRightsStr[k]);
  1239. }
  1240. if (mask == 0)
  1241. break;
  1242. }
  1243. }
  1244. #if DBG
  1245. } else
  1246. {
  1247. if (Debug & (DEBUG_DISPLAY_MASK | DEBUG_VERBOSE))
  1248. {
  1249. printf("\n");
  1250. for (int k = 0; k<NUMRIGHTS ; k++ )
  1251. {
  1252. if ((mask & aRights[k]) == aRights[k])
  1253. {
  1254. if (mask != savmask) printf(" |\n");
  1255. printf(" %s",aRightsStr[k]);
  1256. mask &= ~aRights[k];
  1257. }
  1258. if (mask == 0)
  1259. break;
  1260. }
  1261. }
  1262. VERBOSE((stderr, "=%x",mask))
  1263. if (mask != 0)
  1264. DISPLAY((stderr, "=%x/%x",mask,savmask))
  1265. }
  1266. #endif
  1267. fprintf(stdout, " ");
  1268. }
  1269. //----------------------------------------------------------------------------
  1270. //
  1271. // Function: printmessage
  1272. //
  1273. // Synopsis: prints a message, either from the local message file, or from the system
  1274. //
  1275. // Arguments: IN [fp] - stderr, stdio, etc.
  1276. // IN [messageID] - variable argument list
  1277. //
  1278. // Returns: length of the output buffer
  1279. //
  1280. //----------------------------------------------------------------------------
  1281. ULONG
  1282. __cdecl
  1283. printmessage (FILE* fp, DWORD messageID, ...)
  1284. {
  1285. WCHAR messagebuffer[4096];
  1286. va_list ap;
  1287. va_start(ap, messageID);
  1288. if (!FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, NULL, messageID, 0,
  1289. messagebuffer, 4095, &ap))
  1290. FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, messageID, 0,
  1291. messagebuffer, 4095, &ap);
  1292. CHAR achOem[2048];
  1293. WideCharToMultiByte(CP_OEMCP,
  1294. 0,
  1295. messagebuffer,
  1296. -1,
  1297. achOem,
  1298. sizeof(achOem),
  1299. NULL,
  1300. NULL);
  1301. fprintf(fp, achOem);
  1302. va_end(ap);
  1303. return(wcslen(messagebuffer));
  1304. }