|
|
/*++
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
|