windows-nt/Source/XPSP1/NT/inetsrv/iis/svcs/infocomm/cache2/filemisc.cxx

397 lines
9.6 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/**********************************************************************/
/** Microsoft Windows NT **/
/** Copyright(c) Microsoft Corp., 1994 **/
/**********************************************************************/
/*
filemisc.cxx
This module contains some random functions for manipulating
TS_OPEN_FILE_INFO objects
FILE HISTORY:
MCourage 09-Dec-1997 Created
*/
#include <tsunami.hxx>
#include <imd.h>
#include <mb.hxx>
#include <mbstring.h>
#include "tsunamip.hxx"
#include "etagmb.h"
BOOL
TsDeleteOnClose(PW3_URI_INFO pURIInfo,
HANDLE OpeningUser,
BOOL *fDeleted)
/*++
Routine Description:
Marks the file associated with the passed URIInfo for deletion. When everyone
is done using that file, it will be deleted
Arguments:
pURIInfo - The W3_URI_INFO whose file will be marked for deletion
OpeningUser - HANDLE for the user attempting the delete operation
fDeleted - Will be set if TsDeleteOnClose returns TRUE. If the user has access
and the file was marked deleted fDeleted will be TRUE. Otherwise it will be
FALSE.
Return Values:
TRUE - The user had access and the file was marked, or the user was denied access.
FALSE - An error other than Access Denied occured.
--*/
{
//
// Doesn't do anything. Ha ha!
//
*fDeleted = FALSE;
return FALSE;
}
PSECURITY_DESCRIPTOR
TsGetFileSecDesc(
LPTS_OPEN_FILE_INFO pFile
)
/*++
Routine Description:
Returns the security descriptor associated to the file
To be freed using LocalFree()
Arguments:
pFile - ptr to fie object
Return Value:
ptr to security descriptor or NULL if error
--*/
{
SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION |
DACL_SECURITY_INFORMATION;
BYTE abSecDesc[ SECURITY_DESC_DEFAULT_SIZE ];
DWORD dwSecDescSize;
PSECURITY_DESCRIPTOR pAcl;
if ( GetKernelObjectSecurity(
pFile->QueryFileHandle(),
si,
(PSECURITY_DESCRIPTOR)abSecDesc,
SECURITY_DESC_DEFAULT_SIZE,
&dwSecDescSize ) )
{
if ( dwSecDescSize > SECURITY_DESC_DEFAULT_SIZE )
{
if ( !(pAcl = (PSECURITY_DESCRIPTOR)LocalAlloc( LMEM_FIXED, dwSecDescSize )) )
{
return NULL;
}
if ( !GetKernelObjectSecurity(
pFile->QueryFileHandle(),
si,
pAcl,
dwSecDescSize,
&dwSecDescSize ) )
{
LocalFree( pAcl );
return NULL;
}
}
else
{
if ( dwSecDescSize = GetSecurityDescriptorLength(abSecDesc) )
{
if ( !(pAcl = (PSECURITY_DESCRIPTOR)LocalAlloc( LMEM_FIXED,
dwSecDescSize )) )
{
return NULL;
}
memcpy( pAcl, abSecDesc, dwSecDescSize );
}
else
{
//
// Security descriptor is empty : do not return ptr to security descriptor
//
pAcl = NULL;
}
}
}
else
{
pAcl = NULL;
}
return pAcl;
}
BOOL TsCreateETagFromHandle(
IN HANDLE hFile,
IN PCHAR ETag,
IN BOOL *bWeakETag
)
/*+++
TsCreateETagFromHandle
This routine takes a file handle as input, and creates an ETag in
the supplied buffer for that file handle.
Arguments:
hFile - File handle for which to create an ETag.
ETag - Where to store the ETag. This must be long
enough to hold the maximum length ETag.
bWeakETag - Set to TRUE if the newly created ETag is weak.
Returns:
TRUE if we create an ETag, FALSE otherwise.
---*/
{
BY_HANDLE_FILE_INFORMATION FileInfo;
BOOL bReturn;
PUCHAR Temp;
FILETIME ftNow;
DWORD dwChangeNumber = ETagChangeNumber::GetChangeNumber();
bReturn = GetFileInformationByHandle(
hFile,
&FileInfo
);
if (!bReturn)
{
return FALSE;
}
FORMAT_ETAG(ETag, FileInfo.ftLastWriteTime, dwChangeNumber );
::GetSystemTimeAsFileTime(&ftNow);
__int64 iNow, iFileTime;
iNow = (__int64)*(__int64 *)&ftNow;
iFileTime = (__int64)*(__int64 *)&FileInfo.ftLastWriteTime;
if ((iNow - iFileTime) > STRONG_ETAG_DELTA )
{
*bWeakETag = FALSE;
}
else
{
*bWeakETag = TRUE;
}
return TRUE;
}
BOOL TsLastWriteTimeFromHandle(
IN HANDLE hFile,
IN FILETIME *tm
)
/*+++
TsLastWriteTimeFromHandle
This routine takes a file handle as input, and returns the last write time
for that handle.
Arguments:
hFile - File handle for which to get the last write time.
tm - Where to return the last write time.
Returns:
TRUE if we succeed, FALSE otherwise.
---*/
{
BY_HANDLE_FILE_INFORMATION FileInfo;
BOOL bReturn;
bReturn = GetFileInformationByHandle(
hFile,
&FileInfo
);
if (!bReturn)
{
return FALSE;
}
*tm = FileInfo.ftLastWriteTime;
return TRUE;
}
DWORD
CheckIfShortFileName(
IN CONST UCHAR * pszPath,
IN HANDLE hImpersonation,
OUT BOOL * pfShort
)
/*++
Description:
This function takes a suspected NT/Win95 short filename and checks if there's
an equivalent long filename. For example, c:\foobar\ABCDEF~1.ABC is the same
as c:\foobar\abcdefghijklmnop.abc.
NOTE: This function should be called unimpersonated - the FindFirstFile() must
be called in the system context since most systems have traverse checking turned
off - except for the UNC case where we must be impersonated to get network access.
Arguments:
pszPath - Path to check
hImpersonation - Impersonation handle if this is a UNC path - can be NULL if not UNC
pfShort - Set to TRUE if an equivalent long filename is found
Returns:
Win32 error on failure
--*/
{
DWORD err = NO_ERROR;
WIN32_FIND_DATA FindData;
UCHAR * psz;
BOOL fUNC;
psz = _mbschr( (UCHAR *) pszPath, '~' );
*pfShort = FALSE;
fUNC = (*pszPath == '\\');
//
// Loop for multiple tildas - watch for a # after the tilda
//
while ( psz++ )
{
if ( *psz >= '0' && *psz <= '9' )
{
UCHAR achTmp[MAX_PATH];
UCHAR * pchEndSeg;
UCHAR * pchBeginSeg;
HANDLE hFind;
//
// Isolate the path up to the segment with the
// '~' and do the FindFirst with that path
//
pchEndSeg = _mbschr( psz, '\\' );
if ( !pchEndSeg )
{
pchEndSeg = psz + _mbslen( psz );
}
//
// If the string is beyond MAX_PATH then we allow it through
//
if ( ((INT) (pchEndSeg - pszPath)) >= sizeof( achTmp ))
{
return NO_ERROR;
}
memcpy( achTmp, pszPath, (INT) (pchEndSeg - pszPath) );
achTmp[pchEndSeg - pszPath] = '\0';
if ( fUNC && hImpersonation )
{
if ( !ImpersonateLoggedOnUser( hImpersonation ))
{
return GetLastError();
}
}
hFind = FindFirstFile( (CHAR *) achTmp, &FindData );
if ( fUNC && hImpersonation )
{
RevertToSelf();
}
if ( hFind == INVALID_HANDLE_VALUE )
{
err = GetLastError();
DBGPRINTF(( DBG_CONTEXT,
"FindFirst failed!! - \"%s\", error %d\n",
achTmp,
GetLastError() ));
//
// If the FindFirstFile() fails to find the file then return
// success - the path doesn't appear to be a valid path which
// is ok.
//
if ( err == ERROR_FILE_NOT_FOUND ||
err == ERROR_PATH_NOT_FOUND )
{
return NO_ERROR;
}
return err;
}
DBG_REQUIRE( FindClose( hFind ));
//
// Isolate the last segment of the string which should be
// the potential short name equivalency
//
pchBeginSeg = _mbsrchr( achTmp, '\\' );
DBG_ASSERT( pchBeginSeg );
pchBeginSeg++;
//
// If the last segment doesn't match the long name then this is
// the short name version of the path
//
if ( _mbsicmp( (UCHAR *) FindData.cFileName, pchBeginSeg ))
{
*pfShort = TRUE;
return NO_ERROR;
}
}
psz = _mbschr( psz, '~' );
}
return err;
}
//
// filemisc.cxx
//