home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Borland Programmer's Resource
/
Borland_Programmers_Resource_CD_1995.iso
/
code
/
ntfiles
/
files.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-18
|
6KB
|
274 lines
/* DISKUSE
This program will list the filename, file owner and file size of every file in
a specified directory.
AUTHOR:
Mike Frederick, University of Houston, May 11, 1994
NOTES:
To get the file owner information, a call to the API GetFileSecurity should be
used. However, there is a bug in the Windows NT 3.1 version of the API which
causes the request to fail if the owner of the file has denied access to the
calling user. The API should check to see if the calling user has the
SE_BACKUP_NAME privilege enabled, but it does not.
The work-around (supplied by MS PSS) is to enable SE_BACKUP_NAME, open the
file with the CreateFile API (with FILE_FLAG_BACKUP_SEMANTICS) and then call
GetKernelObjectSecurity on the open handle.
LIMITS:
This program cannot report on files or directory totals greater than 2**32
bytes in size.
*/
#include <stdio.h>
#include <windows.h>
#include <string.h>
#include <malloc.h>
#include <memory.h>
#include <process.h>
#define CopyPathFile lstrcpy(downPath,FindPath);downPath [lstrlen(downPath)-3]=0;lstrcat(downPath,FileData.cFileName);
#define SID_SIZE 100
#define SD_SIZE 512
#define PATH_SIZE 1024
/* Called routines */
dirtotal (const char *);
void usage (void);
BOOL AdjustProcessPrivs (LPTSTR PrivString, BOOL fEnable);
BOOL GetFileOwner (const char * path, PSECURITY_DESCRIPTOR pSD);
DWORD GrandTotal = 0;
int depth = -1;
/* Main routine */
UINT main (int argc, char *argv[]) {
/* Check ARGs */
if (argc < 2) usage ();
/* Enable privs to allow bypassing file system protections */
AdjustProcessPrivs (SE_BACKUP_NAME, TRUE);
/* Call the directory scanner */
dirtotal (argv [1]);
/* Turn off privileges */
AdjustProcessPrivs (NULL, FALSE);
/* Print the total results */
printf ("\n\nGrand Total is: %luK\n", GrandTotal);
return (0);
}
/* Tell the user the correct invocation syntax */
void usage (void)
{
printf ("Usage: FILES path\n");
exit (0);
}
/* Workhorse routine. This routine is called recursively with the name of
every subdirectory. */
dirtotal (const char * path)
{
WIN32_FIND_DATA
FileData;
HANDLE
hSearch;
BOOL
fFinished = FALSE,
od,
status;
DWORD
SizeTotal = 0,
usersize,
domainsize;
UCHAR
FindPath [PATH_SIZE],
downPath [PATH_SIZE],
SD [SD_SIZE],
sid [SID_SIZE],
LastSid [SID_SIZE],
userid [20],
domain [20];
PSECURITY_DESCRIPTOR
pSD = (PSECURITY_DESCRIPTOR) &SD;
PSID
psid = &sid,
LastSidPtr = &LastSid;
SID_NAME_USE
SNU;
PSID_NAME_USE
pSNU = &SNU;
int
i;
depth++;
/* Make a working copy of the input path */
lstrcpy (FindPath, path); lstrcat (FindPath, "*.*");
printf ("%s\n\n", path);
/* Start the wildcard search */
hSearch = FindFirstFile (FindPath, &FileData);
if ((int) hSearch == -1)
{
printf ("Cannot access any of these files or subdirectories\n");
return (0);
}
while (!fFinished) {
/* If the found file is not a directory, report its size */
if (!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
CopyPathFile;
if (GetFileOwner (downPath, pSD))
{
status = GetSecurityDescriptorOwner (pSD, &psid, &od);
/* If this file is owned by the same SID as the previous file examined, don't
go through the overhead of the LookupAccountSid again. */
if (!EqualSid (psid, LastSid))
{
usersize = sizeof (userid);
domainsize = sizeof (domain);
if (!LookupAccountSid ("", psid, userid, &usersize, domain, &domainsize, pSNU))
{
status = GetLastError ();
}
CopySid (sizeof (LastSid), LastSid, psid);
}
}
else
{
/* Use dummy values when the real owner cannot be determined */
lstrcpy (domain, "Unknown");
lstrcpy (userid, "No_file_access");
/* Clear the "LastSid" to force a lookup after a file access is not allowed */
for (i = 0; i < SID_SIZE; i++) LastSid [i] = 0;
}
printf ("+ %12lu %s\\%s %s\n", FileData.nFileSizeLow, domain, userid, FileData.cFileName);
SizeTotal += FileData.nFileSizeLow / 1024;
}
else
{
/* If the found file is a directory, call this routine with the new path.
Ignore the directories "." and "..". */
if (lstrcmp (FileData.cFileName, TEXT (".")) != 0 &&
lstrcmp (FileData.cFileName, TEXT ("..")) != 0)
{
CopyPathFile;
lstrcat (downPath, "\\");
dirtotal (downPath);
}
}
/* Look for more files */
if (!FindNextFile (hSearch, &FileData)) {
if (GetLastError () == ERROR_NO_MORE_FILES) fFinished = TRUE;
}
}
/* Close the wildcard search */
FindClose (hSearch);
/* Print the directory totals */
printf ("\nTotal size: %luK (%luM)\n", SizeTotal, SizeTotal / 1024);
GrandTotal += SizeTotal;
depth--;
}
BOOL GetFileOwner (const char * path, PSECURITY_DESCRIPTOR pSD)
/* GetFileOwner
Because of a problem with the GetFileSecurity API, you must this kludge to
get the ownership of a file to which you have no file access permissions.
*/
{
HANDLE
hFile;
DWORD
status,
SizeRequired;
hFile = CreateFile (
path,
GENERIC_READ,
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
status = GetLastError ();
if (status == ERROR_SUCCESS)
{
status = GetKernelObjectSecurity (
hFile,
OWNER_SECURITY_INFORMATION,
pSD,
SID_SIZE,
&SizeRequired
);
if (status)
{
CloseHandle (hFile);
return TRUE;
}
else
{
printf ("Error calling API GetKernelObjectSecurity = %d\n", status);
printf ("GetLastError = %d\n", GetLastError ());
}
}
else
printf ("Error calling API CreateFile = %d\n", status);
return FALSE;
}