home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / winnt / cacls / t2.cxx < prev    next >
C/C++ Source or Header  |  1997-10-02  |  40KB  |  1,185 lines

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