home *** CD-ROM | disk | FTP | other *** search
/ Borland Programmer's Resource / Borland_Programmers_Resource_CD_1995.iso / code / ntfiles / files.c < prev    next >
C/C++ Source or Header  |  1995-05-18  |  6KB  |  274 lines

  1. /* DISKUSE
  2.  
  3.     This program will list the filename, file owner and file size of every file in
  4.     a specified directory.
  5.  
  6.     AUTHOR:
  7.     Mike Frederick, University of Houston, May 11, 1994
  8.  
  9.     NOTES:
  10.     To get the file owner information, a call to the API GetFileSecurity should be
  11.     used.  However, there is a bug in the Windows NT 3.1 version of the API which
  12.     causes the request to fail if the owner of the file has denied access to the
  13.     calling user.  The API should check to see if the calling user has the
  14.     SE_BACKUP_NAME privilege enabled, but it does not.
  15.  
  16.     The work-around (supplied by MS PSS) is to enable SE_BACKUP_NAME, open the
  17.     file with the CreateFile API (with FILE_FLAG_BACKUP_SEMANTICS) and then call
  18.     GetKernelObjectSecurity on the open handle.
  19.  
  20.     LIMITS:
  21.     This program cannot report on files or directory totals greater than 2**32
  22.     bytes in size.
  23.  
  24. */
  25.  
  26. #include <stdio.h>
  27. #include <windows.h>
  28. #include <string.h>
  29. #include <malloc.h>
  30. #include <memory.h>
  31. #include <process.h>
  32.  
  33. #define CopyPathFile lstrcpy(downPath,FindPath);downPath [lstrlen(downPath)-3]=0;lstrcat(downPath,FileData.cFileName);
  34. #define SID_SIZE 100
  35. #define SD_SIZE 512
  36. #define PATH_SIZE 1024
  37.  
  38. /* Called routines */
  39.  
  40. dirtotal (const char *);
  41. void usage (void);
  42. BOOL AdjustProcessPrivs (LPTSTR PrivString, BOOL fEnable);
  43. BOOL GetFileOwner (const char * path, PSECURITY_DESCRIPTOR pSD);
  44.  
  45. DWORD GrandTotal = 0;
  46. int depth = -1;
  47.  
  48. /* Main routine */
  49.  
  50. UINT main (int argc, char *argv[]) {
  51.  
  52.     /* Check ARGs */
  53.  
  54.     if (argc < 2) usage ();
  55.  
  56.     /* Enable privs to allow bypassing file system protections */
  57.  
  58.     AdjustProcessPrivs (SE_BACKUP_NAME, TRUE);
  59.  
  60.     /* Call the directory scanner */
  61.  
  62.     dirtotal (argv [1]);
  63.  
  64.     /* Turn off privileges */
  65.  
  66.     AdjustProcessPrivs (NULL, FALSE);
  67.  
  68.     /* Print the total results */
  69.  
  70.     printf ("\n\nGrand Total is: %luK\n", GrandTotal);
  71.     return (0);
  72.  
  73. }
  74.  
  75. /* Tell the user the correct invocation syntax */
  76.  
  77. void usage (void)
  78. {
  79.     printf ("Usage: FILES path\n");
  80.     exit (0);
  81. }
  82.  
  83. /* Workhorse routine.  This routine is called recursively with the name of
  84.     every subdirectory. */
  85.  
  86. dirtotal (const char * path)
  87. {
  88.  
  89. WIN32_FIND_DATA
  90.     FileData;
  91.  
  92. HANDLE
  93.     hSearch;
  94.  
  95. BOOL
  96.     fFinished = FALSE,
  97.     od,
  98.     status;
  99.  
  100. DWORD
  101.     SizeTotal = 0,
  102.     usersize,
  103.     domainsize;
  104.  
  105. UCHAR
  106.     FindPath [PATH_SIZE],
  107.     downPath [PATH_SIZE],
  108.     SD [SD_SIZE],
  109.     sid [SID_SIZE],
  110.     LastSid [SID_SIZE],
  111.     userid [20],
  112.     domain [20];
  113.  
  114. PSECURITY_DESCRIPTOR
  115.     pSD = (PSECURITY_DESCRIPTOR) &SD;
  116.  
  117. PSID
  118.     psid = &sid,
  119.     LastSidPtr = &LastSid;
  120.  
  121. SID_NAME_USE
  122.     SNU;
  123.  
  124. PSID_NAME_USE
  125.     pSNU = &SNU;
  126.  
  127. int
  128.     i;
  129.  
  130.  
  131.     depth++;
  132.  
  133.     /* Make a working copy of the input path */
  134.  
  135.     lstrcpy (FindPath, path); lstrcat (FindPath, "*.*");
  136.     printf ("%s\n\n", path);
  137.  
  138.     /* Start the wildcard search */
  139.  
  140.     hSearch = FindFirstFile (FindPath, &FileData);
  141.     if ((int) hSearch == -1)
  142.     {
  143.         printf ("Cannot access any of these files or subdirectories\n");
  144.         return (0);
  145.     }
  146.  
  147.     while (!fFinished) {
  148.  
  149.         /* If the found file is not a directory, report its size */
  150.  
  151.         if (!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  152.             CopyPathFile;
  153.             if (GetFileOwner (downPath, pSD))
  154.             {
  155.                 status = GetSecurityDescriptorOwner (pSD, &psid, &od);
  156.  
  157.                 /* If this file is owned by the same SID as the previous file examined, don't
  158.                     go through the overhead of the LookupAccountSid again. */
  159.  
  160.                 if (!EqualSid (psid, LastSid))
  161.                 {
  162.                     usersize = sizeof (userid);
  163.                     domainsize = sizeof (domain);
  164.                     if (!LookupAccountSid ("", psid, userid, &usersize, domain, &domainsize, pSNU))
  165.                     {
  166.                         status = GetLastError ();
  167.                     }
  168.                     CopySid (sizeof (LastSid), LastSid, psid);
  169.                 }
  170.             }
  171.             else
  172.             {
  173.  
  174.                 /* Use dummy values when the real owner cannot be determined */
  175.  
  176.                 lstrcpy (domain, "Unknown");
  177.                 lstrcpy (userid, "No_file_access");
  178.  
  179.                 /* Clear the "LastSid" to force a lookup after a file access is not allowed */
  180.  
  181.                 for (i = 0; i < SID_SIZE; i++) LastSid [i] = 0;
  182.             }
  183.             printf ("+ %12lu %s\\%s %s\n", FileData.nFileSizeLow, domain, userid, FileData.cFileName);
  184.             SizeTotal += FileData.nFileSizeLow / 1024;
  185.         }
  186.         else
  187.         {
  188.  
  189.         /* If the found file is a directory, call this routine with the new path.
  190.            Ignore the directories "." and "..". */
  191.  
  192.             if (lstrcmp (FileData.cFileName, TEXT (".")) != 0 &&
  193.                 lstrcmp (FileData.cFileName, TEXT ("..")) != 0)
  194.             {
  195.                 CopyPathFile;
  196.                 lstrcat (downPath, "\\");                  
  197.                 dirtotal (downPath);
  198.             }
  199.         }
  200.  
  201.         /* Look for more files */
  202.  
  203.         if (!FindNextFile (hSearch, &FileData))    {
  204.             if (GetLastError () == ERROR_NO_MORE_FILES) fFinished = TRUE;
  205.         }
  206.     }
  207.  
  208.     /* Close the wildcard search */
  209.  
  210.     FindClose (hSearch);
  211.  
  212.     /* Print the directory totals */
  213.  
  214.     printf ("\nTotal size: %luK (%luM)\n", SizeTotal, SizeTotal / 1024);
  215.     GrandTotal += SizeTotal;
  216.     depth--;
  217.  
  218. }
  219.  
  220. BOOL GetFileOwner (const char * path, PSECURITY_DESCRIPTOR pSD)
  221.  
  222. /* GetFileOwner
  223.  
  224.     Because of a problem with the GetFileSecurity API, you must this kludge to
  225.     get the ownership of a file to which you have no file access permissions.
  226.  
  227. */
  228.  
  229. {
  230.  
  231. HANDLE
  232.     hFile;
  233.  
  234. DWORD
  235.     status,
  236.     SizeRequired;
  237.  
  238.     hFile = CreateFile (
  239.         path,
  240.         GENERIC_READ,
  241.         FILE_SHARE_WRITE,
  242.         NULL,
  243.         OPEN_EXISTING,
  244.         FILE_FLAG_BACKUP_SEMANTICS,
  245.         NULL);
  246.     status = GetLastError ();
  247.  
  248.     if (status == ERROR_SUCCESS)
  249.     {
  250.         status = GetKernelObjectSecurity (
  251.             hFile,
  252.             OWNER_SECURITY_INFORMATION,
  253.             pSD,
  254.             SID_SIZE,
  255.             &SizeRequired
  256.             );
  257.         if (status)
  258.         {
  259.             CloseHandle (hFile);
  260.             return TRUE;
  261.         }
  262.         else
  263.         {
  264.             printf ("Error calling API GetKernelObjectSecurity = %d\n", status);
  265.             printf ("GetLastError = %d\n", GetLastError ());
  266.         }
  267.     }
  268.     else
  269.         printf ("Error calling API CreateFile = %d\n", status);
  270.     return FALSE;
  271. }
  272.  
  273.  
  274.