T2.CXX
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:39k
源码类别:

Windows编程

开发平台:

Visual C++

  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. #if DBG
  22. ULONG Debug;
  23. #endif
  24. //+----------------------------------------------------------------------------
  25. //
  26. // local prototypes
  27. //
  28. //+----------------------------------------------------------------------------
  29. BOOLEAN OpenToken(PHANDLE ph);
  30. void printfsid(SID *psid, ULONG *outputoffset);
  31. void printface(ACE_HEADER *paceh, BOOL fdir, ULONG outputoffset);
  32. void printfmask(ULONG mask, UCHAR acetype, BOOL fdir, ULONG outputoffset);
  33. WCHAR *mbstowcs(char *aname );
  34. BOOL GetUserAndAccess(CHAR *arg, WCHAR **user, ULONG *access);
  35. #if DBG
  36. ULONG DebugEnumerate(CHAR *filename, ULONG option);
  37. #endif
  38. ULONG DisplayAces(CHAR *filename, ULONG option);
  39. ULONG ModifyAces(CHAR *filename,
  40.                  MODE emode,
  41.                  ULONG option,
  42.                  CHAR *argv[],
  43.                  LONG astart[], LONG aend[] );
  44. ULONG GetCmdLineArgs(INT argc, char *argv[],
  45.                      ULONG *option,
  46.                      LONG astart[], LONG aend[],
  47.                      MODE *emode
  48. #if DBG
  49.                      ,ULONG *debug
  50. #endif
  51.                      );
  52. ULONG  printmessage (FILE* fp, DWORD messageID, ...);
  53. //+----------------------------------------------------------------------------
  54. //
  55. //  Function:   Usage
  56. //
  57. //  Synopsis:   prints usage functionality
  58. //
  59. //  Arguments: none
  60. //
  61. //----------------------------------------------------------------------------
  62. VOID usage()
  63. {
  64.     printmessage(stdout, MSG_CACLS_USAGE, NULL);
  65. #if DBG
  66.     if (Debug)
  67.     {
  68.         printf("n   /B            deBug <[#]>n");
  69.         printf("                 default is display error returnedn");
  70.         printf("                 in /B '#' is a mask: 1  display SIDS valuesn");
  71.         printf("                                      2  display access masksn");
  72.         printf("                                      4  display error returnedn");
  73.         printf("                                      8  display error locationn");
  74.         printf("                                   0x10  verbosen");
  75.         printf("                                   0x20  verbosern");
  76.         printf("                                   0x40  enumerate namesn");
  77.         printf("                                   0x80  enumerate failuresn");
  78.         printf("                                  0x100  enumerate starts and returnsn");
  79.         printf("                                  0x200  enumerate extra datan");
  80.         printf("                                  0x400  size allocation datan");
  81.         printf("                                  0x800  display enumeration of filesn");
  82.     }
  83. #endif
  84. }
  85. //+----------------------------------------------------------------------------
  86. //
  87. //  Function:     Main, Public
  88. //
  89. //  Synopsis:     main!!
  90. //
  91. //  Arguments:    IN [argc] - cmdline arguement count
  92. //                IN [argv] - input cmdline arguements
  93. //
  94. //----------------------------------------------------------------------------
  95. VOID main(INT argc, char *argv[])
  96. {
  97.     char lBuf[6];
  98.     DWORD dw = GetConsoleOutputCP();
  99. //fix kksuzuka: #2383
  100. //for bilingual messages
  101.    switch (dw) {
  102.        case 932:
  103.        case 936:
  104.        case 949:
  105.        case 950:
  106.            SetThreadLocale(
  107.                MAKELCID( MAKELANGID( PRIMARYLANGID(GetSystemDefaultLangID()),
  108.                                      SUBLANG_ENGLISH_US ),
  109.                    SORT_DEFAULT ) );
  110.            sprintf(lBuf, ".%d", dw);
  111.            setlocale(LC_ALL, lBuf);
  112.            break;
  113.        default:
  114.            SetThreadLocale(
  115.                MAKELCID( MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
  116.                    SORT_DEFAULT ) );
  117.            setlocale(LC_ALL,".437");
  118.            break;
  119.     }
  120.     LONG astart[MAX_OPTIONS], aend[MAX_OPTIONS];
  121.     MODE emode;
  122.     LONG ret;
  123.     ULONG option;
  124.     if (ERROR_SUCCESS != (ret = GetCmdLineArgs(argc, argv,
  125.                                                &option,
  126.                                                astart, aend,
  127.                                                &emode
  128. #if DBG
  129.                                                ,&Debug
  130. #endif
  131.                                                )))
  132.     {
  133.         usage();
  134.         exit(ret);
  135.     }
  136.     switch (emode)
  137.     {
  138.         case MODE_DISPLAY:
  139.             ret = DisplayAces(argv[1], option);
  140.             break;
  141.         case MODE_REPLACE:
  142.         case MODE_MODIFY:
  143.             ret = ModifyAces(argv[1], emode, option, argv, astart, aend );
  144.             break;
  145. #if DBG
  146.         case MODE_DEBUG_ENUMERATE:
  147.             ret = DebugEnumerate(argv[1], option);
  148.             break;
  149. #endif
  150.         default:
  151.         {
  152.             usage();
  153.             exit(1);
  154.         }
  155.     }
  156.     if (ERROR_SUCCESS != ret)
  157.     {
  158.         LAST_ERROR((stderr, "Cacls failed, %ldn",ret))
  159.         printmessage(stderr, ret, NULL);
  160.  }
  161.     exit(ret);
  162. }
  163. //---------------------------------------------------------------------------
  164. //
  165. //  Function:     GetCmdLineArgs
  166. //
  167. //  Synopsis:     gets and parses command line arguments into commands
  168. //                recognized by this program
  169. //
  170. //  Arguments:    IN  [argc]   - cmdline arguement count
  171. //                IN  [argv]   - input cmdline arguements
  172. //                OUT [option] - requested option
  173. //                OUT [astart] - start of arguments for each option
  174. //                OUT [aend]   - end of arguments for each option
  175. //                OUT [emode]  - mode of operation
  176. //                OUT [debug]  - debug mask
  177. //
  178. //
  179. //----------------------------------------------------------------------------
  180. ULONG GetCmdLineArgs(INT argc, char *argv[],
  181.                      ULONG *option,
  182.                      LONG astart[], LONG aend[],
  183.                      MODE *emode
  184. #if DBG
  185.                      ,ULONG *debug
  186. #endif
  187.                      )
  188. {
  189.     ARG_MODE_INDEX am = ARG_MODE_INDEX_NEED_OPTION;
  190. #if DBG
  191.     *debug = 0;
  192. #endif
  193.     *emode = MODE_DISPLAY;
  194.     *option = 0;
  195.     for (LONG j=0; j < MAX_OPTIONS ;j++ )
  196.     {
  197.         astart[j] = 0;
  198.         aend[j] = 0;
  199.     }
  200.     if ( (argc < 2) || (argv[1][0] == '/') )
  201.     {
  202. #if DBG
  203.         // do this so debug args are printed out
  204.         if (argc >= 2)
  205.         {
  206.             if ( (0 == _stricmp(&argv[1][1], "deBug")) ||
  207.                  (0 == _stricmp(&argv[1][1], "b"))  )
  208.             {
  209.                 *debug = DEBUG_LAST_ERROR;
  210.             }
  211.         }
  212. #endif
  213.         return(ERROR_BAD_ARGUMENTS);
  214.     }
  215.     for (LONG k = 2; k < argc ; k++ )
  216.     {
  217.         if (argv[k][0] == '/')
  218.         {
  219.             switch (am)
  220.             {
  221.                 case ARG_MODE_INDEX_NEED_OPTION:
  222. #if DBG
  223.                 case ARG_MODE_INDEX_DEBUG:
  224. #endif
  225.                     break;
  226.                 case ARG_MODE_INDEX_DENY:
  227.                 case ARG_MODE_INDEX_REVOKE:
  228.                 case ARG_MODE_INDEX_GRANT:
  229.                 case ARG_MODE_INDEX_REPLACE:
  230.                     if (astart[am] == k)
  231.                         return(ERROR_BAD_ARGUMENTS);
  232.                     break;
  233.                 default:
  234.                     return(ERROR_BAD_ARGUMENTS);
  235.             }
  236.             if ( (0 == _stricmp(&argv[k][1], "Tree")) ||
  237.                  (0 == _stricmp(&argv[k][1], "t")) )
  238.             {
  239.                 if (*option & OPTION_TREE)
  240.                     return(ERROR_BAD_ARGUMENTS);
  241.                 *option |= OPTION_TREE;
  242.                 am = ARG_MODE_INDEX_NEED_OPTION;
  243.                 continue;
  244.             }
  245.             if ( (0 == _stricmp(&argv[k][1], "Continue")) ||
  246.                  (0 == _stricmp(&argv[k][1], "c")) )
  247.             {
  248.                 if (*option & OPTION_CONTINUE_ON_ERROR)
  249.                     return(ERROR_BAD_ARGUMENTS);
  250.                 *option |= OPTION_CONTINUE_ON_ERROR;
  251.                 am = ARG_MODE_INDEX_NEED_OPTION;
  252.                 continue;
  253.             }
  254.             if ( (0 == _stricmp(&argv[k][1], "Edit")) ||
  255.                  (0 == _stricmp(&argv[k][1], "E")) )
  256.             {
  257.                 if (*emode != MODE_DISPLAY)
  258.                     return(ERROR_BAD_ARGUMENTS);
  259.                 *emode = MODE_MODIFY;
  260.                 am = ARG_MODE_INDEX_NEED_OPTION;
  261.                 continue;
  262.             }
  263. #if DBG
  264.             if ( (0 == _stricmp(&argv[k][1], "deBug")) ||
  265.                  (0 == _stricmp(&argv[k][1], "b"))  )
  266.             {
  267.                 if (*debug)
  268.                     return(ERROR_BAD_ARGUMENTS);
  269.                 am = ARG_MODE_INDEX_DEBUG;
  270.                 *debug = DEBUG_LAST_ERROR;
  271.                 continue;
  272.             }
  273. #endif
  274.             if ( (0 == _stricmp(&argv[k][1], "Deny")) ||
  275.                  (0 == _stricmp(&argv[k][1], "D")) )
  276.             {
  277.                 am = ARG_MODE_INDEX_DENY;
  278.                 *option |= OPTION_DENY;
  279.             } else if ( (0 == _stricmp(&argv[k][1], "Revoke")) ||
  280.                         (0 == _stricmp(&argv[k][1], "R")) )
  281.             {
  282.                 am = ARG_MODE_INDEX_REVOKE;
  283.                 *option |= OPTION_REVOKE;
  284.             } else if ( (0 == _stricmp(&argv[k][1], "Grant")) ||
  285.                         (0 == _stricmp(&argv[k][1], "G")) )
  286.             {
  287.                 am = ARG_MODE_INDEX_GRANT;
  288.                 *option |= OPTION_GRANT;
  289.             } else if ( (0 == _stricmp(&argv[k][1], "rePlace")) ||
  290.                         (0 == _stricmp(&argv[k][1], "P")) )
  291.             {
  292.                 *option |= OPTION_REPLACE;
  293.                 am = ARG_MODE_INDEX_REPLACE;
  294.             } else
  295.                 return(ERROR_BAD_ARGUMENTS);
  296.             if (astart[am] != 0)
  297.                 return(ERROR_BAD_ARGUMENTS);
  298.             astart[am] = k+1;
  299.         } else
  300.         {
  301.             switch (am)
  302.             {
  303.                 case ARG_MODE_INDEX_NEED_OPTION:
  304.                     return(ERROR_BAD_ARGUMENTS);
  305. #if DBG
  306.                 case ARG_MODE_INDEX_DEBUG:
  307.                     *debug = atol(argv[k]);
  308.                     if (*debug & DEBUG_ENUMERATE)
  309.                         if (*emode == MODE_DISPLAY)
  310.                             *emode = MODE_DEBUG_ENUMERATE;
  311.                         else
  312.                             return(ERROR_BAD_ARGUMENTS);
  313.                     am = ARG_MODE_INDEX_NEED_OPTION;
  314.                     break;
  315. #endif
  316.                 case ARG_MODE_INDEX_DENY:
  317.                 case ARG_MODE_INDEX_REVOKE:
  318.                 case ARG_MODE_INDEX_GRANT:
  319.                 case ARG_MODE_INDEX_REPLACE:
  320.                     aend[am] = k+1;
  321.                     break;
  322.                 default:
  323.                     return(ERROR_BAD_ARGUMENTS);
  324.             }
  325.         }
  326.     }
  327.     if ( ( (*option & OPTION_DENY) && (aend[ARG_MODE_INDEX_DENY] == 0) ) ||
  328.          ( (*option & OPTION_REVOKE) && (aend[ARG_MODE_INDEX_REVOKE] == 0) ) ||
  329.          ( (*option & OPTION_GRANT) && (aend[ARG_MODE_INDEX_GRANT] == 0) ) ||
  330.          ( (*option & OPTION_REPLACE) && (aend[ARG_MODE_INDEX_REPLACE] == 0) ) )
  331.     {
  332.         return(ERROR_BAD_ARGUMENTS);
  333.     } else if ( (*option & OPTION_DENY) ||
  334.                 (*option & OPTION_REVOKE) ||
  335.                 (*option & OPTION_GRANT) ||
  336.                 (*option & OPTION_REPLACE) )
  337.     {
  338.         if (*emode == MODE_DISPLAY)
  339.         {
  340.             if (*option & OPTION_REVOKE)
  341.             {
  342.                 return(ERROR_BAD_ARGUMENTS);
  343.             }
  344.             *emode = MODE_REPLACE;
  345.         }
  346.     }
  347.     return(ERROR_SUCCESS);
  348. }
  349. //---------------------------------------------------------------------------
  350. //
  351. //  Function:     DisplayAces
  352. //
  353. //  Synopsis:     displays ACL from specified file
  354. //
  355. //  Arguments:    IN [filename] - file name
  356. //                IN [option]   - display option
  357. //
  358. //----------------------------------------------------------------------------
  359. ULONG DisplayAces(CHAR *filename, ULONG option)
  360. {
  361.     CFileEnumerate cfe(option & OPTION_TREE);
  362.     WCHAR *pwfilename;
  363.     BOOL fdir;
  364.     ULONG ret;
  365.     if (NO_ERROR == (ret = cfe.Init(filename, &pwfilename, &fdir)))
  366.     {
  367.         while ( (NO_ERROR == ret) ||
  368.                 ( ( (ERROR_ACCESS_DENIED == ret ) || (ERROR_SHARING_VIOLATION == ret) )&&
  369.                   (option & OPTION_CONTINUE_ON_ERROR) ) )
  370.         {
  371. #if DBG
  372.             if (fdir)
  373.                 DISPLAY((stderr, "processing file: "))
  374.             else
  375.                 DISPLAY((stderr, "processing dir: "))
  376. #endif
  377.             wprintf(L"%s",  pwfilename);
  378.             if (ERROR_ACCESS_DENIED == ret)
  379.             {
  380.                 printmessage(stdout,MSG_CACLS_ACCESS_DENIED, NULL);
  381.             } else if (ERROR_SHARING_VIOLATION == ret)
  382.             {
  383.                 printmessage(stdout,MSG_CACLS_SHARING_VIOLATION, NULL);
  384.             } else
  385.             {
  386.                 DISPLAY((stderr, "n"))
  387.                 VERBOSE((stderr, "n"))
  388.                 CDumpSecurity cds(pwfilename);
  389.                 if (NO_ERROR == (ret = cds.Init()))
  390.                 {
  391. #if DBG
  392.                     if (Debug & DEBUG_VERBOSE)
  393.                     {
  394.                         SID *psid;
  395.                         ULONG oo;
  396.                         if (NO_ERROR == (ret = cds.GetSDOwner(&psid)))
  397.                         {
  398.                             printf("  Owner = ");
  399.                             printfsid(psid, &oo);
  400.                             if (NO_ERROR == (ret = cds.GetSDGroup(&psid)))
  401.                             {
  402.                                 printf("  Group = ");
  403.                                 printfsid(psid, &oo);
  404.                             }
  405.                             else
  406.                                 ERRORS((stderr, "GetSDGroup failed, %dn",ret))
  407.                         }
  408.                         else
  409.                             ERRORS((stderr, "GetSDOwner failed, %dn",ret))
  410.                     }
  411. #endif
  412.                     ACE_HEADER *paceh;
  413.                     LONG retace;
  414.                     if (NO_ERROR == ret)
  415.                         for (retace = cds.GetNextAce(&paceh); retace >= 0; )
  416.                         {
  417.                             printface(paceh, fdir, wcslen(pwfilename));
  418.                             retace = cds.GetNextAce(&paceh);
  419.                             if (retace >= 0)
  420.                                 printf("%*s",
  421.                                        WideCharToMultiByte(CP_ACP, 0,
  422.                                                pwfilename, -1,
  423.                                                NULL, 0,
  424.                                                NULL, NULL)-1," ");
  425.                         }
  426.                 }
  427. #if DBG
  428.                    else
  429.                     ERRORS((stderr, "cds.init failed, %dn",ret))
  430. #endif
  431.             }
  432.             fprintf(stdout, "n");
  433.             if ( (NO_ERROR == ret) ||
  434.                 ( ( (ERROR_ACCESS_DENIED == ret ) || (ERROR_SHARING_VIOLATION == ret) )&&
  435.                    (option & OPTION_CONTINUE_ON_ERROR) ) )
  436.                 ret = cfe.Next(&pwfilename, &fdir);
  437.         }
  438.         switch (ret)
  439.         {
  440.             case ERROR_NO_MORE_FILES:
  441.                 ret = ERROR_SUCCESS;
  442.                 break;
  443.             case ERROR_ACCESS_DENIED:
  444.             case ERROR_SHARING_VIOLATION:
  445.                 break;
  446.             case ERROR_SUCCESS:
  447.                 break;
  448.             default:
  449.                 break;
  450.         }
  451.     } else
  452.     {
  453.         ERRORS((stderr, "cfe.init failed, %dn",ret))
  454.     }
  455.     return(ret);
  456. }
  457. //---------------------------------------------------------------------------
  458. //
  459. //  Function:     ModifyAces
  460. //
  461. //  Synopsis:     modifies the aces for the specified file(s)
  462. //
  463. //  Arguments:    IN [filename] - name of file(s) to modify the aces on
  464. //                IN [emode]  - mode of operation
  465. //                IN [option] - requested option
  466. //                IN [astart] - start of arguments for each option
  467. //                IN [aend]   - end of arguments for each option
  468. //
  469. //----------------------------------------------------------------------------
  470. ULONG ModifyAces(CHAR *filename,
  471.                  MODE emode,
  472.                  ULONG option,
  473.                  CHAR *argv[],
  474.                  LONG astart[], LONG aend[])
  475. {
  476.     CDaclWrap cdw;
  477.     CFileEnumerate cfe(option & OPTION_TREE);
  478.     WCHAR *user = NULL;
  479.     ULONG access;
  480.     ULONG ret = ERROR_SUCCESS;
  481.     WCHAR *pwfilename;
  482.     ULONG curoption;
  483.     VERBOSER((stderr, "user:permission pairsn"))
  484.     // first proces the command line args to build up the new ace
  485.     for (ULONG j = 0, k = 1;j < MAX_OPTIONS ; k <<= 1, j++ )
  486.     {
  487.         curoption = k;
  488.         if (option & k)
  489.         {
  490.             for (LONG q = astart[j];
  491.                       q < aend[j] ; q++ )
  492.             {
  493.                 VERBOSER((stderr, "      %sn",argv[q]))
  494.                 if ((k & OPTION_GRANT) || (k & OPTION_REPLACE))
  495.                 {
  496.                     if (!GetUserAndAccess(argv[q], &user, &access))
  497.                     {
  498.                         if (user)
  499.                             LocalFree(user);
  500.                         return(ERROR_BAD_ARGUMENTS);
  501.                     }
  502.                     if (GENERIC_NONE == access)
  503.                     {
  504.                         if (!(k & OPTION_REPLACE))
  505.                         {
  506.                             if (user)
  507.                                 LocalFree(user);
  508.                             return(ERROR_BAD_ARGUMENTS);
  509.                         }
  510.                     }
  511.                 } else
  512.                 {
  513.                     user = mbstowcs(argv[q]);
  514.                     access = GENERIC_NONE;
  515.                 }
  516.                 VERBOSER((stderr, "OPTION = %d, USER = %ws, ACCESS = %lxn",
  517.                        option,
  518.                        user,
  519.                        access))
  520.                 if (ERROR_SUCCESS != (ret = cdw.SetAccess(curoption,
  521.                                                      user,
  522.                                                      NULL,
  523.                                                      access)))
  524.                 {
  525.                     ERRORS((stderr, "SetAccess for %ws:%lx failed, %dn",
  526.                            user,
  527.                            access,
  528.                            ret))
  529.                     LocalFree(user);
  530.                     return(ret);
  531.                 }
  532.                 LocalFree(user);
  533.                 user = NULL;
  534.             }
  535.         }
  536.     }
  537.     BOOL fdir;
  538.     if (emode == MODE_REPLACE)
  539.     {
  540.         CHAR well[MAX_PATH];
  541.         CHAR msgbuf[MAX_PATH];
  542.         printmessage(stdout,MSG_CACLS_ARE_YOU_SURE, NULL);
  543.         FormatMessageA(FORMAT_MESSAGE_FROM_HMODULE, NULL, MSG_CACLS_Y, 0,
  544.                       msgbuf, MAX_PATH, NULL);
  545.         fgets(well,MAX_PATH,stdin);
  546.         // remove the trailing return
  547.         if ('n' == well[strlen(well) - sizeof(CHAR)])
  548.             well[strlen(well) - sizeof(CHAR)] = '';
  549.         if (0 != _stricmp(well, msgbuf))
  550.         {
  551.             FormatMessageA(FORMAT_MESSAGE_FROM_HMODULE, NULL, MSG_CACLS_YES, 0,
  552.                           msgbuf, MAX_PATH, NULL);
  553.             if (0 != _stricmp(well, msgbuf))
  554.                 return(ERROR_SUCCESS);
  555.         }
  556.     }
  557.     if (NO_ERROR == (ret = cfe.Init(filename, &pwfilename, &fdir)))
  558.     {
  559.         while ( (NO_ERROR == ret) ||
  560.                 ( ( (ERROR_ACCESS_DENIED == ret ) || (ERROR_SHARING_VIOLATION == ret) )&&
  561.                   (option & OPTION_CONTINUE_ON_ERROR) ) )
  562.         {
  563.             CFileSecurity cfs(pwfilename);
  564.             if (NO_ERROR == (ret = cfs.Init()))
  565.             {
  566.                 if (NO_ERROR != (ret = cfs.SetFS(emode == MODE_REPLACE ? FALSE : TRUE, &cdw, fdir)))
  567.                 {
  568.                     if (!(((ERROR_ACCESS_DENIED == ret) || (ERROR_SHARING_VIOLATION == ret)) &&
  569.                           (option & OPTION_CONTINUE_ON_ERROR)))
  570.                     {
  571.                         ERRORS((stderr, "SetFS on %ws failed %ldn",pwfilename, ret))
  572.                         return(ret);
  573.                     }
  574.                 }
  575.             }
  576.             else
  577.             {
  578.                //
  579.                // If the error is access denied or sharing violation and we are to continue on error,
  580.                // then keep going. Otherwise bail out here.
  581.                //
  582.                if (!(((ERROR_ACCESS_DENIED == ret) || (ERROR_SHARING_VIOLATION == ret)) &&
  583.                    (option & OPTION_CONTINUE_ON_ERROR))) {
  584.                   ERRORS((stderr, "init failed, %dn",ret))
  585.                   return(ret);
  586.                }
  587.             }
  588.             if (NO_ERROR == ret)
  589.             {
  590.                 if (fdir)
  591.                 {
  592.                     printmessage(stdout, MSG_CACLS_PROCESSED_DIR, NULL);
  593.                     wprintf(L"%s",  pwfilename);
  594.                 }
  595.                 else
  596.                 {
  597.                     printmessage(stdout, MSG_CACLS_PROCESSED_FILE, NULL);
  598.                     wprintf(L"%s",  pwfilename);
  599.                 }
  600.             }
  601.             else if (ERROR_ACCESS_DENIED == ret)
  602.             {
  603.                 printmessage(stdout, MSG_CACLS_ACCESS_DENIED, NULL);
  604.                 wprintf(L"%s",  pwfilename);
  605.             }
  606.             else if (ret == ERROR_SHARING_VIOLATION)
  607.             {
  608.                 printmessage(stdout, MSG_CACLS_SHARING_VIOLATION, NULL);
  609.                 wprintf(L"%s",  pwfilename);
  610.             }
  611.             if ( (NO_ERROR == ret) ||
  612.                  ( ( (ERROR_ACCESS_DENIED == ret ) || (ERROR_SHARING_VIOLATION == ret) ) &&
  613.                    (option & OPTION_CONTINUE_ON_ERROR) ) )
  614.                 ret = cfe.Next(&pwfilename, &fdir);
  615.         }
  616.         switch (ret)
  617.         {
  618.             case ERROR_NO_MORE_FILES:
  619.                 ret = ERROR_SUCCESS;
  620.                 break;
  621.             case ERROR_ACCESS_DENIED:
  622.             case ERROR_SHARING_VIOLATION:
  623.                 break;
  624.             case ERROR_SUCCESS:
  625.                 break;
  626.             default:
  627.                 DISPLAY((stderr, "%ws failed: %dn", pwfilename, ret))
  628.                 break;
  629.         }
  630.     } else
  631.         ERRORS((stderr, "file enumeration failed to initialize %ws, %ldn",pwfilename, ret))
  632.     if (ret == ERROR_NO_MORE_FILES)
  633.     {
  634.         ret = ERROR_SUCCESS;
  635.     }
  636.     if (ret != ERROR_SUCCESS)
  637.     {
  638.         ERRORS((stderr, "Enumeration failed, %dn",ret))
  639.     }
  640.     return(ret);
  641. }
  642. #if DBG
  643. //---------------------------------------------------------------------------
  644. //
  645. //  Function:     DebugEnumerate
  646. //
  647. //  Synopsis:     debug function
  648. //
  649. //  Arguments:    IN [filename] - file name
  650. //                IN [option]   - option
  651. //
  652. //----------------------------------------------------------------------------
  653. ULONG DebugEnumerate(CHAR *filename, ULONG option)
  654. {
  655.     CFileEnumerate cfe(option & OPTION_TREE);
  656.     WCHAR *pwfilename;
  657.     BOOL fdir;
  658.     ULONG ret;
  659.     ret = cfe.Init(filename, &pwfilename, &fdir);
  660.     while ( (ERROR_SUCCESS == ret) ||
  661.             ( (ERROR_ACCESS_DENIED == ret ) &&
  662.               (option & OPTION_CONTINUE_ON_ERROR) ) )
  663.     {
  664.         if (fdir)
  665.             printf("dir  name = %ws%wsn",pwfilename,
  666.                    ERROR_ACCESS_DENIED == ret ? L"ACCESS DENIED" : L"");
  667.         else
  668.             printf("file name = %ws%wsn",pwfilename,
  669.                    ERROR_ACCESS_DENIED == ret ? L"ACCESS DENIED" : L"");
  670.         ret = cfe.Next(&pwfilename, &fdir);
  671.     }
  672.     if (ret == ERROR_ACCESS_DENIED)
  673.     {
  674.         if (fdir)
  675.             printf("dir  name = %ws%wsn",pwfilename,
  676.                    ERROR_ACCESS_DENIED == ret ? L"ACCESS DENIED" : L"");
  677.         else
  678.             printf("file name = %ws%wsn",pwfilename,
  679.                    ERROR_ACCESS_DENIED == ret ? L"ACCESS DENIED" : L"");
  680.     }
  681.     if (ret != ERROR_NO_MORE_FILES)
  682.         printf("Enumeration failed, %dn",ret);
  683.     return(ret);
  684. }
  685. #endif
  686. //---------------------------------------------------------------------------
  687. //
  688. //  Function:     GetUserAccess
  689. //
  690. //  Synopsis:     parses an input string for user:access
  691. //
  692. //  Arguments:    IN  [arg]    - input string to parse
  693. //                OUT [user]   - user if found
  694. //                OUT [access] - access if found
  695. //
  696. //----------------------------------------------------------------------------
  697. BOOL GetUserAndAccess(CHAR *arg, WCHAR **user, ULONG *access)
  698. {
  699.     CHAR *saccess = strchr(arg,':');
  700.     if (saccess)
  701.     {
  702.         *saccess = NULL;
  703.         saccess++;
  704.         if (strchr(saccess,':'))
  705.             return(FALSE);
  706.         *user = mbstowcs(arg);
  707.         if (0 == _stricmp(saccess,"F"))
  708.         {
  709.             *access = ( STANDARD_RIGHTS_ALL |
  710.                         FILE_READ_DATA |
  711.                         FILE_WRITE_DATA |
  712.                         FILE_APPEND_DATA |
  713.                         FILE_READ_EA |
  714.                         FILE_WRITE_EA |
  715.                         FILE_EXECUTE |
  716.                         FILE_DELETE_CHILD |
  717.                         FILE_READ_ATTRIBUTES |
  718.                         FILE_WRITE_ATTRIBUTES );
  719.         }
  720.         else if (0 == _stricmp(saccess,"R"))
  721.         {
  722.             *access = FILE_GENERIC_READ | FILE_EXECUTE;
  723.         }
  724.         else if (0 == _stricmp(saccess,"C"))
  725.         {
  726.             *access = FILE_GENERIC_WRITE | FILE_GENERIC_READ | FILE_EXECUTE | DELETE;
  727.         }
  728.         else if (0 == _stricmp(saccess,"N"))
  729.         {
  730.             *access = GENERIC_NONE;
  731.         }
  732.         else if (0 == _stricmp(saccess,"W"))
  733.         {
  734.             *access = FILE_GENERIC_WRITE | FILE_EXECUTE;
  735.         }
  736.         else
  737.             return(FALSE);
  738.         return(TRUE);
  739.     }
  740.     return(FALSE);
  741. }
  742. //---------------------------------------------------------------------------
  743. //
  744. //  Function:     mbstowcs
  745. //
  746. //  Synopsis:     converts char to wchar, allocates space for wchar
  747. //
  748. //  Arguments:    IN [aname] - char string
  749. //
  750. //----------------------------------------------------------------------------
  751. WCHAR *mbstowcs(char *aname )
  752. {
  753.     if (aname)
  754.     {
  755.         WCHAR *pwname = NULL;
  756.         pwname = (WCHAR *)LocalAlloc(LMEM_FIXED, sizeof(WCHAR) * (strlen(aname)+1));
  757.         if (NULL == pwname)
  758.             return(NULL);
  759.         WCHAR *prwname = pwname;
  760.         if (MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
  761.                                 aname, -1,
  762.                                 prwname, sizeof(WCHAR)*(strlen(aname)+1)) == 0)
  763.             return(NULL);
  764.         return(pwname);
  765.     } else
  766.         return(NULL);
  767. }
  768. //----------------------------------------------------------------------------
  769. //
  770. //  Function:
  771. //
  772. //  Synopsis:
  773. //
  774. //  Arguments:
  775. //
  776. //----------------------------------------------------------------------------
  777. BOOLEAN OpenToken(PHANDLE ph)
  778. {
  779.     HANDLE hprocess;
  780.     hprocess = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
  781.     if (hprocess == NULL)
  782.         return(FALSE);
  783.     if (OpenProcessToken(hprocess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ph))
  784.     {
  785.         CloseHandle(hprocess);
  786.         return(TRUE);
  787.     }
  788.     CloseHandle(hprocess);
  789.     return(FALSE);
  790. }
  791. //----------------------------------------------------------------------------
  792. //
  793. //  Function:     printfsid
  794. //
  795. //  Synopsis:     prints a NT SID
  796. //
  797. //  Arguments:    IN [psid] - pointer to the sid to print
  798. //
  799. //----------------------------------------------------------------------------
  800. void printfsid(SID *psid, ULONG *outputoffset)
  801. {
  802. #if DBG
  803.     if ((Debug & DEBUG_VERBOSE) || (Debug & DEBUG_DISPLAY_SIDS))
  804.     {
  805.         printf("S-%lx",psid->Revision);
  806.         if ( (psid->IdentifierAuthority.Value[0] != 0) ||
  807.              (psid->IdentifierAuthority.Value[1] != 0) )
  808.         {
  809.             printf("0x%02hx%02hx%02hx%02hx%02hx%02hx",
  810.                         (USHORT)psid->IdentifierAuthority.Value[0],
  811.                         (USHORT)psid->IdentifierAuthority.Value[1],
  812.                         (USHORT)psid->IdentifierAuthority.Value[2],
  813.                         (USHORT)psid->IdentifierAuthority.Value[3],
  814.                         (USHORT)psid->IdentifierAuthority.Value[4],
  815.                         (USHORT)psid->IdentifierAuthority.Value[5] );
  816.         } else
  817.         {
  818.             printf("-%lu",
  819.                    (ULONG)psid->IdentifierAuthority.Value[5]          +
  820.                    (ULONG)(psid->IdentifierAuthority.Value[4] <<  8)  +
  821.                    (ULONG)(psid->IdentifierAuthority.Value[3] << 16)  +
  822.                    (ULONG)(psid->IdentifierAuthority.Value[2] << 24) );
  823.         }
  824.         if ( 0 < psid->SubAuthorityCount )
  825.         {
  826.             for (int k = 0; k < psid->SubAuthorityCount; k++ )
  827.             {
  828.                 printf("-%d",psid->SubAuthority[k]);
  829.             }
  830.         }
  831.     }
  832. #endif
  833.     ULONG ret;
  834.     CAccount ca(psid, NULL);
  835.     WCHAR *domain = NULL;
  836.     WCHAR *user;
  837.     if (NO_ERROR == ( ret = ca.GetAccountDomain(&domain) ) )
  838.     {
  839.         if ( (NULL == domain) || (0 == wcslen(domain)) )
  840.         {
  841.             fprintf(stdout, " ");
  842.             *outputoffset +=1;
  843.         }
  844.         else
  845.         {
  846.             fprintf(stdout, " ");
  847.             wprintf(L"%s",  domain);
  848. fprintf(stdout, "\");
  849.             *outputoffset += 2 + wcslen( domain );;
  850.         }
  851.         if (NO_ERROR == ( ret = ca.GetAccountName(&user) ) )
  852.         {
  853.             wprintf(L"%s",  user);
  854. fprintf(stdout, ":");
  855.             *outputoffset += 1 + wcslen(user);
  856.         } else
  857.         {
  858.             *outputoffset += printmessage(stdout, MSG_CACLS_NAME_NOT_FOUND, NULL);
  859.             ERRORS((stderr, "(%lx)",ret))
  860.         }
  861.     } else
  862.     {
  863.         *outputoffset+= printmessage(stdout, MSG_CACLS_DOMAIN_NOT_FOUND, NULL);
  864.         ERRORS((stderr, "(%lx)",ret))
  865.     }
  866.     VERBOSE((stderr, "n"))
  867. }
  868. //----------------------------------------------------------------------------
  869. //
  870. //  Function:     printface
  871. //
  872. //  Synopsis:     prints the specifed ace
  873. //
  874. //  Arguments:    IN [paceh] - input ace (header)
  875. //                IN [fdir]  - TRUE = directory (different display options)
  876. //
  877. //----------------------------------------------------------------------------
  878. void printface(ACE_HEADER *paceh, BOOL fdir, ULONG outputoffset)
  879. {
  880.     VERBOSE((stderr, "  "))
  881.     VERBOSER((stderr, "npaceh->AceType  = %xn",paceh->AceType  ))
  882.     VERBOSER((stderr, "paceh->AceFlags = %xn",paceh->AceFlags ))
  883.     VERBOSER((stderr, "paceh->AceSize  = %xn",paceh->AceSize  ))
  884.     ACCESS_ALLOWED_ACE *paaa = (ACCESS_ALLOWED_ACE *)paceh;
  885.     printfsid((SID *)&(paaa->SidStart),&outputoffset);
  886.     if (paceh->AceFlags & OBJECT_INHERIT_ACE      )
  887.     {
  888.         outputoffset+= printmessage(stdout, MSG_CACLS_OBJECT_INHERIT, NULL);
  889.     }
  890.     if (paceh->AceFlags & CONTAINER_INHERIT_ACE   )
  891.     {
  892.         outputoffset+= printmessage(stdout, MSG_CACLS_CONTAINER_INHERIT, NULL);
  893.     }
  894.     if (paceh->AceFlags & NO_PROPAGATE_INHERIT_ACE)
  895.     {
  896.         outputoffset+= printmessage(stdout, MSG_CACLS_NO_PROPAGATE_INHERIT, NULL);
  897.     }
  898.     if (paceh->AceFlags & INHERIT_ONLY_ACE        )
  899.     {
  900.         outputoffset+= printmessage(stdout, MSG_CACLS_INHERIT_ONLY, NULL);
  901.     }
  902.     if (paceh->AceType == ACCESS_DENIED_ACE_TYPE)
  903.     {
  904.             DISPLAY_MASK((stderr, "(DENIED)"))
  905.             VERBOSE((stderr, "(DENIED)"))
  906.     }
  907.     printfmask(paaa->Mask, paceh->AceType, fdir, outputoffset);
  908.     fprintf(stdout, "n");
  909. }
  910. //----------------------------------------------------------------------------
  911. //
  912. //  Function:     printfmask
  913. //
  914. //  Synopsis:     prints the access mask
  915. //
  916. //  Arguments:    IN [mask]    - the access mask
  917. //                IN [acetype] -  allowed/denied
  918. //                IN [fdir]    - TRUE = directory
  919. //
  920. //----------------------------------------------------------------------------
  921. CHAR  *aRightsStr[] = { "STANDARD_RIGHTS_ALL",
  922.                         "DELETE",
  923.                         "READ_CONTROL",
  924.                         "WRITE_DAC",
  925.                         "WRITE_OWNER",
  926.                         "SYNCHRONIZE",
  927.                         "STANDARD_RIGHTS_REQUIRED",
  928.                         "SPECIFIC_RIGHTS_ALL",
  929.                         "ACCESS_SYSTEM_SECURITY",
  930.                         "MAXIMUM_ALLOWED",
  931.                         "GENERIC_READ",
  932.                         "GENERIC_WRITE",
  933.                         "GENERIC_EXECUTE",
  934.                         "GENERIC_ALL",
  935.                         "FILE_GENERIC_READ",
  936.                         "FILE_GENERIC_WRITE",
  937.                         "FILE_GENERIC_EXECUTE",
  938.                         "FILE_READ_DATA",
  939.                         //FILE_LIST_DIRECTORY
  940.                         "FILE_WRITE_DATA",
  941.                         //FILE_ADD_FILE
  942.                         "FILE_APPEND_DATA",
  943.                         //FILE_ADD_SUBDIRECTORY
  944.                         "FILE_READ_EA",
  945.                         "FILE_WRITE_EA",
  946.                         "FILE_EXECUTE",
  947.                         //FILE_TRAVERSE
  948.                         "FILE_DELETE_CHILD",
  949.                         "FILE_READ_ATTRIBUTES",
  950.                         "FILE_WRITE_ATTRIBUTES" };
  951. #define NUMRIGHTS 26
  952. ULONG aRights[NUMRIGHTS] = { STANDARD_RIGHTS_ALL  ,
  953.                          DELETE                   ,
  954.                          READ_CONTROL             ,
  955.                          WRITE_DAC                ,
  956.                          WRITE_OWNER              ,
  957.                          SYNCHRONIZE              ,
  958.                          STANDARD_RIGHTS_REQUIRED ,
  959.                          SPECIFIC_RIGHTS_ALL      ,
  960.                          ACCESS_SYSTEM_SECURITY   ,
  961.                          MAXIMUM_ALLOWED          ,
  962.                          GENERIC_READ             ,
  963.                          GENERIC_WRITE            ,
  964.                          GENERIC_EXECUTE          ,
  965.                          GENERIC_ALL              ,
  966.                          FILE_GENERIC_READ        ,
  967.                          FILE_GENERIC_WRITE       ,
  968.                          FILE_GENERIC_EXECUTE     ,
  969.                          FILE_READ_DATA           ,
  970.                          //FILE_LIST_DIRECTORY    ,
  971.                          FILE_WRITE_DATA          ,
  972.                          //FILE_ADD_FILE          ,
  973.                          FILE_APPEND_DATA         ,
  974.                          //FILE_ADD_SUBDIRECTORY  ,
  975.                          FILE_READ_EA             ,
  976.                          FILE_WRITE_EA            ,
  977.                          FILE_EXECUTE             ,
  978.                          //FILE_TRAVERSE          ,
  979.                          FILE_DELETE_CHILD        ,
  980.                          FILE_READ_ATTRIBUTES     ,
  981.                          FILE_WRITE_ATTRIBUTES  };
  982. void printfmask(ULONG mask, UCHAR acetype, BOOL fdir, ULONG outputoffset)
  983. {
  984.     ULONG savmask = mask;
  985.     VERBOSER((stderr, "mask = %08lx ", mask))
  986.     DISPLAY_MASK((stderr, "mask = %08lxn", mask))
  987.     VERBOSE((stderr, "    "))
  988. #if DBG
  989.     if (!(Debug & (DEBUG_VERBOSE | DEBUG_DISPLAY_MASK)))
  990.     {
  991. #endif
  992.         if ((acetype == ACCESS_ALLOWED_ACE_TYPE) &&
  993.                    (mask == (FILE_GENERIC_READ | FILE_EXECUTE)))
  994.         {
  995.             printmessage(stdout, MSG_CACLS_READ, NULL);
  996.         } else if ((acetype == ACCESS_ALLOWED_ACE_TYPE) &&
  997.                    (mask == (FILE_GENERIC_WRITE | FILE_GENERIC_READ | FILE_EXECUTE | DELETE)))
  998.         {
  999.             printmessage(stdout, MSG_CACLS_CHANGE, NULL);
  1000.         } else if ((acetype == ACCESS_ALLOWED_ACE_TYPE) &&
  1001.                    (mask == (GENERIC_WRITE | GENERIC_READ | GENERIC_EXECUTE | DELETE)))
  1002.         {
  1003.             printmessage(stdout, MSG_CACLS_CHANGE, NULL);
  1004.         } else if ((acetype == ACCESS_ALLOWED_ACE_TYPE) &&
  1005.                    (mask ==  ( STANDARD_RIGHTS_ALL |
  1006.                              FILE_READ_DATA |
  1007.                              FILE_WRITE_DATA |
  1008.                              FILE_APPEND_DATA |
  1009.                              FILE_READ_EA |
  1010.                              FILE_WRITE_EA |
  1011.                              FILE_EXECUTE |
  1012.                              FILE_DELETE_CHILD |
  1013.                              FILE_READ_ATTRIBUTES |
  1014.                              FILE_WRITE_ATTRIBUTES )) )
  1015.         {
  1016.             printmessage(stdout, MSG_CACLS_FULL_CONTROL, NULL);
  1017.         } else if ((acetype == ACCESS_ALLOWED_ACE_TYPE) &&
  1018.                    (mask ==  GENERIC_ALL))
  1019.         {
  1020.             printmessage(stdout, MSG_CACLS_FULL_CONTROL, NULL);
  1021.         } else if ((acetype == ACCESS_DENIED_ACE_TYPE) &&
  1022.                    (mask == GENERIC_ALL))
  1023.         {
  1024.             printmessage(stdout, MSG_CACLS_NONE, NULL);
  1025.         } else if ((acetype == ACCESS_DENIED_ACE_TYPE) &&
  1026.                    (mask ==  ( STANDARD_RIGHTS_ALL |
  1027.                              FILE_READ_DATA |
  1028.                              FILE_WRITE_DATA |
  1029.                              FILE_APPEND_DATA |
  1030.                              FILE_READ_EA |
  1031.                              FILE_WRITE_EA |
  1032.                              FILE_EXECUTE |
  1033.                              FILE_DELETE_CHILD |
  1034.                              FILE_READ_ATTRIBUTES |
  1035.                              FILE_WRITE_ATTRIBUTES )) )
  1036.         {
  1037.             printmessage(stdout, MSG_CACLS_NONE, NULL);
  1038.         } else
  1039.         {
  1040.             if (acetype == ACCESS_DENIED_ACE_TYPE)
  1041.                 printmessage(stdout, MSG_CACLS_DENY, NULL);
  1042.             printmessage(stdout, MSG_CACLS_SPECIAL_ACCESS, NULL);
  1043.             for (int k = 0; k<NUMRIGHTS ; k++ )
  1044.             {
  1045.                 if ((mask & aRights[k]) == aRights[k])
  1046.                 {
  1047.                     fprintf(stdout, "%*s%sn",outputoffset, " ", aRightsStr[k]);
  1048.                 }
  1049.                 if (mask == 0)
  1050.                     break;
  1051.             }
  1052.         }
  1053. #if DBG
  1054.     } else
  1055.     {
  1056.         if (Debug & (DEBUG_DISPLAY_MASK | DEBUG_VERBOSE))
  1057.         {
  1058.             printf("n");
  1059.             for (int k = 0; k<NUMRIGHTS ; k++ )
  1060.             {
  1061.                 if ((mask & aRights[k]) == aRights[k])
  1062.                 {
  1063.                     if (mask != savmask) printf(" |n");
  1064.                     printf("    %s",aRightsStr[k]);
  1065.                     mask &= ~aRights[k];
  1066.                 }
  1067.                 if (mask == 0)
  1068.                 break;
  1069.             }
  1070.         }
  1071.         VERBOSE((stderr, "=%x",mask))
  1072.         if (mask != 0)
  1073.             DISPLAY((stderr, "=%x/%x",mask,savmask))
  1074.     }
  1075. #endif
  1076.     fprintf(stdout, " ");
  1077. }
  1078. //----------------------------------------------------------------------------
  1079. //
  1080. //  Function:     printmessage
  1081. //
  1082. //  Synopsis:     prints a message, either from the local message file, or from the system
  1083. //
  1084. //  Arguments:    IN [fp]    - stderr, stdio, etc.
  1085. //                IN [messageID] - variable argument list
  1086. //
  1087. //  Returns:      length of the output buffer
  1088. //
  1089. //----------------------------------------------------------------------------
  1090. ULONG  printmessage (FILE* fp, DWORD messageID, ...)
  1091. {
  1092.     WCHAR  messagebuffer[4096];
  1093.         va_list ap;
  1094.     va_start(ap, messageID);
  1095.     if (!FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, NULL, messageID, 0,
  1096.                       messagebuffer, 4095, &ap))
  1097.        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, messageID, 0,
  1098.                         messagebuffer, 4095, &ap);
  1099.     fwprintf(fp,  messagebuffer);
  1100.     va_end(ap);
  1101.     return(wcslen(messagebuffer));
  1102. }