Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1685 lines
48 KiB

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
string.c
Abstract:
This file implements file functions for fax.
Author:
Wesley Witt (wesw) 23-Jan-1995
Environment:
User Mode
--*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
#include <Accctrl.h>
#include <Aclapi.h>
#include <Shellapi.h>
#include <strsafe.h>
#include "faxutil.h"
#include "faxreg.h"
#include "FaxUIConstants.h"
VOID
DeleteTempPreviewFiles (
LPTSTR lptstrDirectory,
BOOL bConsole
)
/*++
Routine name : DeleteTempPreviewFiles
Routine description:
Deletes all the temporary fax preview TIFF files from a given folder.
Deletes files: "<lptstrDirectory>\<PREVIEW_TIFF_PREFIX>*.<FAX_TIF_FILE_EXT>".
Author:
Eran Yariv (EranY), Apr, 2001
Arguments:
lptstrDirectory [in] - Folder.
Optional - if NULL, the current user's temp dir is used.
bConsole [in] - If TRUE, called from the client console. Otherwise, from the Fax Send Wizard.
Return Value:
None.
--*/
{
TCHAR szTempPath[MAX_PATH * 2];
TCHAR szSearch [MAX_PATH * 3];
WIN32_FIND_DATA W32FindData;
HANDLE hFind = INVALID_HANDLE_VALUE;
TCHAR* pLast = NULL;
HRESULT hRes;
DEBUG_FUNCTION_NAME(TEXT("DeleteTempPreviewFiles"));
if (!lptstrDirectory)
{
if (!GetTempPath( ARR_SIZE(szTempPath), szTempPath ))
{
DebugPrintEx(DEBUG_ERR,
TEXT("GetTempPath() failed. (ec = %lu)"),
GetLastError());
return;
}
lptstrDirectory = szTempPath;
}
//
// find last \ in path
//
pLast = _tcsrchr(lptstrDirectory,TEXT('\\'));
if(pLast && (*_tcsinc(pLast)) == '\0')
{
//
// the last character is a backslash, truncate it...
//
_tcsnset(pLast,'\0',1);
}
hRes = StringCchPrintf(
szSearch,
ARR_SIZE(szSearch),
TEXT("%s\\%s%08x*.%s"),
lptstrDirectory,
bConsole ? CONSOLE_PREVIEW_TIFF_PREFIX : WIZARD_PREVIEW_TIFF_PREFIX,
GetCurrentProcessId(),
FAX_TIF_FILE_EXT
);
if (FAILED(hRes))
{
DebugPrintEx(DEBUG_ERR,
TEXT("StringCchPrintf failed (ec=%lu)"),
HRESULT_CODE(hRes));
return;
}
hFind = FindFirstFile (szSearch, &W32FindData);
if (INVALID_HANDLE_VALUE == hFind)
{
DebugPrintEx(DEBUG_ERR, TEXT("FindFirstFile failed with %ld"), GetLastError ());
return;
}
//
// Loop and delete all preview files
//
for (;;)
{
TCHAR szFile[MAX_PATH * 3];
//
// Compose full path to file
//
hRes = StringCchPrintf(
szFile,
ARR_SIZE(szFile),
TEXT("%s\\%s"),
lptstrDirectory,
W32FindData.cFileName
);
if ( SUCCEEDED(hRes) )
{
//
// Delete the currently found file
//
if (!DeleteFile (szFile))
{
DebugPrintEx(DEBUG_ERR, TEXT("DeleteFile(%s) failed with %ld"), szFile, GetLastError ());
}
else
{
DebugPrintEx(DEBUG_MSG, TEXT("%s deleted"), szFile);
}
}
//
// Find next file
//
if(!FindNextFile(hFind, &W32FindData))
{
if(ERROR_NO_MORE_FILES != GetLastError ())
{
DebugPrintEx(DEBUG_ERR, TEXT("FindNextFile failed with %ld"), GetLastError ());
}
else
{
//
// End of files - no error
//
}
break;
}
}
FindClose (hFind);
} // DeleteTempPreviewFiles
DWORDLONG
GenerateUniqueFileNameWithPrefix(
BOOL bUseProcessId,
LPTSTR lptstrDirectory,
LPTSTR lptstrPrefix,
LPTSTR lptstrExtension,
LPTSTR lptstrFileName,
DWORD dwFileNameSize
)
/*++
Routine name : GenerateUniqueFileNameWithPrefix
Routine description:
Generates a unique file name
Author:
Eran Yariv (EranY), Apr, 2001
Arguments:
bUseProcessId [in] - If TRUE, the process id is appended after the prefix
lptstrDirectory [in] - Directory where file should be created.
Optional - if NULL, the current user's temp dir is used.
lptstrPrefix [in] - File prefix.
Optional - if NULL, no prefix is used.
lptstrExtension [in] - File extension.
Optional - if NULL, FAX_TIF_FILE_EXT is used.
lptstrFileName [out] - File name.
dwFileNameSize [in] - Size of file name (in characters)
Return Value:
Unique file identifier.
Returns 0 in case of error (sets last error).
--*/
{
DWORD i;
TCHAR szTempPath[MAX_PATH * 2];
TCHAR szProcessId[20] = {0};
DWORDLONG dwlUniqueId = 0;
HRESULT hRes;
DEBUG_FUNCTION_NAME(TEXT("GenerateUniqueFileNameWithPrefix"));
if (!lptstrDirectory)
{
if (!GetTempPath( ARR_SIZE(szTempPath), szTempPath ))
{
DebugPrintEx(DEBUG_ERR,
TEXT("GetTempPath() failed. (ec = %lu)"),
GetLastError());
return 0;
}
lptstrDirectory = szTempPath;
}
TCHAR* pLast = NULL;
pLast = _tcsrchr(lptstrDirectory,TEXT('\\'));
if(pLast && (*_tcsinc(pLast)) == '\0')
{
//
// the last character is a backslash, truncate it...
//
_tcsnset(pLast,'\0',1);
}
if (!lptstrExtension)
{
lptstrExtension = FAX_TIF_FILE_EXT;
}
if (!lptstrPrefix)
{
lptstrPrefix = TEXT("");
}
if (bUseProcessId)
{
hRes = StringCchPrintf (szProcessId, ARR_SIZE(szProcessId), TEXT("%08x"), GetCurrentProcessId());
if (FAILED(hRes))
{
DebugPrintEx(DEBUG_ERR,
TEXT("StringCchPrintf failed (ec=%lu)"),
HRESULT_CODE(hRes));
SetLastError(HRESULT_CODE(hRes));
return 0;
}
}
for (i=0; i<256; i++)
{
HANDLE hFile = INVALID_HANDLE_VALUE;
FILETIME FileTime;
SYSTEMTIME SystemTime;
GetSystemTime( &SystemTime ); // returns VOID
if (!SystemTimeToFileTime( &SystemTime, &FileTime ))
{
DebugPrintEx(DEBUG_ERR, TEXT("SystemTimeToFileTime() failed (ec: %ld)"), GetLastError());
return 0;
}
dwlUniqueId = MAKELONGLONG(FileTime.dwLowDateTime, FileTime.dwHighDateTime);
//
// dwlUniqueId holds the number of 100 nanosecond units since 1.1.1601.
// This occuipies most of the 64 bits.We we need some space to add extra
// information (job type for example) to the job id.
// Thus we give up the precision (1/10000000 of a second is too much for us anyhow)
// to free up 8 MSB bits.
// We shift right the time 8 bits to the right. This divides it by 256 which gives
// us time resolution better than 1/10000 of a sec which is more than enough.
//
dwlUniqueId = dwlUniqueId >> 8;
hRes = StringCchPrintf(
lptstrFileName,
dwFileNameSize,
TEXT("%s\\%s%s%I64X.%s"),
lptstrDirectory,
lptstrPrefix,
szProcessId,
dwlUniqueId,
lptstrExtension );
if (FAILED(hRes))
{
DebugPrintEx(DEBUG_ERR,
TEXT("StringCchPrintf failed (ec=%lu)"),
HRESULT_CODE(hRes));
SetLastError(HRESULT_CODE(hRes));
return 0;
}
hFile = SafeCreateFile(
lptstrFileName,
GENERIC_WRITE,
0,
NULL,
CREATE_NEW,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
DWORD dwError = GetLastError();
if (dwError == ERROR_ALREADY_EXISTS || dwError == ERROR_FILE_EXISTS)
{
continue;
}
else
{
//
// Real error
//
DebugPrintEx(DEBUG_ERR,
TEXT("CreateFile() for [%s] failed. (ec: %ld)"),
lptstrFileName,
GetLastError());
return 0;
}
}
else
{
//
// Success
//
CloseHandle (hFile);
break;
}
}
if (i == 256)
{
DebugPrintEx( DEBUG_ERR,
TEXT("Failed to generate a unique file name after %d attempts. \n")
TEXT("Last attempted UniqueIdValue value is: 0x%I64X \n")
TEXT("Last attempted file name is : [%s]"),
i,
dwlUniqueId,
lptstrFileName);
SetLastError( ERROR_TOO_MANY_OPEN_FILES );
return 0;
}
return dwlUniqueId;
} // GenerateUniqueFileNameWithPrefix
//*********************************************************************************
//* Name: GenerateUniqueFileName()
//* Author:
//* Date:
//*********************************************************************************
//* DESCRIPTION:
//* Generates a unique file in the queue directory.
//* returns a UNIQUE id for the file.
//* PARAMETERS:
//* [IN] LPTSTR Directory
//* The path where the file is to be created.
//* [OUT] LPTSTR Extension
//* The file extension that the generated file should have.
//* [IN] LPTSTR FileName
//* The buffer where the resulting file name (including path) will be
//* placed, must be MAX_PATH.
//* [IN] DWORD FileNameSize
//* The size of the file name buffer.
//* RETURN VALUE:
//* If successful the function returns A DWORDLONG with the unique id for the file.
//* On failure it returns 0.
//* REMARKS:
//* The generated unique id the 64 bit value of the system time.
//* The generated file name is a string containing the hex representation of
//* the 64 bit system time value.
//*********************************************************************************
DWORDLONG
GenerateUniqueFileName(
LPTSTR Directory,
LPTSTR Extension,
LPTSTR FileName,
DWORD FileNameSize
)
{
return GenerateUniqueFileNameWithPrefix (FALSE, Directory, NULL, Extension, FileName, FileNameSize);
} // GenerateUniqueFileName
BOOL
MapFileOpen(
LPCTSTR FileName,
BOOL ReadOnly,
DWORD ExtendBytes,
PFILE_MAPPING FileMapping
)
{
FileMapping->hFile = NULL;
FileMapping->hMap = NULL;
FileMapping->fPtr = NULL;
FileMapping->hFile = SafeCreateFile(
FileName,
ReadOnly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
ReadOnly ? FILE_SHARE_READ : 0,
NULL,
OPEN_EXISTING,
0,
NULL);
if (FileMapping->hFile == INVALID_HANDLE_VALUE)
{
return FALSE;
}
FileMapping->fSize = GetFileSize( FileMapping->hFile, NULL );
FileMapping->hMap = CreateFileMapping(
FileMapping->hFile,
NULL,
ReadOnly ? PAGE_READONLY : PAGE_READWRITE,
0,
FileMapping->fSize + ExtendBytes,
NULL
);
if (FileMapping->hMap == NULL)
{
CloseHandle( FileMapping->hFile );
return FALSE;
}
FileMapping->fPtr = (LPBYTE)MapViewOfFileEx(
FileMapping->hMap,
ReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE,
0,
0,
0,
NULL
);
if (FileMapping->fPtr == NULL)
{
CloseHandle( FileMapping->hFile );
CloseHandle( FileMapping->hMap );
return FALSE;
}
return TRUE;
}
VOID
MapFileClose(
PFILE_MAPPING FileMapping,
DWORD TrimOffset
)
{
UnmapViewOfFile( FileMapping->fPtr );
CloseHandle( FileMapping->hMap );
if (TrimOffset) {
SetFilePointer( FileMapping->hFile, TrimOffset, NULL, FILE_BEGIN );
SetEndOfFile( FileMapping->hFile );
}
CloseHandle( FileMapping->hFile );
}
//
// Function: MultiFileCopy
// Description: Copies multiple files from one directory to another.
// In case of failure, return FALSE without any clean-up.
// Validate that the path names and file names are not sum to be larger than MAX_PATH
// Args:
//
// dwNumberOfFiles : Number of file names to copy
// fileList : Array of strings: file names
// lpctstrSrcDirectory : Source directory (with or without '\' at the end
// lpctstrDestDirectory: Destination directory (with or without '\' at the end
//
// Author: AsafS
BOOL
MultiFileCopy(
DWORD dwNumberOfFiles,
LPCTSTR* fileList,
LPCTSTR lpctstrSrcDirectory,
LPCTSTR lpctstrDestDirerctory
)
{
DEBUG_FUNCTION_NAME(TEXT("MultiFileCopy"))
TCHAR szSrcPath [MAX_PATH];
TCHAR szDestPath[MAX_PATH];
HRESULT hRes;
DWORD dwLengthOfDestDirectory = _tcslen(lpctstrDestDirerctory);
DWORD dwLengthOfSrcDirectory = _tcslen(lpctstrSrcDirectory);
// Make sure that all the file name lengths are not too big
DWORD dwMaxPathLen = 1 + max((dwLengthOfDestDirectory),(dwLengthOfSrcDirectory));
DWORD dwBufferLen = (sizeof(szSrcPath)/sizeof(TCHAR)) - 1;
DWORD i=0;
Assert (dwNumberOfFiles);
for (i=0 ; i < dwNumberOfFiles ; i++)
{
if ( (_tcslen(fileList[i]) + dwMaxPathLen) > dwBufferLen )
{
DebugPrintEx(
DEBUG_ERR,
TEXT("The file/path names are too long")
);
SetLastError( ERROR_BUFFER_OVERFLOW );
return (FALSE);
}
}
hRes = StringCchCopy( szSrcPath,
ARR_SIZE(szSrcPath),
lpctstrSrcDirectory);
if (FAILED(hRes))
{
DebugPrintEx(DEBUG_ERR,
TEXT("StringCchCopy failed (ec=%lu)"),
HRESULT_CODE(hRes));
SetLastError( HRESULT_CODE(hRes) );
return (FALSE);
}
hRes = StringCchCopy( szDestPath,
ARR_SIZE(szDestPath),
lpctstrDestDirerctory);
if (FAILED(hRes))
{
DebugPrintEx(DEBUG_ERR,
TEXT("StringCchCopy failed (ec=%lu)"),
HRESULT_CODE(hRes));
SetLastError( HRESULT_CODE(hRes) );
return (FALSE);
}
//
// Verify that directories end with '\\'.
//
TCHAR* pLast = NULL;
pLast = _tcsrchr(szSrcPath,TEXT('\\'));
if( !( pLast && (*_tcsinc(pLast)) == '\0' ) )
{
// the last character is not a backslash, add one...
hRes = StringCchCat(szSrcPath, ARR_SIZE(szSrcPath), TEXT("\\"));
if (FAILED(hRes))
{
DebugPrintEx(DEBUG_ERR,
TEXT("StringCchCat failed (ec=%lu)"),
HRESULT_CODE(hRes));
SetLastError( HRESULT_CODE(hRes) );
return (FALSE);
}
}
pLast = _tcsrchr(szDestPath,TEXT('\\'));
if( !( pLast && (*_tcsinc(pLast)) == '\0' ) )
{
// the last character is not a backslash, add one...
hRes = StringCchCat(szDestPath, ARR_SIZE(szDestPath), TEXT("\\"));
if (FAILED(hRes))
{
DebugPrintEx(DEBUG_ERR,
TEXT("StringCchCat failed (ec=%lu)"),
HRESULT_CODE(hRes));
SetLastError( HRESULT_CODE(hRes) );
return (FALSE);
}
}
// Do the copy now
for (i=0 ; i < dwNumberOfFiles ; i++)
{
TCHAR szSrcFile[MAX_PATH];
TCHAR szDestFile[MAX_PATH];
hRes = StringCchPrintf(
szSrcFile,
ARR_SIZE(szSrcFile),
TEXT("%s%s"),
szSrcPath,
fileList[i]
);
if (FAILED(hRes))
{
DebugPrintEx(DEBUG_ERR,
TEXT("StringCchPrintf failed (ec=%lu)"),
HRESULT_CODE(hRes));
SetLastError(HRESULT_CODE(hRes));
return FALSE;
}
hRes = StringCchPrintf(
szDestFile,
ARR_SIZE(szDestFile),
TEXT("%s%s"),
szDestPath,
fileList[i]
);
if (FAILED(hRes))
{
DebugPrintEx(DEBUG_ERR,
TEXT("StringCchPrintf failed (ec=%lu)"),
HRESULT_CODE(hRes));
SetLastError(HRESULT_CODE(hRes));
return FALSE;
}
if (!CopyFile(szSrcFile, szDestFile, FALSE))
{
DebugPrintEx(
DEBUG_ERR,
TEXT("CopyFile(%s, %s) failed: %d."),
szSrcFile,
szDestFile,
GetLastError()
);
return(FALSE);
}
DebugPrintEx(
DEBUG_MSG,
TEXT("CopyFile(%s, %s) succeeded."),
szSrcFile,
szDestFile
);
}
return TRUE;
}
//
// Function: MultiFileDelete
// Description: Deletes multiple files from given directory.
// In case of failure, continue with the rest of the files and returns FALSE. Call to
// GetLastError() to get the reason for the last failure that occured
// If all DeleteFile calls were successful - return TRUE
// Validate that the path name and file names are not sum to be larger than MAX_PATH
// Args:
//
// dwNumberOfFiles : Number of file names to copy
// fileList : Array of strings: file names
// lpctstrFilesDirectory : Directory of the files (with or without '\' at the end
//
// Author: AsafS
BOOL
MultiFileDelete(
DWORD dwNumberOfFiles,
LPCTSTR* fileList,
LPCTSTR lpctstrFilesDirectory
)
{
DEBUG_FUNCTION_NAME(TEXT("MultiFileDelete"))
BOOL retVal = TRUE;
DWORD dwLastError = 0;
TCHAR szFullPath[MAX_PATH];
HRESULT hRes;
DWORD dwLengthOfDirectoryName = _tcslen(lpctstrFilesDirectory);
// Make sure that all the file name lengths are not too big
DWORD dwBufferLen = (sizeof(szFullPath)/sizeof(TCHAR)) - 1;
DWORD i;
Assert (dwNumberOfFiles);
for (i=0 ; i < dwNumberOfFiles ; i++)
{
if ( (_tcslen(fileList[i]) + dwLengthOfDirectoryName + 1) > dwBufferLen )
{
DebugPrintEx(
DEBUG_ERR,
TEXT("The file/path names are too long")
);
SetLastError( ERROR_BUFFER_OVERFLOW );
return (FALSE);
}
}
hRes = StringCchCopy(szFullPath ,ARR_SIZE(szFullPath), lpctstrFilesDirectory);
if (FAILED(hRes))
{
DebugPrintEx(DEBUG_ERR,
TEXT("StringCchCopy failed (ec=%lu)"),
HRESULT_CODE(hRes));
SetLastError( HRESULT_CODE(hRes) );
return (FALSE);
}
dwLengthOfDirectoryName = _tcslen(lpctstrFilesDirectory);
//
// Verify that directory end with '\\' to the end of the path.
//
TCHAR* pLast = NULL;
pLast = _tcsrchr(szFullPath,TEXT('\\'));
if( !( pLast && (*_tcsinc(pLast)) == '\0' ) )
{
// the last character is not a backslash, add one...
hRes = StringCchCat(szFullPath, ARR_SIZE(szFullPath), TEXT("\\"));
if (FAILED(hRes))
{
DebugPrintEx(DEBUG_ERR,
TEXT("StringCchCat failed (ec=%lu)"),
HRESULT_CODE(hRes));
SetLastError( HRESULT_CODE(hRes) );
return (FALSE);
}
}
for(i=0 ; i < dwNumberOfFiles ; i++)
{
TCHAR szFileName[MAX_PATH];
hRes = StringCchPrintf(
szFileName,
ARR_SIZE(szFileName),
TEXT("%s%s"),
szFullPath,
fileList[i]
);
if (FAILED(hRes))
{
DebugPrintEx(DEBUG_ERR,
TEXT("StringCchPrintf failed (ec=%lu)"),
HRESULT_CODE(hRes));
SetLastError(HRESULT_CODE(hRes));
return FALSE;
}
if (!DeleteFile(szFileName))
{
dwLastError = GetLastError();
DebugPrintEx(
DEBUG_ERR,
TEXT("Delete (%s) failed: %d."),
szFileName,
dwLastError
);
retVal = FALSE; // Continue with the list
}
else
{
DebugPrintEx(
DEBUG_MSG,
TEXT("Delete (%s) succeeded."),
szFileName
);
}
}
if (!retVal) // In case there was a failure to delete any file
{
SetLastError(dwLastError);
DebugPrintEx(
DEBUG_ERR,
TEXT("Delete files from (%s) failed: %d."),
szFullPath,
dwLastError
);
}
return retVal;
}
BOOL
ValidateCoverpage(
IN LPCTSTR CoverPageName,
IN LPCTSTR ServerName,
IN BOOL ServerCoverpage,
OUT LPTSTR ResolvedName,
IN DWORD dwResolvedNameSize
)
/*++
Routine Description:
This routine tries to validate that that coverpage specified by the user actually exists where
they say it does, and that it is indeed a coverpage (or a resolvable link to one)
Please see the SDK for documentation on the rules for how server coverpages work, etc.
Arguments:
CoverpageName - contains name of coverpage
ServerName - name of the server, if any (can be null)
ServerCoverpage - indicates if this coverpage is on the server, or in the server location for
coverpages locally
ResolvedName - a pointer to buffer (should be MAX_PATH large at least) to receive the
resolved coverpage name.
dwResolvedNameSize - holds the size of ResolvedName buffer in TCAHRs
Return Value:
TRUE if coverpage can be used.
FALSE if the coverpage is invalid or cannot be used.
--*/
{
LPTSTR p;
DWORD ec = ERROR_SUCCESS;
TCHAR CpDir [MAX_PATH];
TCHAR tszExt[_MAX_EXT];
TCHAR tszFileName[_MAX_FNAME];
HRESULT hRes;
DEBUG_FUNCTION_NAME(TEXT("ValidateCoverpage"));
Assert (ResolvedName);
if (!CoverPageName)
{
ec = ERROR_INVALID_PARAMETER;
goto exit;
}
hRes = StringCchCopy(CpDir, ARR_SIZE(CpDir), CoverPageName);
if (FAILED(hRes))
{
DebugPrintEx(DEBUG_ERR,
TEXT("StringCchCopy failed (ec=%lu)"),
HRESULT_CODE(hRes));
ec = HRESULT_CODE(hRes);
goto exit;
}
if (TRUE == ServerCoverpage)
{
//
// If this is a server cover page, make sure we only have the file name
//
TCHAR tszFullFileName[MAX_PATH];
_tsplitpath(CpDir, NULL, NULL, tszFileName, tszExt);
hRes = StringCchCopy(tszFullFileName, ARR_SIZE(tszFullFileName), tszFileName);
if (FAILED(hRes))
{
//
// Can not happen. CpDir is MAX_PATH
//
Assert (FALSE);
}
hRes = StringCchCat(tszFullFileName, ARR_SIZE(tszFullFileName), tszExt);
if (FAILED(hRes))
{
//
// Can not happen. CpDir is MAX_PATH
//
Assert (FALSE);
}
if (0 != _tcsicmp(tszFullFileName, CpDir))
{
DebugPrintEx(
DEBUG_ERR,
TEXT("server coverpage does not contain file name only. cover page name: %s "),
CpDir);
ec = ERROR_INVALID_PARAMETER;
goto exit;
}
if (0 == _tcsicmp(tszExt, CP_SHORTCUT_EXT) )
{
DebugPrintEx(DEBUG_ERR,
_T("Server Based Cover Page File Name should not be a link : %s"),
CpDir);
ec = ERROR_INVALID_PARAMETER;
goto exit;
}
}
p = _tcschr(CpDir, FAX_PATH_SEPARATOR_CHR );
if (p)
{
//
// the coverpage file name contains a path so just use it.
//
if (GetFileAttributes( CpDir ) == 0xffffffff)
{
ec = ERROR_FILE_NOT_FOUND;
DebugPrintEx(DEBUG_ERR,
_T("GetFileAttributes failed for %ws. ec = %ld"),
CpDir,
ec);
goto exit;
}
}
else
{
//
// the coverpage file name does not contain
// a path so we must construct a full path name
//
if (ServerCoverpage)
{
if (!ServerName || ServerName[0] == 0)
{
if (!GetServerCpDir( NULL, CpDir, sizeof(CpDir) / sizeof(CpDir[0]) ))
{
ec = GetLastError ();
DebugPrintEx(DEBUG_ERR,
_T("GetServerCpDir failed . ec = %ld"),
GetLastError());
}
}
else
{
if (!GetServerCpDir( ServerName, CpDir, sizeof(CpDir) / sizeof(CpDir[0]) ))
{
ec = GetLastError ();
DebugPrintEx(DEBUG_ERR,
_T("GetServerCpDir failed . ec = %ld"),
GetLastError());
}
}
}
else
{
if (!GetClientCpDir( CpDir, sizeof(CpDir) / sizeof(CpDir[0])))
{
ec = GetLastError ();
DebugPrintEx(DEBUG_ERR,
_T("GetClientCpDir failed . ec = %ld"),
GetLastError());
}
}
if (ERROR_SUCCESS != ec)
{
ec = ERROR_FILE_NOT_FOUND;
goto exit;
}
hRes = StringCchCat( CpDir, ARR_SIZE(CpDir), TEXT("\\") );
if (FAILED(hRes))
{
DebugPrintEx(DEBUG_ERR,
TEXT("StringCchCat failed (ec=%lu)"),
HRESULT_CODE(hRes));
ec = HRESULT_CODE(hRes);
goto exit;
}
hRes = StringCchCat( CpDir, ARR_SIZE(CpDir), CoverPageName );
if (FAILED(hRes))
{
DebugPrintEx(DEBUG_ERR,
TEXT("StringCchCat failed (ec=%lu)"),
HRESULT_CODE(hRes));
ec = HRESULT_CODE(hRes);
goto exit;
}
_tsplitpath(CpDir, NULL, NULL, NULL, tszExt);
if (!_tcslen(tszExt))
{
hRes = StringCchCat( CpDir, ARR_SIZE(CpDir), FAX_COVER_PAGE_FILENAME_EXT );
if (FAILED(hRes))
{
DebugPrintEx(DEBUG_ERR,
TEXT("StringCchCat failed (ec=%lu)"),
HRESULT_CODE(hRes));
ec = HRESULT_CODE(hRes);
goto exit;
}
}
if (GetFileAttributes( CpDir ) == 0xffffffff)
{
ec = ERROR_FILE_NOT_FOUND;
goto exit;
}
}
hRes = StringCchCopy( ResolvedName, dwResolvedNameSize, CpDir );
if (FAILED(hRes))
{
DebugPrintEx(DEBUG_ERR,
TEXT("StringCchCopy failed (ec=%lu)"),
HRESULT_CODE(hRes));
ec = HRESULT_CODE(hRes);
goto exit;
}
//
// Make sure it is not a device
// Try to open file
//
HANDLE hFile = SafeCreateFile (
ResolvedName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if ( INVALID_HANDLE_VALUE == hFile )
{
ec = GetLastError ();
DebugPrintEx(
DEBUG_ERR,
TEXT("Opening %s for read failed (ec: %ld)"),
ResolvedName,
ec);
goto exit;
}
if (!CloseHandle (hFile))
{
DebugPrintEx(
DEBUG_ERR,
TEXT("CloseHandle failed (ec: %ld)"),
GetLastError());
}
Assert (ERROR_SUCCESS == ec);
exit:
if (ERROR_SUCCESS != ec)
{
SetLastError(ec);
return FALSE;
}
return TRUE;
} // ValidateCoverpage
DWORD
ViewFile (
LPCTSTR lpctstrFile
)
/*++
Routine Description:
Launches the application associated with a given file to view it.
We first attempt to use the "open" verb.
If that fails, we try the NULL (default) verb.
Arguments:
lpctstrFile [in] - File name
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
SHELLEXECUTEINFO executeInfo = {0};
DEBUG_FUNCTION_NAME(TEXT("ViewFile"));
executeInfo.cbSize = sizeof(executeInfo);
executeInfo.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_FLAG_DDEWAIT;
executeInfo.lpVerb = TEXT("open");
executeInfo.lpFile = lpctstrFile;
executeInfo.nShow = SW_SHOWNORMAL;
//
// Execute the associated application with the "open" verb
//
if(!ShellExecuteEx(&executeInfo))
{
DebugPrintEx(
DEBUG_ERR,
TEXT("ShellExecuteEx(open) failed (ec: %ld)"),
GetLastError());
//
// "open" verb is not supported. Try the NULL (default) verb.
//
executeInfo.lpVerb = NULL;
if(!ShellExecuteEx(&executeInfo))
{
dwRes = GetLastError();
DebugPrintEx(
DEBUG_ERR,
TEXT("ShellExecuteEx(NULL) failed (ec: %ld)"),
dwRes);
}
}
return dwRes;
} // ViewFile
#ifdef UNICODE
DWORD
CheckToSeeIfSameDir(
LPWSTR lpwstrDir1,
LPWSTR lpwstrDir2,
BOOL* pIsSameDir
)
{
/*++
Routine name : IsDiffrentDir
Routine description:
Checks if both paths point to the same directory. Note that the directory pointed by lpwstrDir1 must exist.
Author:
Oded Sacher (OdedS), Aug, 2000
Arguments:
lpwstrDir1 [in] - First path - the directory must exist.
lpwstrDir2 [in] - Second path - the directory does not have to exist
pIsSameDir [out] - Receives the answer to "IsSameDir?" Valid only if the function succeeds.
Return Value:
Win32 Erorr code
--*/
Assert (lpwstrDir1 && lpwstrDir2 && pIsSameDir);
DWORD ec = ERROR_SUCCESS;
WCHAR wszTestFile1[MAX_PATH];
WCHAR wszTestFile2[MAX_PATH * 2];
BOOL fFileCreated = FALSE;
HANDLE hFile1 = INVALID_HANDLE_VALUE;
HANDLE hFile2 = INVALID_HANDLE_VALUE;
LPWSTR lpwstrFileName = NULL;
DEBUG_FUNCTION_NAME(TEXT("CheckToSeeIfSameDir)"));
HRESULT hRes;
if (0 == _wcsicmp(lpwstrDir1, lpwstrDir2))
{
*pIsSameDir = TRUE;
return ERROR_SUCCESS;
}
//
// Create temporary files
//
if (!GetTempFileName (lpwstrDir1, L"TST", 0, wszTestFile1))
{
//
// Either the folder doesn't exist or we don't have access
//
ec = GetLastError ();
DebugPrintEx(
DEBUG_ERR,
TEXT("GetTempFileName failed with %ld"), ec);
goto exit;
}
//
// GetTempFileName created 0 bytes file, that we need to delete before exiting
//
fFileCreated = TRUE;
hFile1 = SafeCreateFile(
wszTestFile1,
0,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if (INVALID_HANDLE_VALUE == hFile1)
{
ec = GetLastError();
DebugPrintEx(DEBUG_ERR,
TEXT("CreateFile failed (ec: %ld)"),
ec);
goto exit;
}
lpwstrFileName = wcsrchr(wszTestFile1, L'\\');
Assert (lpwstrFileName);
hRes = StringCchCopy (wszTestFile2, ARR_SIZE(wszTestFile2), lpwstrDir2);
if (FAILED(hRes))
{
DebugPrintEx(DEBUG_ERR,
TEXT("StringCchCopy failed (ec=%lu)"),
HRESULT_CODE(hRes));
ec = HRESULT_CODE(hRes);
goto exit;
}
hRes = StringCchCat (wszTestFile2, ARR_SIZE(wszTestFile2), lpwstrFileName);
if (FAILED(hRes))
{
DebugPrintEx(DEBUG_ERR,
TEXT("StringCchCat failed (ec=%lu)"),
HRESULT_CODE(hRes));
ec = HRESULT_CODE(hRes);
goto exit;
}
hFile2 = SafeCreateFile(
wszTestFile2,
0,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if (INVALID_HANDLE_VALUE == hFile2)
{
//
// Check if failure is *NOT* because of access or availability
//
ec = GetLastError ();
if (ERROR_NOT_ENOUGH_MEMORY == ec ||
ERROR_OUTOFMEMORY == ec )
{
DebugPrintEx(DEBUG_ERR,
TEXT("CreateFile failed (ec: %ld)"),
ec);
goto exit;
}
//
// On any other failure we asssume that the paths are diffrent
//
*pIsSameDir = FALSE;
ec = ERROR_SUCCESS;
goto exit;
}
BY_HANDLE_FILE_INFORMATION hfi1;
BY_HANDLE_FILE_INFORMATION hfi2;
if (!GetFileInformationByHandle(hFile1, &hfi1))
{
ec = GetLastError();
DebugPrintEx(DEBUG_ERR,
TEXT("GetFileInformationByHandle failed (ec: %ld)"),
ec);
goto exit;
}
if (!GetFileInformationByHandle(hFile2, &hfi2))
{
ec = GetLastError();
DebugPrintEx(DEBUG_ERR,
TEXT("GetFileInformationByHandle failed (ec: %ld)"),
ec);
goto exit;
}
if ((hfi1.nFileIndexHigh == hfi2.nFileIndexHigh) &&
(hfi1.nFileIndexLow == hfi2.nFileIndexLow) &&
(hfi1.dwVolumeSerialNumber == hfi2.dwVolumeSerialNumber))
{
*pIsSameDir = TRUE;
}
else
{
*pIsSameDir = FALSE;
}
Assert (ERROR_SUCCESS == ec);
exit:
if (INVALID_HANDLE_VALUE != hFile1)
{
if (!CloseHandle(hFile1))
{
DebugPrintEx(DEBUG_ERR,
TEXT("CloseHandle failed (ec: %ld)"),
GetLastError());
}
}
if (INVALID_HANDLE_VALUE != hFile2)
{
if (!CloseHandle(hFile2))
{
DebugPrintEx(DEBUG_ERR,
TEXT("CloseHandle failed (ec: %ld)"),
GetLastError());
}
}
if (TRUE == fFileCreated)
{
if (!DeleteFile(wszTestFile1))
{
DebugPrintEx(DEBUG_ERR,
TEXT("DeleteFile failed. File: %s, (ec: %ld)"),
wszTestFile1,
GetLastError());
}
}
return ec;
}
#endif //UNICODE
typedef enum
{
SAFE_METAFILE_SEMANTICS_NONE = 0x00000000,
SAFE_METAFILE_SEMANTICS_TEMP = 0x00000001, // File is temporary. Should be deleted on close / reboot
SAFE_METAFILE_SEMANTICS_SENSITIVE = 0x00000002 // File contains sensitive information. Should not be indexed
} SAFE_METAFILE_SEMANTICS;
static
HANDLE
InternalSafeCreateFile(
LPCTSTR IN lpFileName, // File name
DWORD IN dwDesiredAccess, // Access mode
DWORD IN dwShareMode, // Share mode
LPSECURITY_ATTRIBUTES IN lpSecurityAttributes, // SD
DWORD IN dwCreationDisposition, // How to create
DWORD IN dwFlagsAndAttributes, // File attributes
HANDLE IN hTemplateFile, // Handle to template file
DWORD IN dwMetaFileSemantics // Meta file semantics
)
/*++
Routine name : InternalSafeCreateFile
Routine description:
This is a safe wrapper around the Win32 CreateFile API.
It only supports creating real files (as opposed to COM ports, named pipes, etc.).
It uses some widely-discussed mitigation techniques to guard agaist some well known security
issues in CreateFile().
Author:
Eran Yariv (EranY), Mar, 2002
Arguments:
lpFileName [in] - Refer to the CreateFile() documentation for parameter description.
dwDesiredAccess [in] - Refer to the CreateFile() documentation for parameter description.
dwShareMode [in] - Refer to the CreateFile() documentation for parameter description.
lpSecurityAttributes [in] - Refer to the CreateFile() documentation for parameter description.
dwCreationDisposition [in] - Refer to the CreateFile() documentation for parameter description.
dwFlagsAndAttributes [in] - Refer to the CreateFile() documentation for parameter description.
hTemplateFile [in] - Refer to the CreateFile() documentation for parameter description.
dwMetaFileSemantics [in] - Meta file semantics.
This parameter can be a combination of the following values:
SAFE_METAFILE_SEMANTICS_TEMP
The file is a temporary file.
The file will be created / opened using the FILE_FLAG_DELETE_ON_CLOSE flag.
When the last file handle is closed, the file will be automatically deleted.
In addition, the file is marked for deletion after reboot (Unicode-version only).
This will only work if the calling thread's user is a member of the local admins group.
If marking for deletion-post-reboot fails, the InternalSafeCreateFile function call still succeeds.
SAFE_METAFILE_SEMANTICS_SENSITIVE
The file contains sensitive information.
The current implementation of this function will mark the file with the
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED flag.
Return Value:
If the function succeeds, the return value is an open handle to the specified file.
If the specified file exists before the function call and dwCreationDisposition is CREATE_ALWAYS or OPEN_ALWAYS,
a call to GetLastError returns ERROR_ALREADY_EXISTS (even though the function has succeeded).
If the file does not exist before the call, GetLastError returns zero.
If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error information, call GetLastError.
For more information see the "Return value" section in the CreateFile() documentation.
Remarks:
Please refer to the CreateFile() documentation.
--*/
{
HANDLE hFile;
DWORD dwFaxFlagsAndAttributes = SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS;
DWORD dwFaxShareMode = 0;
DEBUG_FUNCTION_NAME(TEXT("InternalSafeCreateFile"));
//
// Always use SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS in file flags and attributes.
// This prevents us from opening a user-supplied named pipe and allowing the other side
// of that pipe to impersonate the caller.
//
if (SAFE_METAFILE_SEMANTICS_SENSITIVE & dwMetaFileSemantics)
{
//
// File contains sensitive data. It should not be indexed.
//
dwFaxFlagsAndAttributes |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
}
if (SAFE_METAFILE_SEMANTICS_TEMP & dwMetaFileSemantics)
{
//
// File is temporary.
//
dwFaxFlagsAndAttributes |= FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE;
#ifdef UNICODE
dwFaxShareMode = FILE_SHARE_DELETE;
#endif // UNICODE
}
hFile = CreateFile (lpFileName,
dwDesiredAccess,
dwShareMode | dwFaxShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes | dwFaxFlagsAndAttributes,
hTemplateFile);
if (INVALID_HANDLE_VALUE == hFile)
{
return hFile;
}
//
// Never allow using non-disk file (e.g. COM ports)
//
if (FILE_TYPE_DISK != GetFileType (hFile))
{
CloseHandle (hFile);
SetLastError (ERROR_UNSUPPORTED_TYPE);
return INVALID_HANDLE_VALUE;
}
#ifdef UNICODE
if (SAFE_METAFILE_SEMANTICS_TEMP & dwMetaFileSemantics)
{
//
// File is temporary.
// Mark it for delete after reboot.
// This can fail if we're not admins. That's why we're not checking return value from MoveFileEx.
//
MoveFileEx (lpFileName, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
}
#endif // UNICODE
return hFile;
} // InternalSafeCreateFile
HANDLE
SafeCreateFile(
LPCTSTR IN lpFileName, // File name
DWORD IN dwDesiredAccess, // Access mode
DWORD IN dwShareMode, // Share mode
LPSECURITY_ATTRIBUTES IN lpSecurityAttributes, // SD
DWORD IN dwCreationDisposition, // How to create
DWORD IN dwFlagsAndAttributes, // File attributes
HANDLE IN hTemplateFile // Handle to template file
)
{
return InternalSafeCreateFile (lpFileName,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile,
SAFE_METAFILE_SEMANTICS_SENSITIVE);
} // SafeCreateFile
HANDLE
SafeCreateTempFile(
LPCTSTR IN lpFileName, // File name
DWORD IN dwDesiredAccess, // Access mode
DWORD IN dwShareMode, // Share mode
LPSECURITY_ATTRIBUTES IN lpSecurityAttributes, // SD
DWORD IN dwCreationDisposition, // How to create
DWORD IN dwFlagsAndAttributes, // File attributes
HANDLE IN hTemplateFile // Handle to template file
)
{
return InternalSafeCreateFile (lpFileName,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile,
SAFE_METAFILE_SEMANTICS_SENSITIVE |
SAFE_METAFILE_SEMANTICS_TEMP);
} // SafeCreateTempFile
DWORD
IsValidFaxFolder(
LPCTSTR szFolder
)
/*++
Routine name : IsValidFaxFolder
Routine description:
Check if fax service has access right to a given folder.
The routine checks for these rights:
o Create file/Write file
o Enumerate files
o Delete file
Author:
Caliv Nir (t-nicali) Mar, 2002
Arguments:
lpwstrFolder [in] - the folder name.
Return Value:
Win32 error code. ERROR_SUCCESS if the folder can be used by fax service.
Otherwise, the Win32 error code to return to the caller.
--*/
{
TCHAR szTestFile[MAX_PATH]={0};
DWORD dwFileAtt;
LPTSTR szExpandedFolder = NULL;
HANDLE hFind = INVALID_HANDLE_VALUE;
WIN32_FIND_DATA FindFileData = {0};
BOOL bFileCreated = FALSE;
DWORD ec = ERROR_SUCCESS;
DEBUG_FUNCTION_NAME(TEXT("IsValidFaxFolder"));
szExpandedFolder = ExpandEnvironmentString( szFolder );
if (!szExpandedFolder)
{
ec = GetLastError();
DebugPrintEx( DEBUG_ERR,
TEXT("ExpandEnvironmentString failed (ec=%lu)."),
ec);
return ec;
}
//
// Check to see if the directory exist
//
dwFileAtt = GetFileAttributes( szExpandedFolder );
if (INVALID_FILE_ATTRIBUTES == dwFileAtt || !(dwFileAtt & FILE_ATTRIBUTE_DIRECTORY))
{
//
// The directory does not exists
//
ec = GetLastError ();
DebugPrintEx(
DEBUG_ERR,
TEXT("GetFileAttributes failed with %lu"), ec);
goto exit;
}
//
// Verify that we have access to this folder - Create a temporary file
//
if (!GetTempFileName (szExpandedFolder, TEXT("TST"), 0, szTestFile))
{
//
// Either the folder doesn't exist or we don't have access
//
ec = GetLastError ();
DebugPrintEx(
DEBUG_ERR,
TEXT("GetTempFileName failed with %ld"), ec);
goto exit;
}
bFileCreated = TRUE;
//
// Try to enumarate files in this folder
//
hFind = FindFirstFile(szTestFile, &FindFileData);
if (hFind == INVALID_HANDLE_VALUE)
{
//
// Couldn't enumerate folder
//
ec = GetLastError ();
DebugPrintEx(
DEBUG_ERR,
TEXT("FindFirstFile failed with %ld"), ec);
goto exit;
}
Assert(ec == ERROR_SUCCESS);
exit:
//
// Close find handle
//
if (hFind != INVALID_HANDLE_VALUE)
{
if(!FindClose(hFind))
{
DebugPrintEx(
DEBUG_ERR,
TEXT("FindClose failed with %ld"), GetLastError ());
}
}
if (bFileCreated)
{
//
// Delete the file
//
if (!DeleteFile(szTestFile))
{
/***********************************************************
/* Although it's a clean up code we propagate the error code
/* It may say that we lack the permission to delete this
/* file.
/***********************************************************/
ec = GetLastError ();
DebugPrintEx(
DEBUG_ERR,
TEXT("DeleteFile() failed with %ld"),ec);
}
}
MemFree(szExpandedFolder);
return ec;
} // IsValidFaxFolder