You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2829 lines
72 KiB
2829 lines
72 KiB
//
|
|
// Modification:
|
|
// oct.29, 1997 changed by a-zexu to debug bug#113977(incorrect output info).
|
|
// May 10, 1998 changed by a-zexu to debug bug#158667.
|
|
//
|
|
//
|
|
|
|
|
|
#include "PERMS.H"
|
|
|
|
|
|
PSID SidEveryone = NULL;
|
|
PSID SidOwnerGroup = NULL;
|
|
PSID SidFromLookupName = NULL;
|
|
PSID ASidFromLookupName[10];
|
|
PSID *AccountSids = NULL;
|
|
DWORD cbSidFromLookupName=0;
|
|
SAM_HANDLE SamServerHandle = NULL;
|
|
SAM_HANDLE SamDomainHandle = NULL;
|
|
ACCESS_MASK grant_mask = 0;
|
|
BOOL g_noAccess = FALSE;
|
|
BOOL owner_flag = FALSE;
|
|
BOOL owner_group = FALSE;
|
|
BOOL Local_Machine = TRUE;
|
|
ULONG Total_Sids=0;
|
|
BOOL inter_logon=FALSE; /* interactive login flag */
|
|
PSECURITY_DESCRIPTOR SidFromGetFileSecurity; /* address of security descriptor */
|
|
|
|
_cdecl main(int argc, char *argv[])
|
|
{
|
|
char
|
|
UserNameBuff[LSA_WIN_STANDARD_BUFFER_SIZE], /* user name buff */
|
|
SystemNameBuff[LSA_WIN_STANDARD_BUFFER_SIZE], /* system name buff */
|
|
FileNameBuff[LSA_WIN_STANDARD_BUFFER_SIZE], /* system name buff */
|
|
FileSystemNameBuff[LSA_WIN_STANDARD_BUFFER_SIZE], /* system name buff */
|
|
RefDFromLookupName[LSA_WIN_STANDARD_BUFFER_SIZE],
|
|
GeneralUseBuffer[LSA_WIN_STANDARD_BUFFER_SIZE],
|
|
LocalSystemName[MAX_COMPUTERNAME_LENGTH + 1],
|
|
FileName[LSA_WIN_STANDARD_BUFFER_SIZE],
|
|
FilePath[LSA_WIN_STANDARD_BUFFER_SIZE];
|
|
|
|
DWORD cchRefDFromLookupName=0,
|
|
SidsizeFromGetFileSecurity=0,
|
|
lpcbsdRequired=0,
|
|
SNameLen = MAX_COMPUTERNAME_LENGTH + 1;
|
|
|
|
SID_NAME_USE UseFromLookupName;
|
|
|
|
DWORD cchNameFromLookupSid;
|
|
char NameFromLookupSid[LSA_WIN_STANDARD_BUFFER_SIZE];
|
|
char RefDFromLookupSid[LSA_WIN_STANDARD_BUFFER_SIZE];
|
|
DWORD cchRefDFromLookupSid,
|
|
WStatus,
|
|
WNetSize = LSA_WIN_STANDARD_BUFFER_SIZE;
|
|
SID_NAME_USE UseFromLookupSid;
|
|
PSID usid; /* user SID pointer */
|
|
LPDWORD sidsize;
|
|
LPSTR User = NULL,
|
|
System,
|
|
Path,
|
|
File = NULL,
|
|
FileMachine = NULL;
|
|
LPDWORD domain_size;
|
|
PSID_NAME_USE psnu;
|
|
LPTSTR pbslash; /* address of string for back slash */
|
|
SECURITY_INFORMATION /* requested information */
|
|
si =(OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION
|
|
|DACL_SECURITY_INFORMATION);
|
|
DWORD cbsd, LastError; /* size of security descriptor buffer */
|
|
|
|
BOOL BoolStatus=TRUE;
|
|
int i, k, j;
|
|
ULONG ui;
|
|
BOOL sys=FALSE,
|
|
fl=FALSE,
|
|
LocalFlag=FALSE,
|
|
BackUpPriv=TRUE,
|
|
DriveFlag=FALSE,
|
|
RecurseFlag=FALSE,
|
|
RestorePriv=TRUE,
|
|
DirFlag=FALSE;
|
|
ULONG AccountSidsLength;
|
|
HANDLE TokenHandle,
|
|
FindFileHandle;
|
|
WIN32_FIND_DATA FindFileData;
|
|
|
|
// Set Back up privs for process
|
|
// Get our process token
|
|
if(!GetTokenHandle(&TokenHandle))
|
|
{
|
|
syserror(GetLastError());
|
|
return(TRUE);
|
|
}
|
|
|
|
// Have valid process token handle
|
|
// Now set the backup operator priv
|
|
|
|
if(!SetBackOperatorPriv(TokenHandle))
|
|
BackUpPriv = FALSE;
|
|
|
|
CloseHandle(TokenHandle);
|
|
|
|
// Initialize some memory say for 100 sids
|
|
AccountSidsLength = 100 * sizeof ( PSID );
|
|
AccountSids = (PSID *) LocalAlloc( LPTR, AccountSidsLength );
|
|
|
|
// Initialize some memory for a large file security discriptor
|
|
SidFromGetFileSecurity = (PSECURITY_DESCRIPTOR) GlobalAlloc( GPTR, (DWORD) LARGEPSID);
|
|
|
|
// Check to see if memory was allocated
|
|
if(AccountSids == NULL || SidFromGetFileSecurity == NULL )
|
|
{
|
|
syserror(GetLastError());
|
|
return(TRUE);
|
|
}
|
|
|
|
UserNameBuff[0] = (char) NULL;
|
|
SystemNameBuff[0] = (char) NULL;
|
|
FilePath[0] = (char) NULL;
|
|
FileNameBuff[0] = (char) NULL;
|
|
FileSystemNameBuff[0] = (char) NULL;
|
|
GeneralUseBuffer[0] = (char) NULL;
|
|
|
|
/* Check for valid command line argument syntax before processing */
|
|
/* check for some count greater than zero and less than max argc count */
|
|
if(argc > 1 && argc <= MAXARGS)
|
|
{
|
|
/* Need to make the following assumptions: That the first command line arg
|
|
can be a help request or other switch "/? -? /i -i" or an account name.
|
|
and not a switch option, could be additional switches or a path name.
|
|
Also, switches can be intermixed the account name and path. Path is
|
|
not required local directory is assumed. First parse switches,
|
|
account and path.
|
|
*/
|
|
|
|
|
|
/* Loop through command line args */
|
|
for(i=1; i<argc; i++)
|
|
{
|
|
/* check length of args, 2 may indicate a switch */
|
|
switch(strlen(argv[i]))
|
|
{
|
|
case 1:
|
|
if(sys == FALSE) // if file flagg true have an invalid case
|
|
{
|
|
strcpy(UserNameBuff, argv[i]);
|
|
// System is local
|
|
System = NULL;
|
|
sys = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// copy the argument into the file name buffer
|
|
strcpy(FileNameBuff,argv[i]);
|
|
// Make the Machine name NULL for local machine
|
|
FileMachine = NULL;
|
|
LocalFlag = TRUE;
|
|
fl = TRUE;
|
|
}
|
|
break;
|
|
|
|
case 2: /* Valid size for switch */
|
|
/* check for switch flag */
|
|
if( argv[i][0] == '/' || argv[i][0] == '-')
|
|
{
|
|
switch((int)argv[i][1])
|
|
{ // Help Switch
|
|
case (int) '?':
|
|
usage(HELP, NULL);
|
|
return(TRUE);
|
|
|
|
// Interactive Logon Switchs
|
|
case (int) 'i':
|
|
inter_logon = TRUE;
|
|
continue;
|
|
|
|
case (int) 'I':
|
|
inter_logon = TRUE;
|
|
continue;
|
|
|
|
// Recurse Subdirectories
|
|
case (int) 's':
|
|
RecurseFlag = TRUE;
|
|
continue;
|
|
|
|
case (int) 'S':
|
|
RecurseFlag = TRUE;
|
|
continue;
|
|
|
|
|
|
default:
|
|
usage(INVALID_SWT, argv[i]);
|
|
usage(USAGE_ARG, NULL);
|
|
return(TRUE);
|
|
}
|
|
}
|
|
else /* if not swiches then must be a or 2 char path name */
|
|
{
|
|
if(sys == FALSE) // if file flag true have an invalid case
|
|
{
|
|
strcpy(UserNameBuff, argv[i]);
|
|
// System is local
|
|
System = NULL;
|
|
sys = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// copy the argument into the file name buffer
|
|
strcpy(FileNameBuff,argv[i]);
|
|
// Check for "_:" drive type
|
|
pbslash = strchr(argv[i], 0x3a);
|
|
if(pbslash != NULL)
|
|
{
|
|
strcat(FileNameBuff, "\\");
|
|
// Set File pointer
|
|
File = (LPTSTR) &FileNameBuff[0];
|
|
}
|
|
|
|
fl = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default: /* look for account or path */
|
|
// Also we know that a sys/user machine\user is the first string
|
|
if(sys == FALSE)
|
|
{
|
|
// need to to find the "\" in the
|
|
pbslash = strchr(argv[i], 0x5c);
|
|
// check pointer location if a NULL no "\" or at first postion in string
|
|
// if no slash have a account name only
|
|
if(pbslash == NULL)
|
|
{
|
|
strcpy(UserNameBuff, argv[i]);
|
|
// Set System to NULL
|
|
System = NULL;
|
|
sys = TRUE;
|
|
break;
|
|
}
|
|
if( pbslash == argv[i])
|
|
{
|
|
usage(INVALID_ARG, argv[i]);
|
|
usage(USAGE_ARG, NULL);
|
|
return(TRUE);
|
|
}
|
|
// copy the string from the "\" tho the user buffer
|
|
strcpy(UserNameBuff, ++pbslash);
|
|
// copy the string up to the "\" in to the system buffer
|
|
// now terminate the string at "\" to a NULL
|
|
--pbslash;
|
|
*pbslash = '\0';
|
|
|
|
// Check to see if we have a domain name
|
|
if(!IsDomainName(argv[i], (LPSTR) SystemNameBuff))
|
|
{
|
|
// add the "\\" to the begining of string
|
|
strcpy(SystemNameBuff, "\\\\");
|
|
strcat(SystemNameBuff, argv[i]);
|
|
System = (LPTSTR) &SystemNameBuff[0];
|
|
}
|
|
else
|
|
{
|
|
System = (LPTSTR) &SystemNameBuff[0];
|
|
// printf("\n :%s is :%s \n", argv[i], System);
|
|
}
|
|
sys = TRUE;
|
|
}
|
|
else // File argument
|
|
{
|
|
// Get the local machine name
|
|
// machine is in UNC form.
|
|
// add the "\\" to the begining of string
|
|
strcpy(LocalSystemName, "\\\\");
|
|
if(!GetComputerName(&LocalSystemName[2],
|
|
&SNameLen))
|
|
{
|
|
syserror(GetLastError());
|
|
return(TRUE);
|
|
}
|
|
|
|
// Check for "\\" in first 2 chars in file path for UNC path
|
|
if( strncmp(argv[i], "\\\\", 2) == 0)
|
|
{
|
|
// copy "\\ to the next \" to the file machine name
|
|
for(j=0; j < (int) strlen(argv[i]); j++)
|
|
{
|
|
if(j<2)
|
|
FileSystemNameBuff[j] = argv[i][j];
|
|
else
|
|
{
|
|
// check for 3rd "\"
|
|
if(argv[i][j] == 0x5c)
|
|
break;
|
|
FileSystemNameBuff[j] = argv[i][j];
|
|
}
|
|
}
|
|
// add null to string
|
|
FileSystemNameBuff[j] = '\0';
|
|
// now need to check for the local machine name
|
|
// The get file security call will fail if local
|
|
// Compare the local machine name to the file machine
|
|
if(_stricmp(LocalSystemName, FileSystemNameBuff) == 0)
|
|
{
|
|
// Have a local Machine UNC path
|
|
// Check account machine name
|
|
if(_stricmp(LocalSystemName, System) == 0)
|
|
{
|
|
// Have a local Machine equal to account machine
|
|
// no need to look up sids for file machine.
|
|
LocalFlag = TRUE;
|
|
}
|
|
|
|
// Make the Machine name NULL for local machine
|
|
FileMachine = NULL;
|
|
// Need to strip off UNC name of local machine
|
|
// The j counter is at "\" character
|
|
|
|
strcpy(FileNameBuff, &argv[i][j]);
|
|
}
|
|
else // Have a nonlocal path
|
|
{
|
|
// Need to check system name against account machine
|
|
if(System != NULL)
|
|
if(_stricmp(FileSystemNameBuff, System) == 0)
|
|
{
|
|
// Have a file Machine equal to account machine
|
|
// no need to look up sids for file machine.
|
|
LocalFlag = TRUE;
|
|
}
|
|
strcpy(FileNameBuff,argv[i]);
|
|
FileMachine = (LPTSTR) &FileSystemNameBuff[0];
|
|
|
|
}
|
|
// printf("\n file machine: %s", FileMachine);
|
|
|
|
}
|
|
else // have a local file (assume local) or logical
|
|
{
|
|
// Need to get the logical or drive ie "_:"
|
|
pbslash = strchr(argv[i], 0x3a);
|
|
// check pointer location if a NULL assume a "\xx\xx" type path
|
|
if(pbslash == NULL)
|
|
{
|
|
strcpy(FileNameBuff,argv[i]);
|
|
// set the filemachine name to a null to force local
|
|
FileMachine = NULL;
|
|
}
|
|
else
|
|
{
|
|
// Have a logical drive or a machine drive
|
|
// Need the drive part
|
|
k = (int) strlen(argv[i]);
|
|
for(j=0; j < k; j++)
|
|
{
|
|
GeneralUseBuffer[j] = argv[i][j];
|
|
// check for ":"
|
|
if(argv[i][j] == 0x3a)
|
|
break;
|
|
}
|
|
// add null to string
|
|
GeneralUseBuffer[++j] = '\0';
|
|
// WNetGetConnection
|
|
WStatus = WNetGetConnection((LPTSTR) GeneralUseBuffer, // Drive name
|
|
(LPTSTR) FileSystemNameBuff, // Returned Name
|
|
&WNetSize);
|
|
// Check return status
|
|
if(WStatus == NO_ERROR)
|
|
{
|
|
// Have a valid redirected drive
|
|
// Build the full path name
|
|
strcat(FileNameBuff, argv[i]);
|
|
// Next get the machine name of the share
|
|
// copy "\\ to the next \" to the file machine name
|
|
for(j=0; j < (int) strlen(FileSystemNameBuff); j++)
|
|
{
|
|
if(j>2)
|
|
{
|
|
// check for 3rd "\"
|
|
if(FileSystemNameBuff[j] == 0x5c)
|
|
break;
|
|
}
|
|
}
|
|
// Add NULL
|
|
FileSystemNameBuff[j] = '\0';
|
|
FileMachine = (LPTSTR) &FileSystemNameBuff[0];
|
|
}
|
|
else
|
|
{
|
|
// Have a local machine drive
|
|
strcpy(FileNameBuff,argv[i]);
|
|
// Check for drive only path "_:\" or "_:"
|
|
// FindFirstFile has with it.
|
|
// Need to convert "_:" to "_:\"
|
|
if(k <= 3)
|
|
DriveFlag = TRUE;
|
|
|
|
// Check for a System = NULL
|
|
if(System != NULL)
|
|
{
|
|
// Check User Account system against local name
|
|
if(_stricmp(LocalSystemName, System) == 0)
|
|
{
|
|
// Have a local user account machine
|
|
LocalFlag = TRUE;
|
|
}
|
|
}
|
|
else // System is Local machine
|
|
LocalFlag = TRUE;
|
|
|
|
// set the filemachine name to a null to force local
|
|
FileMachine = NULL;
|
|
|
|
}
|
|
}
|
|
}
|
|
fl = TRUE;
|
|
// Set File pointer
|
|
File = (LPTSTR) &FileNameBuff[0];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
} /* end switch */
|
|
} /* end for argv loop */
|
|
|
|
User = (LPTSTR) &UserNameBuff[0];
|
|
// Make sure GeneralUseBuffer is null
|
|
GeneralUseBuffer[0] = (CHAR) NULL;
|
|
// Check to see if file was entered
|
|
if(fl == FALSE)
|
|
{
|
|
usage(INVALID_FIL, (CHAR) NULL);
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
// Clean up the file name ie "." ".." ".\" etc
|
|
if(!CleanUpSource((LPTSTR) FileNameBuff, (LPTSTR) FileName, &DirFlag))
|
|
{
|
|
usage(INVALID_FIL, (LPTSTR) FileNameBuff);
|
|
return(FALSE);
|
|
}
|
|
File = &FileName[0];
|
|
Path = &FilePath[0];
|
|
strcpy(Path, File);
|
|
//Find last Slash
|
|
pbslash = strrchr(Path, 0x5c);
|
|
if(pbslash != NULL)
|
|
{
|
|
pbslash++;
|
|
*pbslash = (CHAR) NULL;
|
|
}
|
|
|
|
|
|
/*** Get everyone SID by use LookupAccountName ***/
|
|
|
|
/* Have no buffer sizes first call to LookupAccountName will return
|
|
need buffer sizes */
|
|
if( LookupAccountName( NULL,
|
|
TEXT("everyone"),
|
|
SidEveryone,
|
|
&cbSidFromLookupName,
|
|
RefDFromLookupName,
|
|
&cchRefDFromLookupName,
|
|
&UseFromLookupName))
|
|
{
|
|
usage(INVALID_ACC, User);
|
|
usage(USAGE_ARG, NULL);
|
|
return(TRUE);
|
|
}
|
|
|
|
/* Now have valid buffer sizes to call LookupAccountName for a valid SID */
|
|
/* allocate memory for the sid */
|
|
SidEveryone = LocalAlloc( (UINT) LMEM_FIXED, (UINT) cbSidFromLookupName);
|
|
|
|
if(SidEveryone == NULL)
|
|
{
|
|
syserror(GetLastError());
|
|
return(TRUE);
|
|
}
|
|
|
|
if( !LookupAccountName( NULL,
|
|
TEXT("everyone"),
|
|
SidEveryone,
|
|
&cbSidFromLookupName,
|
|
RefDFromLookupName,
|
|
&cchRefDFromLookupName,
|
|
&UseFromLookupName))
|
|
{
|
|
usage(INVALID_ACC, User);
|
|
usage(USAGE_ARG, NULL);
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
/* Have no buffer sizes first call to LookupAccountName will return
|
|
need buffer sizes */
|
|
if( LookupAccountName( System,
|
|
User,
|
|
SidFromLookupName,
|
|
&cbSidFromLookupName,
|
|
RefDFromLookupName,
|
|
&cchRefDFromLookupName,
|
|
&UseFromLookupName))
|
|
{
|
|
usage(INVALID_ACC, User);
|
|
usage(USAGE_ARG, NULL);
|
|
return(TRUE);
|
|
}
|
|
|
|
/* Now have valid buffer sizes to call LookupAccountName for a valid SID */
|
|
/* allocate memory for the sid */
|
|
|
|
SidFromLookupName = LocalAlloc( (UINT) LMEM_FIXED, (UINT) cbSidFromLookupName);
|
|
|
|
if(SidFromLookupName == NULL)
|
|
{
|
|
syserror(GetLastError());
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
if( !LookupAccountName( System,
|
|
User,
|
|
SidFromLookupName,
|
|
&cbSidFromLookupName,
|
|
RefDFromLookupName,
|
|
&cchRefDFromLookupName,
|
|
&UseFromLookupName))
|
|
{
|
|
usage(INVALID_ACC, User);
|
|
usage(USAGE_ARG, NULL);
|
|
return(TRUE);
|
|
}
|
|
|
|
ASidFromLookupName[0] = SidFromLookupName;
|
|
if(!VariableInitialization())
|
|
{
|
|
syserror(GetLastError());
|
|
return(TRUE);
|
|
}
|
|
|
|
// look up the user's group sids for the machine the accounts on
|
|
BoolStatus = LookupAllUserSidsWS(System);
|
|
|
|
// look up the user's group sid for the workstation that the file resides on
|
|
// Need to check if the account machine and file machine are the same.
|
|
// If not done duplicate sids will be build.
|
|
|
|
if( LocalFlag == FALSE)
|
|
{
|
|
if( !LookupAllUserSidsWS(FileMachine))
|
|
{
|
|
// system error message
|
|
syserror(GetLastError());
|
|
return(TRUE);
|
|
}
|
|
}
|
|
// Not a directory
|
|
if(!DirFlag)
|
|
{
|
|
// Need to get the findfirstfile
|
|
FindFileHandle = FindFirstFile(File, &FindFileData);
|
|
if(FindFileHandle == INVALID_HANDLE_VALUE)
|
|
{
|
|
usage(INVALID_FIL, (LPTSTR) FileNameBuff);
|
|
return(FALSE);
|
|
}
|
|
|
|
// FindClose(FindFileHandle);
|
|
|
|
if(Path != NULL)
|
|
{
|
|
strcpy(File, Path);
|
|
// This sould give a valid path
|
|
strcat(File,FindFileData.cFileName);
|
|
}
|
|
else
|
|
strcpy(File,FindFileData.cFileName);
|
|
}
|
|
else // need to fake out the Finfirstfile data structure
|
|
FindFileData.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
|
|
|
|
// Now have all of the user sid and the first file.
|
|
// Loop through the files
|
|
while(1)
|
|
{
|
|
if(strcmp(FindFileData.cFileName, ".") != 0)
|
|
if(strcmp(FindFileData.cFileName, "..") != 0)
|
|
{
|
|
|
|
/* The call to GetFileSecurity works similar to LookupAccountName
|
|
in that the first call get need buffer sizes */
|
|
|
|
|
|
// Use a fairly larger buffer size of returned size value.
|
|
// This will keep the number of malloc type calls down.
|
|
SidsizeFromGetFileSecurity = LARGEPSID;
|
|
BoolStatus = GetFileSecurityBackup(File,
|
|
si,
|
|
SidFromGetFileSecurity,
|
|
SidsizeFromGetFileSecurity, /* buffer size */
|
|
&lpcbsdRequired, /* required buffer size */
|
|
BackUpPriv);
|
|
if(!BoolStatus)
|
|
{
|
|
// GetFileSecurity failed need to check if buffer was to small
|
|
if(lpcbsdRequired != 0)
|
|
{
|
|
SidsizeFromGetFileSecurity = lpcbsdRequired;
|
|
// Reallocate the memory to the new size
|
|
SidFromGetFileSecurity = GlobalReAlloc( SidFromGetFileSecurity, lpcbsdRequired, GMEM_ZEROINIT);
|
|
BoolStatus = GetFileSecurityBackup(File,
|
|
si,
|
|
SidFromGetFileSecurity,
|
|
SidsizeFromGetFileSecurity,
|
|
&lpcbsdRequired,
|
|
BackUpPriv);
|
|
if(!BoolStatus)
|
|
{
|
|
syserror(GetLastError());
|
|
return(TRUE);
|
|
}
|
|
}
|
|
else // Have a problem with file
|
|
{
|
|
usage(INVALID_FIL, (LPTSTR) File);
|
|
return(FALSE);
|
|
}
|
|
}
|
|
// Clear access masks
|
|
grant_mask = 0;
|
|
if(!GetFilePermissions(SidFromGetFileSecurity, (PSID) SidFromLookupName))
|
|
{
|
|
syserror(GetLastError());
|
|
return(TRUE);
|
|
}
|
|
// Need to chech for directory structure
|
|
if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
{
|
|
// Display the directory perms
|
|
if(!IsLastCharSlash(File))
|
|
strcat(File, "\\");
|
|
DisplayPerms(File, TRUE);
|
|
// Check Recurse subdirectories flagg
|
|
// This is ugly but time is short
|
|
if(!DirFlag)
|
|
if(RecurseFlag == TRUE)
|
|
{
|
|
// Need the Filename, Path, user account sid, and Backup priv flag
|
|
RecurseSubs(FindFileData.cFileName, Path, SidFromLookupName, BackUpPriv,
|
|
RecurseFlag);
|
|
}
|
|
}
|
|
else // For initial files that are directories
|
|
if(!DirFlag)
|
|
DisplayPerms(File, TRUE);
|
|
} // End if "." .""
|
|
// Go for the next file
|
|
// for recursing subdirectories.
|
|
if(DirFlag)
|
|
{
|
|
// Check recurse flag
|
|
if(RecurseFlag)
|
|
{
|
|
// Need to update the path
|
|
strcpy(Path, File);
|
|
// Add the wild card
|
|
strcat(File, "*");
|
|
|
|
FindClose(FindFileHandle);
|
|
// Need to get the findfirstfile
|
|
FindFileHandle = FindFirstFile(File, &FindFileData);
|
|
if(FindFileHandle == INVALID_HANDLE_VALUE)
|
|
{
|
|
syserror(GetLastError());
|
|
return(TRUE);
|
|
}
|
|
// Add path to file
|
|
strcpy(File, Path);
|
|
// This sould give a valid path
|
|
strcat(File,FindFileData.cFileName);
|
|
DirFlag = FALSE;
|
|
continue;
|
|
}
|
|
// Have only a single directory
|
|
// if(!IsLastCharSlash(File))
|
|
// strcat(File, "\\");
|
|
// DisplayPerms(File, TRUE);
|
|
break;
|
|
}
|
|
|
|
if(FindNextFile(FindFileHandle, &FindFileData))
|
|
{
|
|
if(Path != NULL)
|
|
{
|
|
strcpy(File, Path);
|
|
// This sould give a valid path
|
|
strcat(File,FindFileData.cFileName);
|
|
}
|
|
else
|
|
strcpy(File,FindFileData.cFileName);
|
|
|
|
}
|
|
else // Have end of files
|
|
break;
|
|
|
|
} // End While loop
|
|
|
|
FindClose(FindFileHandle);
|
|
|
|
// free memory
|
|
if(AccountSids)
|
|
LocalFree(AccountSids);
|
|
if(SidFromLookupName)
|
|
LocalFree(SidFromLookupName);
|
|
if(SidEveryone)
|
|
LocalFree(SidEveryone);
|
|
|
|
return(TRUE);
|
|
|
|
} /* end of main if */
|
|
else
|
|
usage(HELP, NULL);
|
|
|
|
return(TRUE);
|
|
} /* End of Main */
|
|
|
|
/* *********************************************************************
|
|
Recure Subdirectories
|
|
************************************************************************ */
|
|
BOOL
|
|
RecurseSubs(IN LPTSTR FileName,
|
|
IN LPTSTR FilePath,
|
|
IN PSID UserSid,
|
|
IN BOOL BackPriv,
|
|
IN BOOL Recurse)
|
|
{
|
|
char
|
|
PathBuff[LSA_WIN_STANDARD_BUFFER_SIZE],
|
|
FileNameBuffer[LSA_WIN_STANDARD_BUFFER_SIZE],
|
|
GeneralUseBuffer[LSA_WIN_STANDARD_BUFFER_SIZE];
|
|
|
|
DWORD cchRefDFromLookupName=0,
|
|
SidsizeFromGetFileSecurity=0,
|
|
lpcbsdRequired=0;
|
|
|
|
SID_NAME_USE UseFromLookupSid;
|
|
LPSTR RPath,
|
|
RFile;
|
|
SECURITY_INFORMATION si; /* requested information */
|
|
BOOL BoolStatus=TRUE;
|
|
ULONG AccountSidsLength;
|
|
HANDLE FileHandle;
|
|
WIN32_FIND_DATA FindFileData;
|
|
|
|
|
|
|
|
// Need to create a wildcard file name for FindFirstFile
|
|
sprintf(FileNameBuffer, "%s%s%s", FilePath, FileName, "\\*");
|
|
RFile = (LPTSTR) &FileNameBuffer[0];
|
|
// Update path to include the new directory
|
|
sprintf(PathBuff, "%s%s%s", FilePath, FileName, "\\");
|
|
RPath = (LPTSTR) &PathBuff[0];
|
|
FileHandle = FindFirstFile(RFile, &FindFileData);
|
|
if(FileHandle == INVALID_HANDLE_VALUE)
|
|
return(FALSE);
|
|
|
|
si =(OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION
|
|
|DACL_SECURITY_INFORMATION);
|
|
|
|
|
|
// Now have all of the user sid and the first file.
|
|
// Loop through the files
|
|
while(1)
|
|
{
|
|
|
|
// Need to check for "." and ".."
|
|
|
|
if(strcmp(FindFileData.cFileName, ".") != 0)
|
|
if(strcmp(FindFileData.cFileName, "..") != 0)
|
|
{
|
|
sprintf(RFile, "%s%s", RPath, FindFileData.cFileName);
|
|
/* The call to GetFileSecurity works similar to LookupAccountName
|
|
in that the first call get need buffer sizes */
|
|
|
|
|
|
// Use a fairly larger buffer size of returned size value.
|
|
// This will keep the number of malloc type calls down.
|
|
SidsizeFromGetFileSecurity = LARGEPSID;
|
|
BoolStatus = GetFileSecurityBackup(RFile,
|
|
si,
|
|
SidFromGetFileSecurity,
|
|
SidsizeFromGetFileSecurity, /* buffer size */
|
|
&lpcbsdRequired, /* required buffer size */
|
|
BackPriv);
|
|
if(!BoolStatus)
|
|
{
|
|
// GetFileSecurity failed need to check if buffer was to small
|
|
if(lpcbsdRequired != 0)
|
|
{
|
|
SidsizeFromGetFileSecurity = lpcbsdRequired;
|
|
// Reallocate the memory to the new size
|
|
SidFromGetFileSecurity = GlobalReAlloc( SidFromGetFileSecurity, lpcbsdRequired, GMEM_ZEROINIT);
|
|
BoolStatus = GetFileSecurityBackup(RFile,
|
|
si,
|
|
SidFromGetFileSecurity,
|
|
SidsizeFromGetFileSecurity,
|
|
&lpcbsdRequired,
|
|
BackPriv);
|
|
if(!BoolStatus)
|
|
{
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
}
|
|
// Have general failure this is a access priv problem.
|
|
DisplayPerms(RFile, FALSE);
|
|
}
|
|
if(BoolStatus) // Valid file security discriptor
|
|
{
|
|
grant_mask = 0;
|
|
|
|
if(!GetFilePermissions(SidFromGetFileSecurity, (PSID) UserSid))
|
|
return(FALSE);
|
|
// Need to chech for directory structure
|
|
if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
{
|
|
// Display the directory perms
|
|
strcat(RFile, "\\");
|
|
DisplayPerms(RFile, TRUE);
|
|
// Recurse subdirectories
|
|
// Need the Filename, Path, user account sid, and Backup priv flag
|
|
RecurseSubs(FindFileData.cFileName, RPath, SidFromLookupName, BackPriv,
|
|
Recurse);
|
|
|
|
}
|
|
else
|
|
DisplayPerms(RFile, TRUE);
|
|
} // End of valid security descriptor else
|
|
} // end of ". or .." if
|
|
// Go for the next file
|
|
if(!FindNextFile(FileHandle, &FindFileData))
|
|
break;
|
|
} // End While loop
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
/* ***************************************************************
|
|
Usage Error subroutine
|
|
******************************************************************* */
|
|
|
|
|
|
void usage(IN INT message_num,
|
|
IN PCHAR string_val)
|
|
{
|
|
if(string_val == NULL)
|
|
fprintf(stderr, "\n%s\n", MESSAGES[message_num]);
|
|
else
|
|
fprintf(stderr,"\n%s %s\n", MESSAGES[message_num], string_val);
|
|
}
|
|
|
|
/*
|
|
System Error subroutine
|
|
*/
|
|
|
|
|
|
void syserror(DWORD error_val)
|
|
{
|
|
CHAR MessageBuf[512];
|
|
DWORD eval,
|
|
Lang_Val;
|
|
|
|
Lang_Val = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
|
|
FormatMessage(
|
|
FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL,
|
|
error_val,
|
|
Lang_Val,
|
|
(LPTSTR) MessageBuf,
|
|
512,
|
|
NULL);
|
|
|
|
printf("\n%s", MessageBuf);
|
|
}
|
|
|
|
/* ********************************************************************* */
|
|
BOOL IsDomainName(
|
|
IN LPSTR TestDomainName,
|
|
IN LPSTR DomainNameBuff)
|
|
{
|
|
NTSTATUS dNtStatus;
|
|
ANSI_STRING AnsiString;
|
|
UNICODE_STRING UDomainName;
|
|
NET_API_STATUS NetCallStatus;
|
|
LPBYTE xbuff = NULL;
|
|
LPWSTR NDomainName;
|
|
UINT BuffSize;
|
|
INT AnsiSize, slen;
|
|
|
|
UDomainName.Buffer = NULL;
|
|
// get a unicode string
|
|
RtlInitAnsiString( &AnsiString, TestDomainName );
|
|
dNtStatus = RtlAnsiStringToUnicodeString( &UDomainName, &AnsiString, TRUE );
|
|
// Free up the ansi string to use it later
|
|
// RtlFreeAnsiString(&AnsiString);
|
|
// Compute the needed amount of memory for a zero terminated string
|
|
// Allocate the memory and zero it
|
|
BuffSize = (UINT) (UDomainName.Length * 2) + 4;
|
|
NDomainName = LocalAlloc( (UINT) LPTR,
|
|
BuffSize);
|
|
|
|
if (NDomainName == NULL)
|
|
{
|
|
syserror(GetLastError());
|
|
exit(FALSE);
|
|
}
|
|
// Copy the wide string to the allocated memory
|
|
RtlMoveMemory( NDomainName, UDomainName.Buffer, BuffSize-4);
|
|
// Should now have a zero terminated string
|
|
|
|
// now check for the domain name
|
|
NetCallStatus = NetGetDCName(NULL, NDomainName,
|
|
&xbuff );
|
|
if(NetCallStatus == ERROR_SUCCESS)
|
|
{
|
|
// Convert the wchar null string to ansi sting is passed back machine
|
|
// name of domain controler
|
|
// Use the current unicode buffer
|
|
slen = wcslen((USHORT *) xbuff) * 2;
|
|
UDomainName.Length = (USHORT) slen;
|
|
UDomainName.MaximumLength = (USHORT) slen + 2;
|
|
UDomainName.Buffer = (PWSTR) xbuff;
|
|
dNtStatus = RtlUnicodeStringToAnsiString( &AnsiString, &UDomainName, TRUE );
|
|
// return the string pointer
|
|
RtlMoveMemory( DomainNameBuff, AnsiString.Buffer,
|
|
(UINT) strlen(AnsiString.Buffer) +1);
|
|
LocalFree(NDomainName);
|
|
|
|
return(TRUE);
|
|
}
|
|
LocalFree(NDomainName);
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
/* ********************************************************************* */
|
|
|
|
BOOL
|
|
LookupAllUserSidsWS( IN LPSTR lpSystemName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
BOOL - TRUE is returned if successful, else FALSE.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS xNtStatus;
|
|
ANSI_STRING AnsiString;
|
|
UNICODE_STRING USystemName;
|
|
ULONG Count;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
|
|
LSA_HANDLE PolicyHandle = NULL;
|
|
UNICODE_STRING AccountDomainName;
|
|
PPOLICY_ACCOUNT_DOMAIN_INFO PolicyAccountDomainInfo;
|
|
USystemName.Buffer = NULL;
|
|
|
|
|
|
|
|
RtlInitAnsiString( &AnsiString, lpSystemName );
|
|
xNtStatus = RtlAnsiStringToUnicodeString( &USystemName, &AnsiString, TRUE );
|
|
|
|
if (!NT_SUCCESS(xNtStatus))
|
|
{
|
|
SetLastError(xNtStatus);
|
|
return(FALSE);
|
|
}
|
|
//
|
|
// Open a handle to the target Workstation's Policy Object so that we can
|
|
// information from it and also so that we can use it for looking up.
|
|
// Sids
|
|
//
|
|
|
|
InitObjectAttributes(
|
|
&ObjectAttributes,
|
|
&SecurityQualityOfService
|
|
);
|
|
|
|
|
|
xNtStatus = LsaOpenPolicy(
|
|
&USystemName, // WorkstationName,
|
|
&ObjectAttributes,
|
|
POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION,
|
|
&PolicyHandle
|
|
);
|
|
|
|
if (!NT_SUCCESS(xNtStatus))
|
|
{
|
|
// try local machine
|
|
PolicyHandle = NULL;
|
|
xNtStatus = LsaOpenPolicy(
|
|
NULL, // WorkstationName,
|
|
&ObjectAttributes,
|
|
POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION,
|
|
&PolicyHandle
|
|
);
|
|
|
|
|
|
if (!NT_SUCCESS(xNtStatus))
|
|
{
|
|
SetLastError(xNtStatus);
|
|
return(FALSE);
|
|
}
|
|
}
|
|
// Lookup the Group Sids contained in the Workstation's
|
|
// SAM Account Domain
|
|
//
|
|
// First, obtain the Name and Sid of the SAM Account Domain from the
|
|
// Workstation's LSA Policy Object.
|
|
//
|
|
|
|
|
|
xNtStatus = LsaQueryInformationPolicy(
|
|
PolicyHandle,
|
|
PolicyAccountDomainInformation,
|
|
(PVOID *) &PolicyAccountDomainInfo
|
|
);
|
|
|
|
if (!NT_SUCCESS(xNtStatus))
|
|
{
|
|
SetLastError(xNtStatus);
|
|
return(FALSE);
|
|
}
|
|
|
|
AccountDomainName = PolicyAccountDomainInfo->DomainName;
|
|
|
|
xNtStatus = LsaClose(PolicyHandle);
|
|
if(!NT_SUCCESS(xNtStatus))
|
|
{
|
|
|
|
SetLastError(xNtStatus);
|
|
return(FALSE);
|
|
}
|
|
|
|
if(!LookupSidsInSamDomain(
|
|
&USystemName, // WorkstationName,
|
|
&USystemName, // WorkstationName,
|
|
&AccountDomainName
|
|
))
|
|
return(FALSE);
|
|
|
|
if( USystemName.Buffer != NULL )
|
|
{
|
|
|
|
RtlFreeUnicodeString( &USystemName );
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
BOOL
|
|
GeneralBuildSid(
|
|
OUT PSID *Sid,
|
|
IN PSID DomainSid,
|
|
IN ULONG RelativeId
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function builds a Sid from a Domain Sid and a RelativeId.
|
|
|
|
Arguments:
|
|
|
|
Sid - Receives a pointer to the constructed Sid.
|
|
|
|
DomainSid - Points to a Domain Sid
|
|
|
|
RelativeId - Contains a Relative Id
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOL - TRUE if successful, else FALSE.
|
|
|
|
--*/
|
|
|
|
{
|
|
PSID OutputSid = NULL;
|
|
ULONG OutputSidLength;
|
|
UCHAR SubAuthorityCount;
|
|
|
|
SubAuthorityCount = *RtlSubAuthorityCountSid( DomainSid ) + (UCHAR) 1;
|
|
OutputSidLength = RtlLengthRequiredSid( SubAuthorityCount );
|
|
|
|
OutputSid = LocalAlloc( (UINT) LMEM_FIXED, (UINT) OutputSidLength );
|
|
|
|
if (OutputSid == NULL) {
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
RtlMoveMemory( OutputSid, DomainSid, OutputSidLength - sizeof (ULONG));
|
|
(*RtlSubAuthorityCountSid( OutputSid ))++;
|
|
(*RtlSubAuthoritySid(OutputSid, SubAuthorityCount - (UCHAR) 1)) = RelativeId;
|
|
|
|
*Sid = OutputSid;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
InitObjectAttributes(
|
|
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
|
IN PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService
|
|
)
|
|
|
|
/* ++
|
|
|
|
Routine Description:
|
|
|
|
This function initializes the given Object Attributes structure, including
|
|
Security Quality Of Service. Memory must be allcated for both
|
|
ObjectAttributes and Security QOS by the caller.
|
|
|
|
Arguments:
|
|
|
|
ObjectAttributes - Pointer to Object Attributes to be initialized.
|
|
|
|
SecurityQualityOfService - Pointer to Security QOS to be initialized.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
-- */
|
|
|
|
{
|
|
SecurityQualityOfService->Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
|
|
SecurityQualityOfService->ImpersonationLevel = SecurityImpersonation;
|
|
SecurityQualityOfService->ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
|
|
SecurityQualityOfService->EffectiveOnly = FALSE;
|
|
|
|
//
|
|
// Set up the object attributes prior to opening the LSA.
|
|
//
|
|
|
|
InitializeObjectAttributes(
|
|
ObjectAttributes,
|
|
NULL,
|
|
0L,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
//
|
|
// The InitializeObjectAttributes macro presently stores NULL for
|
|
// the SecurityQualityOfService field, so we must manually copy that
|
|
// structure for now.
|
|
//
|
|
|
|
ObjectAttributes->SecurityQualityOfService = SecurityQualityOfService;
|
|
}
|
|
|
|
|
|
BOOL
|
|
LookupSidsInSamDomain(
|
|
IN OPTIONAL PUNICODE_STRING WorkstationName,
|
|
IN PUNICODE_STRING DomainControllerName,
|
|
IN PUNICODE_STRING SamDomainName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function enumerates all the SAM accounts of a specified type
|
|
in a specified SAM domain on a specified target system. The system
|
|
must be one of the following:
|
|
|
|
o The Workstation itself.
|
|
o A Domain Controller for the Primary Domain of the Workstation.
|
|
o A Domain Controller for one of the Trusted Domains of the
|
|
Workstation.
|
|
|
|
|
|
Having enumerated the accounts, the function then performs
|
|
an LsaLookupSids call via the specified Workstation to lookup all of
|
|
these account Sids, and then compares the returned information
|
|
with that expected.
|
|
|
|
Arguments:
|
|
|
|
WorkstationName - Specifies a Workstation Name. The name may be
|
|
the NULL string, which means the current system.
|
|
|
|
DomainControllerName - Specifies the name of a target Domain Controller
|
|
for (the Workstation's Primary Domain or one of its Trusted
|
|
Domains.
|
|
|
|
SamDomainName - Specifies the name of the SAM Domain. This is either
|
|
the BUILTIN Domain or the name of the Accounts Domain.
|
|
|
|
SamAccountType - Specifies the type of SAM account to be enumerated
|
|
and looked up.
|
|
|
|
Return Values:
|
|
|
|
BOOL - TRUE if successful, else FALSE.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS CtStatus;
|
|
BOOL BooleanStatus = TRUE;
|
|
OBJECT_ATTRIBUTES SamObjectAttributes;
|
|
OBJECT_ATTRIBUTES LsaObjectAttributes;
|
|
PSID SamDomainSid = NULL;
|
|
SID WorldTypeSid = SECURITY_WORLD_SID_AUTHORITY;
|
|
PSAM_RID_ENUMERATION EnumerationBuffer = NULL;
|
|
ULONG DomainIndex;
|
|
ULONG UserAccountControl;
|
|
ULONG GroupCount;
|
|
ULONG SidCount=0;
|
|
ULONG Relid=0;
|
|
ULONG RidIndex=0;
|
|
ULONG GenRid;
|
|
ULONG CountReturned;
|
|
PULONG AliasBuffer;
|
|
UNICODE_STRING TmpDomainControllerName;
|
|
PVOID EnumerationInformation;
|
|
ULONG EnumerationContext;
|
|
ULONG PreferedMaximumLength;
|
|
|
|
//
|
|
// Connect to the SAM server.
|
|
//
|
|
|
|
CtStatus = SamConnect(
|
|
DomainControllerName,
|
|
&SamServerHandle,
|
|
SAM_SERVER_ENUMERATE_DOMAINS | SAM_SERVER_LOOKUP_DOMAIN,
|
|
&SamObjectAttributes
|
|
);
|
|
|
|
if (!NT_SUCCESS(CtStatus))
|
|
{
|
|
|
|
// try local machine
|
|
CtStatus = SamConnect(
|
|
NULL, // DomainControllerName,
|
|
&SamServerHandle,
|
|
SAM_SERVER_ENUMERATE_DOMAINS | SAM_SERVER_LOOKUP_DOMAIN,
|
|
&SamObjectAttributes
|
|
);
|
|
if (!NT_SUCCESS(CtStatus))
|
|
{
|
|
SetLastError(CtStatus);
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Lookup the Named Domain in the Sam Server to get its Sid.
|
|
//
|
|
CountReturned = 0;
|
|
EnumerationContext = 0;
|
|
EnumerationBuffer = NULL;
|
|
PreferedMaximumLength = 512;
|
|
CtStatus = SamEnumerateDomainsInSamServer(
|
|
SamServerHandle,
|
|
&EnumerationContext,
|
|
(PVOID *) &EnumerationBuffer,
|
|
PreferedMaximumLength,
|
|
&CountReturned
|
|
);
|
|
if(!NT_SUCCESS(CtStatus))
|
|
{
|
|
SetLastError(CtStatus);
|
|
return(FALSE);
|
|
}
|
|
|
|
if((INT) CountReturned == 0)
|
|
{
|
|
SetLastError(CtStatus);
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
//
|
|
// Now look up the sid for the domains in the samserver
|
|
//
|
|
|
|
for(DomainIndex = 0; DomainIndex < CountReturned; DomainIndex++)
|
|
{
|
|
|
|
// if(SamDomainHandle != NULL)
|
|
// CtStatus = SamCloseHandle(SamDomainHandle);
|
|
SamDomainHandle = NULL;
|
|
SamDomainSid = NULL;
|
|
GroupCount = 0;
|
|
SidCount = 0;
|
|
|
|
CtStatus = SamLookupDomainInSamServer(
|
|
SamServerHandle,
|
|
(PUNICODE_STRING) &EnumerationBuffer[ DomainIndex ].Name, // SamDomainName,
|
|
&SamDomainSid
|
|
);
|
|
|
|
if(!NT_SUCCESS(CtStatus))
|
|
{
|
|
SetLastError(CtStatus);
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Open the Domain
|
|
//
|
|
|
|
CtStatus = SamOpenDomain(
|
|
SamServerHandle,
|
|
(GENERIC_READ | GENERIC_EXECUTE), //(DOMAIN_LIST_ACCOUNTS|DOMAIN_GET_ALIAS_MEMBERSHIP)
|
|
SamDomainSid,
|
|
&SamDomainHandle
|
|
);
|
|
|
|
if (!NT_SUCCESS(CtStatus))
|
|
{
|
|
SetLastError(CtStatus);
|
|
return(FALSE);
|
|
}
|
|
CtStatus = SamGetAliasMembership(
|
|
SamDomainHandle,
|
|
1,
|
|
ASidFromLookupName,
|
|
&GroupCount,
|
|
&AliasBuffer
|
|
);
|
|
if(!NT_SUCCESS(CtStatus))
|
|
{
|
|
SetLastError(CtStatus);
|
|
return(FALSE);
|
|
}
|
|
|
|
if (GroupCount == 0)
|
|
{
|
|
// SamCloseHandle(SamDomainHandle);
|
|
SamFreeMemory(AliasBuffer);
|
|
SamDomainSid = NULL;
|
|
GroupCount = 0;
|
|
SidCount = 0;
|
|
continue;
|
|
}
|
|
//
|
|
// Now construct the Account Sids from the Rids just enumerated.
|
|
// We prepend the Sam Domain Sid to the Rids.
|
|
//
|
|
SidCount = RidIndex + GroupCount;
|
|
for (RidIndex; RidIndex < SidCount; RidIndex++)
|
|
{
|
|
Relid = AliasBuffer[ RidIndex ];
|
|
if (!GeneralBuildSid(
|
|
&(AccountSids[Total_Sids++]),
|
|
SamDomainSid,
|
|
AliasBuffer[ RidIndex ]
|
|
))
|
|
{
|
|
SetLastError(CtStatus);
|
|
return(FALSE);
|
|
}
|
|
} // end for loop
|
|
|
|
// free up Sam memory to use again
|
|
SamFreeMemory(AliasBuffer);
|
|
|
|
} // domain for loop
|
|
|
|
// add world sid
|
|
AccountSids[Total_Sids++] = SeWorldSid;
|
|
|
|
|
|
// if interactive logon
|
|
if(inter_logon)
|
|
{
|
|
// printf("\n adding Interactive sid ");
|
|
AccountSids[Total_Sids++] = SeInteractiveSid;
|
|
}
|
|
else
|
|
AccountSids[Total_Sids++] = SeNetworkSid;
|
|
|
|
|
|
// Add in Account Sid
|
|
AccountSids[Total_Sids++] = SidFromLookupName;
|
|
|
|
//
|
|
// If necessary, close the SAM Domain Handle for the Workstation.
|
|
//
|
|
if(SamDomainHandle != NULL)
|
|
CtStatus = SamCloseHandle( SamDomainHandle);
|
|
//
|
|
// If necessary, disconnect from the SAM Server.
|
|
//
|
|
|
|
if(SamServerHandle != NULL)
|
|
CtStatus = SamCloseHandle( SamServerHandle );
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
void DisplayPerms(IN LPTSTR filename, IN BOOL valid_access)
|
|
{
|
|
if(g_noAccess)
|
|
{
|
|
printf("-");
|
|
goto exit;
|
|
}
|
|
|
|
if(valid_access)
|
|
{
|
|
if(owner_flag == TRUE)
|
|
printf("*");
|
|
else if(owner_group == TRUE)
|
|
printf("#");
|
|
|
|
if( grant_mask == 0)
|
|
{
|
|
printf("?");
|
|
goto exit;
|
|
}
|
|
|
|
if(grant_mask == FILE_GEN_ALL)
|
|
{
|
|
printf("A");
|
|
goto exit;
|
|
}
|
|
if((FILE_GENERIC_READ & grant_mask) == FILE_GENERIC_READ)
|
|
printf("R");
|
|
|
|
if((FILE_GENERIC_WRITE & grant_mask) == FILE_GENERIC_WRITE)
|
|
printf("W");
|
|
|
|
if((FILE_GENERIC_EXECUTE & grant_mask) == FILE_GENERIC_EXECUTE)
|
|
printf("X");
|
|
|
|
if((DELETE & grant_mask) == DELETE)
|
|
printf("D");
|
|
|
|
if((WRITE_DAC & grant_mask) == WRITE_DAC)
|
|
printf("P");
|
|
|
|
if((WRITE_OWNER & grant_mask) == WRITE_OWNER)
|
|
printf("O");
|
|
} // End if !valid_access
|
|
else
|
|
printf("?");
|
|
|
|
exit:
|
|
printf("\t%s\n", filename);
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
BOOL GetFilePermissions(
|
|
IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
OUT PSID UserAccountSids)
|
|
|
|
{
|
|
|
|
PISECURITY_DESCRIPTOR ISecurityDescriptor;
|
|
UCHAR Revision;
|
|
SECURITY_DESCRIPTOR_CONTROL Control;
|
|
PSID Owner;
|
|
PSID Group;
|
|
PACL Sacl;
|
|
PACL Dacl;
|
|
ULONG ui;
|
|
|
|
|
|
ISecurityDescriptor = ( PISECURITY_DESCRIPTOR )SecurityDescriptor;
|
|
|
|
Revision = ISecurityDescriptor->Revision;
|
|
Control = ISecurityDescriptor->Control;
|
|
|
|
Owner = SepOwnerAddrSecurityDescriptor( ISecurityDescriptor );
|
|
Group = SepGroupAddrSecurityDescriptor( ISecurityDescriptor );
|
|
Sacl = SepSaclAddrSecurityDescriptor( ISecurityDescriptor );
|
|
Dacl = SepDaclAddrSecurityDescriptor( ISecurityDescriptor );
|
|
|
|
|
|
if(EqualSid(UserAccountSids, Owner))
|
|
owner_flag = TRUE;
|
|
// check all the group sids for owner
|
|
for(ui=0; ui < Total_Sids; ui++)
|
|
{
|
|
if(EqualSid(AccountSids[ui], Owner))
|
|
{
|
|
SidOwnerGroup = AccountSids[ui];
|
|
owner_group = TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
if(Dacl == NULL)
|
|
{
|
|
return(TRUE);
|
|
}
|
|
else
|
|
{
|
|
// Check the user sid ACLS
|
|
if(!ProcessAcl( Dacl))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
/* ********************************************************************** */
|
|
|
|
|
|
// changed by a-zexu @ 5/10/98
|
|
BOOL ProcessAcl(PACL Acl)
|
|
{
|
|
ULONG i;
|
|
PACCESS_ALLOWED_ACE Ace;
|
|
BOOL KnownType = FALSE;
|
|
ULONG isid;
|
|
ACCESS_MASK mask = 0;
|
|
PCHAR AceTypes[] = { "Access Allowed",
|
|
"Access Denied ",
|
|
"System Audit ",
|
|
"System Alarm " };
|
|
|
|
|
|
// Check if the Acl is null.
|
|
if (Acl == NULL)
|
|
return(FALSE);
|
|
|
|
// Now for each Ace check the Sids of Owner
|
|
if(owner_group)
|
|
{
|
|
mask = 0;
|
|
|
|
for (i = 0, Ace = FirstAce(Acl);
|
|
i < Acl->AceCount;
|
|
i++, Ace = NextAce(Ace) )
|
|
{
|
|
if(EqualSid(SidOwnerGroup, &Ace->SidStart))
|
|
{
|
|
// Special case on the standard ace types
|
|
if(Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
|
|
{
|
|
mask = Ace->Mask;
|
|
}
|
|
else if(Ace->Header.AceType == ACCESS_DENIED_ACE_TYPE)
|
|
g_noAccess = TRUE;
|
|
}
|
|
} //end ace loop
|
|
|
|
grant_mask |= mask;
|
|
}
|
|
|
|
// Now for each Ace check the Sids of Everyone
|
|
if(!g_noAccess && SidEveryone)
|
|
{
|
|
mask = 0;
|
|
|
|
for (i = 0, Ace = FirstAce(Acl);
|
|
i < Acl->AceCount;
|
|
i++, Ace = NextAce(Ace) )
|
|
{
|
|
if(EqualSid(SidEveryone, &Ace->SidStart))
|
|
{
|
|
// Special case on the standard ace types
|
|
if(Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
|
|
{
|
|
mask = Ace->Mask;
|
|
}
|
|
else if(Ace->Header.AceType == ACCESS_DENIED_ACE_TYPE)
|
|
g_noAccess = TRUE;
|
|
}
|
|
} //end ace loop
|
|
|
|
grant_mask |= mask;
|
|
}
|
|
|
|
// Now for each Ace check the Sids of the user
|
|
if(!g_noAccess)
|
|
{
|
|
mask = 0;
|
|
|
|
for (i = 0, Ace = FirstAce(Acl);
|
|
i < Acl->AceCount;
|
|
i++, Ace = NextAce(Ace) )
|
|
{
|
|
if(EqualSid(SidFromLookupName, &Ace->SidStart))
|
|
{
|
|
// Special case on the standard ace types
|
|
if(Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
|
|
{
|
|
mask = Ace->Mask;
|
|
}
|
|
else if(Ace->Header.AceType == ACCESS_DENIED_ACE_TYPE)
|
|
g_noAccess = TRUE;
|
|
}
|
|
} //end ace loop
|
|
|
|
grant_mask |= mask;
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
/********************************************************************/
|
|
|
|
|
|
BOOL
|
|
VariableInitialization()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function initializes the global variables used by and exposed
|
|
by security.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
TRUE if variables successfully initialized.
|
|
FALSE if not successfully initialized.
|
|
|
|
--*/
|
|
{
|
|
|
|
PVOID HeapHandel;
|
|
|
|
ULONG SidWithZeroSubAuthorities;
|
|
ULONG SidWithOneSubAuthority;
|
|
ULONG SidWithTwoSubAuthorities;
|
|
ULONG SidWithThreeSubAuthorities;
|
|
|
|
SID_IDENTIFIER_AUTHORITY NullSidAuthority;
|
|
SID_IDENTIFIER_AUTHORITY WorldSidAuthority;
|
|
SID_IDENTIFIER_AUTHORITY LocalSidAuthority;
|
|
SID_IDENTIFIER_AUTHORITY CreatorSidAuthority;
|
|
SID_IDENTIFIER_AUTHORITY SeNtAuthority;
|
|
|
|
|
|
|
|
//
|
|
// Get the handle to the current process heap
|
|
//
|
|
|
|
HeapHandel = RtlProcessHeap();
|
|
|
|
|
|
|
|
|
|
NullSidAuthority = SepNullSidAuthority;
|
|
WorldSidAuthority = SepWorldSidAuthority;
|
|
LocalSidAuthority = SepLocalSidAuthority;
|
|
CreatorSidAuthority = SepCreatorSidAuthority;
|
|
SeNtAuthority = SepNtAuthority;
|
|
|
|
|
|
//
|
|
// The following SID sizes need to be allocated
|
|
//
|
|
|
|
SidWithZeroSubAuthorities = RtlLengthRequiredSid( 0 );
|
|
SidWithOneSubAuthority = RtlLengthRequiredSid( 1 );
|
|
SidWithTwoSubAuthorities = RtlLengthRequiredSid( 2 );
|
|
SidWithThreeSubAuthorities = RtlLengthRequiredSid( 3 );
|
|
|
|
//
|
|
// Allocate and initialize the universal SIDs
|
|
//
|
|
|
|
SeNullSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithOneSubAuthority);
|
|
SeWorldSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithOneSubAuthority);
|
|
SeLocalSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithOneSubAuthority);
|
|
SeCreatorOwnerSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithOneSubAuthority);
|
|
SeCreatorGroupSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithOneSubAuthority);
|
|
|
|
//
|
|
// Fail initialization if we didn't get enough memory for the universal
|
|
// SIDs.
|
|
//
|
|
|
|
if ( (SeNullSid == NULL) ||
|
|
(SeWorldSid == NULL) ||
|
|
(SeLocalSid == NULL) ||
|
|
(SeCreatorOwnerSid == NULL) ||
|
|
(SeCreatorGroupSid == NULL)
|
|
)
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
RtlInitializeSid( SeNullSid, &NullSidAuthority, 1 );
|
|
RtlInitializeSid( SeWorldSid, &WorldSidAuthority, 1 );
|
|
RtlInitializeSid( SeLocalSid, &LocalSidAuthority, 1 );
|
|
RtlInitializeSid( SeCreatorOwnerSid, &CreatorSidAuthority, 1 );
|
|
RtlInitializeSid( SeCreatorGroupSid, &CreatorSidAuthority, 1 );
|
|
|
|
*(RtlSubAuthoritySid( SeNullSid, 0 )) = SECURITY_NULL_RID;
|
|
*(RtlSubAuthoritySid( SeWorldSid, 0 )) = SECURITY_WORLD_RID;
|
|
*(RtlSubAuthoritySid( SeLocalSid, 0 )) = SECURITY_LOCAL_RID;
|
|
*(RtlSubAuthoritySid( SeCreatorOwnerSid, 0 )) = SECURITY_CREATOR_OWNER_RID;
|
|
*(RtlSubAuthoritySid( SeCreatorGroupSid, 0 )) = SECURITY_CREATOR_GROUP_RID;
|
|
|
|
//
|
|
// Allocate and initialize the NT defined SIDs
|
|
//
|
|
|
|
SeNetworkSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithOneSubAuthority);
|
|
SeInteractiveSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithOneSubAuthority);
|
|
SeLocalSystemSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithOneSubAuthority);
|
|
|
|
SeAliasAdminsSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithTwoSubAuthorities);
|
|
SeAliasUsersSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithTwoSubAuthorities);
|
|
SeAliasGuestsSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithTwoSubAuthorities);
|
|
SeAliasPowerUsersSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithTwoSubAuthorities);
|
|
SeAliasAccountOpsSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithTwoSubAuthorities);
|
|
SeAliasSystemOpsSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithTwoSubAuthorities);
|
|
SeAliasPrintOpsSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithTwoSubAuthorities);
|
|
SeAliasBackupOpsSid = (PSID)RtlAllocateHeap(HeapHandel, 0,SidWithTwoSubAuthorities);
|
|
|
|
//
|
|
// Fail initialization if we didn't get enough memory for the NT SIDs.
|
|
//
|
|
|
|
if((SeNetworkSid == NULL) ||
|
|
(SeInteractiveSid == NULL) ||
|
|
(SeLocalSystemSid == NULL) ||
|
|
(SeAliasAdminsSid == NULL) ||
|
|
(SeAliasUsersSid == NULL) ||
|
|
(SeAliasGuestsSid == NULL) ||
|
|
(SeAliasPowerUsersSid == NULL) ||
|
|
(SeAliasAccountOpsSid == NULL) ||
|
|
(SeAliasSystemOpsSid == NULL) ||
|
|
(SeAliasPrintOpsSid == NULL) ||
|
|
(SeAliasBackupOpsSid == NULL)
|
|
) {
|
|
return(FALSE);
|
|
}
|
|
|
|
RtlInitializeSid( SeNetworkSid, &SeNtAuthority, 1 );
|
|
RtlInitializeSid( SeInteractiveSid, &SeNtAuthority, 1 );
|
|
RtlInitializeSid( SeLocalSystemSid, &SeNtAuthority, 1 );
|
|
|
|
|
|
*(RtlSubAuthoritySid( SeNetworkSid, 0 )) = SECURITY_NETWORK_RID;
|
|
*(RtlSubAuthoritySid( SeInteractiveSid, 0 )) = SECURITY_INTERACTIVE_RID;
|
|
*(RtlSubAuthoritySid( SeLocalSystemSid, 0 )) = SECURITY_LOCAL_SYSTEM_RID;
|
|
|
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
|
|
/* ************************************************************************* */
|
|
|
|
|
|
|
|
BOOL
|
|
GetTokenHandle(
|
|
IN OUT PHANDLE TokenHandle
|
|
)
|
|
//
|
|
// This routine will open the current process and return
|
|
// a handle to its token.
|
|
//
|
|
// These handles will be closed for us when the process
|
|
// exits.
|
|
//
|
|
{
|
|
|
|
HANDLE ProcessHandle;
|
|
BOOL Result;
|
|
|
|
ProcessHandle = OpenProcess(
|
|
PROCESS_QUERY_INFORMATION,
|
|
FALSE,
|
|
GetCurrentProcessId()
|
|
);
|
|
|
|
if (ProcessHandle == NULL)
|
|
return(FALSE);
|
|
|
|
|
|
Result = OpenProcessToken (
|
|
ProcessHandle,
|
|
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
|
|
TokenHandle
|
|
);
|
|
|
|
if (!Result)
|
|
return(FALSE);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
BOOL
|
|
SetBackOperatorPriv(
|
|
IN HANDLE TokenHandle
|
|
)
|
|
//
|
|
// This routine turns on SeSetBackupPrivilege in the current
|
|
// token. Once that has been accomplished, we can open the file
|
|
// for READ_OWNER even if we are denied that access by the ACL
|
|
// on the file.
|
|
|
|
{
|
|
LUID SetBackupPrivilegeValue;
|
|
TOKEN_PRIVILEGES TokenPrivileges;
|
|
|
|
|
|
//
|
|
// First, find out the value of Backup Privilege
|
|
//
|
|
|
|
|
|
if(!LookupPrivilegeValue(
|
|
NULL,
|
|
"SeBackupPrivilege",
|
|
&SetBackupPrivilegeValue
|
|
))
|
|
return(FALSE);
|
|
|
|
//
|
|
// Set up the privilege set we will need
|
|
//
|
|
|
|
TokenPrivileges.PrivilegeCount = 1;
|
|
TokenPrivileges.Privileges[0].Luid = SetBackupPrivilegeValue;
|
|
TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
|
|
|
|
|
|
|
|
|
(VOID) AdjustTokenPrivileges (
|
|
TokenHandle,
|
|
FALSE,
|
|
&TokenPrivileges,
|
|
sizeof( TOKEN_PRIVILEGES ),
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
if(GetLastError() != NO_ERROR )
|
|
return(FALSE);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
GetFileSecurityBackupW(
|
|
LPWSTR lpFileName,
|
|
SECURITY_INFORMATION RequestedInformation,
|
|
PSECURITY_DESCRIPTOR pSecurityDescriptor,
|
|
DWORD nLength,
|
|
LPDWORD lpnLengthNeeded,
|
|
BOOL UseBackUp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This API returns top the caller a copy of the security descriptor
|
|
protecting a file or directory. Based on the caller's access
|
|
rights and privileges, this procedure will return a security
|
|
descriptor containing the requested security descriptor fields.
|
|
To read the handle's security descriptor the caller must be
|
|
granted READ_CONTROL access or be the owner of the object. In
|
|
addition, the caller must have SeSecurityPrivilege privilege to
|
|
read the system ACL.
|
|
|
|
Arguments:
|
|
|
|
lpFileName - Represents the name of the file or directory whose
|
|
security is being retrieved.
|
|
|
|
RequestedInformation - A pointer to the security information being
|
|
requested.
|
|
|
|
pSecurityDescriptor - A pointer to the buffer to receive a copy of
|
|
the secrity descriptor protecting the object that the caller
|
|
has the rigth to view. The security descriptor is returned in
|
|
self-relative format.
|
|
|
|
nLength - The size, in bytes, of the security descriptor buffer.
|
|
|
|
lpnLengthNeeded - A pointer to the variable to receive the number
|
|
of bytes needed to store the complete secruity descriptor. If
|
|
returned number of bytes is less than or equal to nLength then
|
|
the entire security descriptor is returned in the output
|
|
buffer, otherwise none of the descriptor is returned.
|
|
|
|
Return Value:
|
|
|
|
TRUE is returned for success, FALSE if access is denied or if the
|
|
buffer is too small to hold the security descriptor.
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS WStatus;
|
|
HANDLE FileHandle;
|
|
ACCESS_MASK DesiredAccess;
|
|
OBJECT_ATTRIBUTES Obja;
|
|
UNICODE_STRING FileName;
|
|
RTL_RELATIVE_NAME_U RelativeName;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
PVOID FreeBuffer;
|
|
|
|
QuerySecAccessMask(
|
|
RequestedInformation,
|
|
&DesiredAccess
|
|
);
|
|
|
|
if(!RtlDosPathNameToRelativeNtPathName_U(
|
|
lpFileName,
|
|
&FileName,
|
|
NULL,
|
|
&RelativeName
|
|
))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
FreeBuffer = FileName.Buffer;
|
|
|
|
if(RelativeName.RelativeName.Length)
|
|
{
|
|
FileName = RelativeName.RelativeName;
|
|
}
|
|
else
|
|
{
|
|
RelativeName.ContainingDirectory = NULL;
|
|
}
|
|
|
|
InitializeObjectAttributes(
|
|
&Obja,
|
|
&FileName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
RelativeName.ContainingDirectory,
|
|
NULL
|
|
);
|
|
// Check for backup operator priv.
|
|
if(UseBackUp)
|
|
{
|
|
WStatus = NtOpenFile(
|
|
&FileHandle,
|
|
DesiredAccess,
|
|
&Obja,
|
|
&IoStatusBlock,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
FILE_OPEN_FOR_BACKUP_INTENT
|
|
);
|
|
}
|
|
else
|
|
{
|
|
WStatus = NtOpenFile(
|
|
&FileHandle,
|
|
DesiredAccess,
|
|
&Obja,
|
|
&IoStatusBlock,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
0
|
|
);
|
|
}
|
|
|
|
RtlReleaseRelativeName(&RelativeName);
|
|
RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer);
|
|
|
|
if(NT_SUCCESS(WStatus))
|
|
{
|
|
WStatus = NtQuerySecurityObject(
|
|
FileHandle,
|
|
RequestedInformation,
|
|
pSecurityDescriptor,
|
|
nLength,
|
|
lpnLengthNeeded
|
|
);
|
|
NtClose(FileHandle);
|
|
}
|
|
|
|
|
|
if(!NT_SUCCESS(WStatus))
|
|
{
|
|
// LastNTError(WStatus);
|
|
return(FALSE);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOL
|
|
GetFileSecurityBackup(
|
|
LPSTR lpFileName,
|
|
SECURITY_INFORMATION RequestedInformation,
|
|
PSECURITY_DESCRIPTOR pSecurityDescriptor,
|
|
DWORD nLength,
|
|
LPDWORD lpnLengthNeeded,
|
|
BOOL BackUpPrivFlag
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
ANSI thunk to GetFileSecurityBackupW
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PUNICODE_STRING Unicode;
|
|
ANSI_STRING AnsiString;
|
|
NTSTATUS FStatus;
|
|
|
|
Unicode = &NtCurrentTeb()->StaticUnicodeString;
|
|
RtlInitAnsiString(&AnsiString,lpFileName);
|
|
FStatus = RtlAnsiStringToUnicodeString(Unicode,&AnsiString,FALSE);
|
|
if(!NT_SUCCESS(FStatus))
|
|
{
|
|
// LastNTError(FStatus);
|
|
return FALSE;
|
|
}
|
|
return ( GetFileSecurityBackupW( Unicode->Buffer,
|
|
RequestedInformation,
|
|
pSecurityDescriptor,
|
|
nLength,
|
|
lpnLengthNeeded,
|
|
BackUpPrivFlag
|
|
)
|
|
);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VOID
|
|
QuerySecAccessMask(
|
|
IN SECURITY_INFORMATION SecurityInformation,
|
|
OUT LPDWORD DesiredAccess
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine builds an access mask representing the accesses necessary
|
|
to query the object security information specified in the
|
|
SecurityInformation parameter. While it is not difficult to determine
|
|
this information, the use of a single routine to generate it will ensure
|
|
minimal impact when the security information associated with an object is
|
|
extended in the future (to include mandatory access control information).
|
|
|
|
Arguments:
|
|
|
|
SecurityInformation - Identifies the object's security information to be
|
|
queried.
|
|
|
|
DesiredAccess - Points to an access mask to be set to represent the
|
|
accesses necessary to query the information specified in the
|
|
SecurityInformation parameter.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// Figure out accesses needed to perform the indicated operation(s).
|
|
//
|
|
|
|
(*DesiredAccess) = 0;
|
|
|
|
if ((SecurityInformation & OWNER_SECURITY_INFORMATION) ||
|
|
(SecurityInformation & GROUP_SECURITY_INFORMATION) ||
|
|
(SecurityInformation & DACL_SECURITY_INFORMATION)) {
|
|
(*DesiredAccess) |= READ_CONTROL;
|
|
}
|
|
|
|
if ((SecurityInformation & SACL_SECURITY_INFORMATION)) {
|
|
(*DesiredAccess) |= ACCESS_SYSTEM_SECURITY;
|
|
}
|
|
|
|
return;
|
|
|
|
} // end function
|
|
|
|
|
|
|
|
|
|
/* ******************************************************************
|
|
This routines filter out odd user inputs . .. ../ / _: and
|
|
unc //xxx/xxx. The routine adds a backslash to root level
|
|
directories only. For the "FROM" String.
|
|
****************************************************************** */
|
|
BOOL CleanUpSource(IN LPTSTR InString,
|
|
OUT LPTSTR OutString,
|
|
OUT BOOL *DirectoryFlag)
|
|
{
|
|
LPTSTR searchchar,
|
|
schar,
|
|
OutstringAddr=NULL;
|
|
|
|
char CurDir[STANDARD_BUFFER_SIZE],
|
|
SaveCurDir[STANDARD_BUFFER_SIZE],
|
|
TempBuff[STANDARD_BUFFER_SIZE];
|
|
DWORD DirNameLen;
|
|
BOOL Valid=TRUE;
|
|
|
|
strcpy(OutString, InString);
|
|
|
|
OutstringAddr=OutString;
|
|
|
|
// Check for ":" file type
|
|
searchchar = strchr(OutString, ':');
|
|
if(searchchar != NULL)
|
|
{
|
|
// Have a device type root dir
|
|
// Check the next char of NULL
|
|
searchchar++;
|
|
if(*searchchar == (CHAR) NULL)
|
|
{
|
|
// add a "\" after the ":"
|
|
*searchchar = 0x5c;
|
|
searchchar++;
|
|
// Terminate the string
|
|
*searchchar = (CHAR) NULL;
|
|
*DirectoryFlag = TRUE;
|
|
return(TRUE);
|
|
}
|
|
// Have a : Check for "\"
|
|
// Note this takes care of _:\ paths Can't Do Checking on redirected
|
|
// drives with findfirstfile program will blow out later
|
|
|
|
if(*searchchar == 0x5c)
|
|
{
|
|
//check for NULL
|
|
searchchar++;
|
|
if(*searchchar == (CHAR) NULL)
|
|
{
|
|
*DirectoryFlag = TRUE;
|
|
return(TRUE);
|
|
}
|
|
}
|
|
// Need to check for relative path stuff ".\.\.." etc
|
|
if(IsRelativeString(InString))
|
|
{
|
|
strcpy(TempBuff, InString);
|
|
// Save Current directory
|
|
DirNameLen = GetCurrentDirectory(STANDARD_BUFFER_SIZE,
|
|
(LPTSTR) SaveCurDir);
|
|
if(DirNameLen == 0)
|
|
return(FALSE);
|
|
// Find the end directory
|
|
searchchar = strrchr(InString, 0x5c);
|
|
schar = strrchr(TempBuff, 0x5c);
|
|
if(schar == NULL)
|
|
return(FALSE);
|
|
// Chech for . or ..
|
|
schar++;
|
|
if(*schar == '.')
|
|
{
|
|
schar++;
|
|
if(*schar == '.')
|
|
{
|
|
schar++;
|
|
*schar == (CHAR) NULL;
|
|
searchchar+3;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
schar--;
|
|
*schar == (CHAR) NULL;
|
|
}
|
|
// Have the path now get the real path
|
|
if(!SetCurrentDirectory(TempBuff))
|
|
return(FALSE);
|
|
// Now Save the current directory
|
|
DirNameLen = GetCurrentDirectory(STANDARD_BUFFER_SIZE, (LPTSTR) CurDir);
|
|
if(DirNameLen == 0)
|
|
return(FALSE);
|
|
*OutstringAddr = (CHAR) NULL;
|
|
// Build The String with real path
|
|
strcpy(OutString, CurDir);
|
|
// Remove end "\" from "C:\" GetCurrentDir.. returns with "\" on root
|
|
RemoveEndSlash(OutString);
|
|
strcat(OutString, searchchar);
|
|
// return to the user's diretory
|
|
if(!SetCurrentDirectory(SaveCurDir))
|
|
return(FALSE);
|
|
|
|
}
|
|
// Check for wild card
|
|
if(IsWildCard(OutString))
|
|
{
|
|
*DirectoryFlag = FALSE;
|
|
return(TRUE);
|
|
}
|
|
// Check for Direcory or file
|
|
if(!IsDirectory(OutString, &Valid))
|
|
*DirectoryFlag = FALSE;
|
|
else
|
|
*DirectoryFlag = TRUE;
|
|
|
|
if(Valid == FALSE)
|
|
return(FALSE);
|
|
return(TRUE);
|
|
}
|
|
// Have a nondevice name
|
|
|
|
// Check for "\\" in first 2 chars in file path for UNC path
|
|
if(strncmp(InString, "\\\\", 2) == 0)
|
|
{
|
|
// Bump pointer
|
|
InString +=3;
|
|
// Serarch for the next "\"
|
|
searchchar = strchr(InString, 0x5c);
|
|
if(searchchar == NULL)
|
|
return(FALSE);
|
|
// Have the 3rd one check for fourth on in typical UNC string
|
|
searchchar++;
|
|
searchchar = strchr(searchchar, 0x5c);
|
|
if(searchchar == NULL)
|
|
{ // Have UNC Pth Only
|
|
// Need to add "\" to end of string
|
|
strcat(OutString, "\\");
|
|
*DirectoryFlag = TRUE;
|
|
return(TRUE);
|
|
}
|
|
else
|
|
{
|
|
// Have the fouth "\" need to check for file or directory
|
|
// Check for wild card
|
|
if(IsWildCard(OutString))
|
|
{
|
|
*DirectoryFlag = FALSE;
|
|
return(TRUE);
|
|
}
|
|
// Check for Direcory or file
|
|
if(!IsDirectory(OutString, &Valid))
|
|
*DirectoryFlag = FALSE;
|
|
else
|
|
*DirectoryFlag = TRUE;
|
|
if(Valid == FALSE)
|
|
return(FALSE);
|
|
return(TRUE);
|
|
}
|
|
} // End of "\\"
|
|
|
|
|
|
// Check for a "\"
|
|
if(*OutString == 0x5c)
|
|
{
|
|
// Have a leading "\" check next char
|
|
OutString++;
|
|
if(*OutString != (CHAR) NULL)
|
|
{
|
|
// Check for wild card
|
|
if(IsWildCard(InString))
|
|
{
|
|
*DirectoryFlag = FALSE;
|
|
return(TRUE);
|
|
}
|
|
// Check for directory
|
|
if(!IsDirectory(InString, &Valid))
|
|
*DirectoryFlag = FALSE;
|
|
else
|
|
*DirectoryFlag = TRUE;
|
|
if(Valid == FALSE)
|
|
return(FALSE);
|
|
return(TRUE);
|
|
}
|
|
// Have a single need to get full "_:\"
|
|
DirNameLen = GetCurrentDirectory(STANDARD_BUFFER_SIZE, (LPTSTR) CurDir);
|
|
if(DirNameLen == 0)
|
|
return(FALSE);
|
|
// Now feed the result in to StripRootDir
|
|
// Set OutString to a NULL char to recive the string
|
|
OutString--;
|
|
*OutString = (CHAR) NULL;
|
|
if(!StripRootDir( (LPTSTR) CurDir, OutString))
|
|
return(FALSE);
|
|
*DirectoryFlag = TRUE;
|
|
return(TRUE);
|
|
} // End of "\"
|
|
|
|
// Now check for .. ../
|
|
if(strncmp(InString, "..", 2) == 0)
|
|
{
|
|
// Save Current directory
|
|
DirNameLen = GetCurrentDirectory(STANDARD_BUFFER_SIZE, (LPTSTR) SaveCurDir);
|
|
if(DirNameLen == 0)
|
|
return(FALSE);
|
|
// Chech the Input string for the last Slash
|
|
searchchar = strrchr(InString, 0x5c);
|
|
if(searchchar == NULL)
|
|
{ // Just have ..
|
|
// set current dir to where the path (InString) is
|
|
if(!SetCurrentDirectory(InString))
|
|
return(FALSE);
|
|
// Now Save the current directory
|
|
DirNameLen = GetCurrentDirectory(STANDARD_BUFFER_SIZE, (LPTSTR) CurDir);
|
|
if(DirNameLen == 0)
|
|
return(FALSE);
|
|
strcpy(OutString, CurDir);
|
|
*DirectoryFlag = TRUE;
|
|
// return to the user's diretory
|
|
if(!SetCurrentDirectory(SaveCurDir))
|
|
return(FALSE);
|
|
return(TRUE);
|
|
}
|
|
else // Have smething after the ..
|
|
{
|
|
// Need to check for a ending ".."
|
|
schar = strstr(searchchar, "..");
|
|
if(schar != NULL)
|
|
{
|
|
// set current dir to where the path (InString) is
|
|
if(!SetCurrentDirectory(InString))
|
|
return(FALSE);
|
|
|
|
// Now Save the current directory
|
|
DirNameLen = GetCurrentDirectory(STANDARD_BUFFER_SIZE, (LPTSTR) CurDir);
|
|
if(DirNameLen == 0)
|
|
return(FALSE);
|
|
// Save the path
|
|
strcpy(OutString, CurDir);
|
|
*DirectoryFlag = TRUE;
|
|
// return to the user's diretory
|
|
if(!SetCurrentDirectory(SaveCurDir))
|
|
return(FALSE);
|
|
return(TRUE);
|
|
}
|
|
// Save the last "\" Position
|
|
schar = strrchr(OutString, 0x5c);
|
|
|
|
// Terminate the string after the last slash
|
|
*schar = (CHAR) NULL;
|
|
// set current dir to where the path (OutString) is
|
|
if(!SetCurrentDirectory(OutString))
|
|
return(FALSE);
|
|
// Now Save the current directory
|
|
DirNameLen = GetCurrentDirectory(STANDARD_BUFFER_SIZE, (LPTSTR) CurDir);
|
|
if(DirNameLen == 0)
|
|
return(FALSE);
|
|
// Save the path
|
|
strcpy(OutString, CurDir);
|
|
// Copy anything after and including the "\" for the input string
|
|
strcat(OutString, searchchar);
|
|
// Check for wildcard
|
|
if(IsWildCard(InString))
|
|
{
|
|
// Restore dir path
|
|
if(!SetCurrentDirectory(SaveCurDir))
|
|
return(FALSE);
|
|
*DirectoryFlag = FALSE;
|
|
return(TRUE);
|
|
}
|
|
|
|
// Check for Direcory or file
|
|
if(!IsDirectory(OutString, &Valid))
|
|
*DirectoryFlag = FALSE;
|
|
else
|
|
*DirectoryFlag = TRUE;
|
|
|
|
// Restore dir path
|
|
if(!SetCurrentDirectory(SaveCurDir))
|
|
return(FALSE);
|
|
|
|
if(Valid == FALSE)
|
|
return(FALSE);
|
|
|
|
return(TRUE);
|
|
}
|
|
} // End of "..\"
|
|
|
|
|
|
// "." and ".\"
|
|
if(*InString == '.')
|
|
{
|
|
// Save Current directory
|
|
DirNameLen = GetCurrentDirectory(STANDARD_BUFFER_SIZE, (LPTSTR) SaveCurDir);
|
|
if(DirNameLen == 0)
|
|
return(FALSE);
|
|
// Chech the Input string for the last Slash
|
|
searchchar = strrchr(InString, 0x5c);
|
|
if(searchchar == NULL)
|
|
{ // Just have . or something after it ._
|
|
// set current dir to where the path (InString) is
|
|
if(!SetCurrentDirectory(InString))
|
|
{
|
|
strcpy(OutString, SaveCurDir);
|
|
// Add "\" directory
|
|
strcat(OutString, "\\");
|
|
strcat(OutString, InString);
|
|
*DirectoryFlag = FALSE;
|
|
return(TRUE);
|
|
}
|
|
// Now Save the current directory
|
|
DirNameLen = GetCurrentDirectory(STANDARD_BUFFER_SIZE, (LPTSTR) CurDir);
|
|
if(DirNameLen == 0)
|
|
return(FALSE);
|
|
strcpy(OutString, CurDir);
|
|
*DirectoryFlag = TRUE;
|
|
// return to the user's diretory
|
|
if(!SetCurrentDirectory(SaveCurDir))
|
|
return(FALSE);
|
|
return(TRUE);
|
|
}
|
|
else // Have smething after the .
|
|
{
|
|
// Need to check for a ending ".."
|
|
schar = strstr(searchchar, "..");
|
|
if(schar != NULL)
|
|
{
|
|
// set current dir to where the path (InString) is
|
|
if(!SetCurrentDirectory(InString))
|
|
return(FALSE);
|
|
|
|
// Now Save the current directory
|
|
DirNameLen = GetCurrentDirectory(STANDARD_BUFFER_SIZE, (LPTSTR) CurDir);
|
|
if(DirNameLen == 0)
|
|
return(FALSE);
|
|
// Save the path
|
|
strcpy(OutString, CurDir);
|
|
*DirectoryFlag = TRUE;
|
|
// return to the user's diretory
|
|
if(!SetCurrentDirectory(SaveCurDir))
|
|
return(FALSE);
|
|
return(TRUE);
|
|
}
|
|
// Save the last "\" Position
|
|
schar = strrchr(OutString, 0x5c);
|
|
|
|
// Terminate the string after the last slash
|
|
*schar = (CHAR) NULL;
|
|
// set current dir to where the path (OutString) is
|
|
if(!SetCurrentDirectory(OutString))
|
|
return(FALSE);
|
|
// Now Save the current directory
|
|
DirNameLen = GetCurrentDirectory(STANDARD_BUFFER_SIZE, (LPTSTR) CurDir);
|
|
if(DirNameLen == 0)
|
|
return(FALSE);
|
|
// Save the path
|
|
strcpy(OutString, CurDir);
|
|
// Copy anything after and including the "\" for the input string
|
|
strcat(OutString, searchchar);
|
|
// Check for wildcard
|
|
if(IsWildCard(InString))
|
|
{
|
|
// Restore dir path
|
|
if(!SetCurrentDirectory(SaveCurDir))
|
|
return(FALSE);
|
|
*DirectoryFlag = FALSE;
|
|
return(TRUE);
|
|
}
|
|
|
|
// Check for Direcory or file
|
|
if(!IsDirectory(OutString, &Valid))
|
|
*DirectoryFlag = FALSE;
|
|
else
|
|
*DirectoryFlag = TRUE;
|
|
|
|
// Restore dir path
|
|
if(!SetCurrentDirectory(SaveCurDir))
|
|
return(FALSE);
|
|
|
|
if(Valid == FALSE)
|
|
return(FALSE);
|
|
|
|
return(TRUE);
|
|
}
|
|
} // End of "." ".\"
|
|
|
|
|
|
|
|
// Now only have a file name or directory local
|
|
DirNameLen = GetCurrentDirectory(STANDARD_BUFFER_SIZE, (LPTSTR) CurDir);
|
|
if(DirNameLen == 0)
|
|
return(FALSE);
|
|
strcpy(OutString, CurDir);
|
|
// Check if last last char slash
|
|
if(!IsLastCharSlash(OutString))
|
|
strcat(OutString, "\\");
|
|
strcat(OutString, InString);
|
|
// Check for wild Card
|
|
if(IsWildCard(InString))
|
|
{
|
|
*DirectoryFlag = FALSE;
|
|
return(TRUE);
|
|
}
|
|
// Check for Directory
|
|
if(!IsDirectory(OutString, &Valid))
|
|
*DirectoryFlag = FALSE;
|
|
else
|
|
*DirectoryFlag = TRUE;
|
|
if(Valid == FALSE)
|
|
return(FALSE);
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
/* ********************************************************************
|
|
*********************************************************************** */
|
|
BOOL IsDirectory(IN LPTSTR InTestFile,
|
|
IN BOOL *FileValid)
|
|
{
|
|
WIN32_FIND_DATA FindFileData;
|
|
HANDLE FindFileHandle;
|
|
char IsBuff[STANDARD_BUFFER_SIZE];
|
|
|
|
strcpy(IsBuff, InTestFile);
|
|
if(RemoveEndSlash((LPTSTR) IsBuff))
|
|
FindFileHandle = FindFirstFile(IsBuff, &FindFileData);
|
|
else
|
|
FindFileHandle = FindFirstFile(InTestFile, &FindFileData);
|
|
|
|
|
|
if(FindFileHandle == INVALID_HANDLE_VALUE)
|
|
{
|
|
// printf("\n problem with findfirstfile in IsDirectory");
|
|
*FileValid = FALSE;
|
|
return(FALSE);
|
|
}
|
|
if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
{
|
|
FindClose(FindFileHandle); // changed by a-zexu @ 10/19/97
|
|
return(TRUE);
|
|
}
|
|
FindClose(FindFileHandle); // changed by a-zexu @ 10/19/97
|
|
return(FALSE);
|
|
|
|
|
|
}
|
|
|
|
|
|
BOOL IsWildCard(LPSTR psz)
|
|
{
|
|
char ch;
|
|
|
|
while (ch = *psz++)
|
|
{
|
|
if (ch == '*' || ch == '?')
|
|
return(TRUE);
|
|
}
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
BOOL RemoveEndSlash(LPSTR TestString)
|
|
{
|
|
LPTSTR slashptr;
|
|
|
|
slashptr = strrchr(TestString, 0x5c);
|
|
if(slashptr == NULL)
|
|
return(FALSE);
|
|
// Check Next char for NULL
|
|
slashptr++;
|
|
if(*slashptr == (CHAR) NULL)
|
|
{
|
|
slashptr--;
|
|
*slashptr = (CHAR) NULL;
|
|
return(TRUE);
|
|
}
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
BOOL SetSlash(IN LPTSTR InString,
|
|
IN OUT LPTSTR TestString)
|
|
{
|
|
LPTSTR slashptr;
|
|
strcpy(TestString, InString);
|
|
slashptr = strrchr(TestString, 0x5c);
|
|
if(slashptr == NULL)
|
|
return(FALSE);
|
|
slashptr++;
|
|
*slashptr = (CHAR) NULL;
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
BOOL AddDotSlash(LPSTR TestString)
|
|
{
|
|
LPTSTR slashptr;
|
|
|
|
// Find End of String
|
|
slashptr = strrchr(TestString, (CHAR) NULL);
|
|
if(slashptr == NULL)
|
|
return(FALSE);
|
|
// Check previous char for "\"
|
|
slashptr--;
|
|
if(*slashptr == 0x5c)
|
|
{
|
|
slashptr++;
|
|
*slashptr = '.';
|
|
slashptr++;
|
|
*slashptr = (CHAR) NULL;
|
|
}
|
|
else
|
|
{
|
|
slashptr++;
|
|
*slashptr = 0x5c;
|
|
slashptr++;
|
|
*slashptr = '.';
|
|
slashptr++;
|
|
*slashptr = (CHAR) NULL;
|
|
}
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
BOOL AddWildCards(LPSTR TestString)
|
|
{
|
|
LPTSTR slashptr;
|
|
|
|
// Find End of String
|
|
slashptr = strrchr(TestString, (CHAR) NULL);
|
|
if(slashptr == NULL)
|
|
return(FALSE);
|
|
// Check previous char for "\"
|
|
slashptr--;
|
|
if(*slashptr == 0x5c)
|
|
{
|
|
slashptr++;
|
|
*slashptr = '*';
|
|
slashptr++;
|
|
*slashptr = '.';
|
|
slashptr++;
|
|
*slashptr = '*';
|
|
slashptr++;
|
|
*slashptr = (CHAR) NULL;
|
|
}
|
|
else
|
|
{
|
|
slashptr++;
|
|
*slashptr = 0x5c;
|
|
slashptr++;
|
|
*slashptr = '*';
|
|
slashptr++;
|
|
*slashptr = '.';
|
|
slashptr++;
|
|
*slashptr = '*';
|
|
slashptr++;
|
|
*slashptr = (CHAR) NULL;
|
|
}
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
BOOL IsLastCharSlash(LPSTR TestString)
|
|
{
|
|
LPTSTR slashptr;
|
|
|
|
// Find End of String
|
|
slashptr = strrchr(TestString, (CHAR) NULL);
|
|
if(slashptr == NULL)
|
|
return(FALSE);
|
|
// Check previous char for "\"
|
|
slashptr--;
|
|
if(*slashptr == 0x5c)
|
|
return(TRUE);
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
BOOL IsRelativeString(LPSTR TestString)
|
|
{
|
|
LPTSTR slashptr;
|
|
// Start looking for Relative strings order is important
|
|
slashptr = strstr(TestString, "..\\");
|
|
if(slashptr != NULL)
|
|
return(TRUE);
|
|
slashptr = strstr(TestString, ".\\");
|
|
if(slashptr != NULL)
|
|
return(TRUE);
|
|
slashptr = strstr(TestString, "\\..");
|
|
if(slashptr != NULL)
|
|
return(TRUE);
|
|
slashptr = strstr(TestString, "\\.");
|
|
if(slashptr != NULL)
|
|
{
|
|
// Check Next Char for NULL or "\"
|
|
slashptr++;
|
|
if(*slashptr == (CHAR) NULL);
|
|
return(TRUE);
|
|
if(*slashptr == 0x5c);
|
|
return(TRUE);
|
|
}
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
|
|
BOOL RemoveEndDot(LPSTR TestString)
|
|
{
|
|
LPTSTR slashptr;
|
|
|
|
// Find End of String
|
|
slashptr = strrchr(TestString, (CHAR) NULL);
|
|
if(slashptr == NULL)
|
|
return(FALSE);
|
|
// Check previous char for "."
|
|
slashptr--;
|
|
if(*slashptr == '.')
|
|
{
|
|
*slashptr = (CHAR) NULL;
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
|
|
/* *********************************************************************
|
|
********************************************************************* */
|
|
BOOL StripRootDir(IN LPTSTR InDir,
|
|
OUT LPTSTR OutRootDir)
|
|
{
|
|
LPTSTR searchchar;
|
|
|
|
strcpy(OutRootDir, InDir);
|
|
|
|
// Check for ":" file type
|
|
searchchar = strchr(OutRootDir, ':');
|
|
if(searchchar != NULL)
|
|
{
|
|
// Have a device type root dir
|
|
searchchar++;
|
|
// add a "\" after the ":"
|
|
*searchchar = 0x5c;
|
|
searchchar++;
|
|
// Terminate the string
|
|
*searchchar = (CHAR) NULL;
|
|
return(TRUE);
|
|
}
|
|
else // Have a nondevice name
|
|
{
|
|
// Check for "\\" in first 2 chars in file path for UNC path
|
|
if( strncmp(OutRootDir, "\\\\", 2) == 0)
|
|
{
|
|
// Bump pointer
|
|
OutRootDir +=3;
|
|
// Serarch for the next "\"
|
|
searchchar = strchr(OutRootDir, 0x5c);
|
|
if(searchchar == NULL)
|
|
return(FALSE);
|
|
// Have the 3rd one check for fourth on in typical UNC string
|
|
searchchar++;
|
|
searchchar = strchr(searchchar, 0x5c);
|
|
if(searchchar == NULL)
|
|
{ // Have UNC Pth Only
|
|
// Need to add "\" to end of string
|
|
OutRootDir += strlen(OutRootDir);
|
|
*OutRootDir = 0x5c;
|
|
++OutRootDir;
|
|
*OutRootDir = (CHAR) NULL;
|
|
return(TRUE);
|
|
}
|
|
else
|
|
{
|
|
// Have the fouth "\"
|
|
++searchchar;
|
|
// Add NULL
|
|
*searchchar = (CHAR) NULL;
|
|
return(TRUE);
|
|
}
|
|
}
|
|
else // Have a "\" or whatever
|
|
{
|
|
*OutRootDir = (CHAR) NULL;
|
|
return(TRUE);
|
|
}
|
|
}
|
|
// Should not get here
|
|
return(FALSE);
|
|
}
|
|
|
|
// End of File
|