|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
util.c
Abstract:
This module contains various utility functions.
Author:
Wesley Witt (wesw) 16-Jan-1996
Revision History:
--*/
#include "faxsvc.h"
#pragma hdrstop
#if DBG
extern HANDLE hLogFile; extern LIST_ENTRY CritSecListHead; #endif
typedef struct _STRING_TABLE { DWORD ResourceId; DWORD InternalId; LPTSTR String; } STRING_TABLE, *PSTRING_TABLE;
static STRING_TABLE StringTable[] = { { IDS_DIALING, FPS_DIALING, NULL }, { IDS_SENDING, FPS_SENDING, NULL }, { IDS_RECEIVING, FPS_RECEIVING, NULL }, { IDS_COMPLETED, FPS_COMPLETED, NULL }, { IDS_HANDLED, FPS_HANDLED, NULL }, { IDS_BUSY, FPS_BUSY, NULL }, { IDS_NO_ANSWER, FPS_NO_ANSWER, NULL }, { IDS_BAD_ADDRESS, FPS_BAD_ADDRESS, NULL }, { IDS_NO_DIAL_TONE, FPS_NO_DIAL_TONE, NULL }, { IDS_DISCONNECTED, FPS_DISCONNECTED, NULL }, { IDS_FATAL_ERROR, FPS_FATAL_ERROR, NULL }, { IDS_NOT_FAX_CALL, FPS_NOT_FAX_CALL, NULL }, { IDS_CALL_DELAYED, FPS_CALL_DELAYED, NULL }, { IDS_CALL_BLACKLISTED, FPS_CALL_BLACKLISTED, NULL }, { IDS_UNAVAILABLE, FPS_UNAVAILABLE, NULL }, { IDS_AVAILABLE, FPS_AVAILABLE, NULL }, { IDS_ABORTING, FPS_ABORTING, NULL }, { IDS_ROUTING, FPS_ROUTING, NULL }, { IDS_INITIALIZING, FPS_INITIALIZING, NULL }, { IDS_SENDFAILED, FPS_SENDFAILED, NULL }, { IDS_SENDRETRY, FPS_SENDRETRY, NULL }, { IDS_BLANKSTR, FPS_BLANKSTR, NULL }, { IDS_ROUTERETRY, FPS_ROUTERETRY, NULL }, { IDS_ANSWERED, FPS_ANSWERED, NULL }, { IDS_DR_SUBJECT, IDS_DR_SUBJECT, NULL }, { IDS_DR_FILENAME, IDS_DR_FILENAME, NULL }, { IDS_NDR_SUBJECT, IDS_NDR_SUBJECT, NULL }, { IDS_NDR_FILENAME, IDS_NDR_FILENAME, NULL }, { IDS_POWERED_OFF_MODEM, IDS_POWERED_OFF_MODEM, NULL }, { IDS_SERVICE_NAME, IDS_SERVICE_NAME, NULL }, { IDS_NO_MAPI_LOGON, IDS_NO_MAPI_LOGON, NULL }, { IDS_DEFAULT, IDS_DEFAULT, NULL }, { IDS_SERVER_NAME, IDS_SERVER_NAME, NULL }, { IDS_FAX_LOG_CATEGORY_INIT_TERM, IDS_FAX_LOG_CATEGORY_INIT_TERM, NULL }, { IDS_FAX_LOG_CATEGORY_OUTBOUND, IDS_FAX_LOG_CATEGORY_OUTBOUND, NULL }, { IDS_FAX_LOG_CATEGORY_INBOUND, IDS_FAX_LOG_CATEGORY_INBOUND, NULL }, { IDS_FAX_LOG_CATEGORY_UNKNOWN, IDS_FAX_LOG_CATEGORY_UNKNOWN, NULL }, { IDS_SET_CONFIG, IDS_SET_CONFIG, NULL }, { IDS_NO_SEND_DEVICES, IDS_NO_SEND_DEVICES, NULL}, { IDS_MODEM_PROVIDER_NAME, IDS_MODEM_PROVIDER_NAME, NULL}
};
#define CountStringTable (sizeof(StringTable)/sizeof(STRING_TABLE))
VOID InitializeStringTable( VOID ) { DWORD i; HINSTANCE hInstance; TCHAR Buffer[256];
hInstance = GetModuleHandle(NULL);
for (i=0; i<CountStringTable; i++) {
if (LoadString( hInstance, StringTable[i].ResourceId, Buffer, sizeof(Buffer)/sizeof(TCHAR) )) {
StringTable[i].String = (LPTSTR) MemAlloc( StringSize( Buffer ) ); if (!StringTable[i].String) { StringTable[i].String = TEXT(""); } else { _tcscpy( StringTable[i].String, Buffer ); }
} else {
StringTable[i].String = TEXT("");
} } }
VOID LogMessage( DWORD FormatId, ... )
/*++
Routine Description:
Prints a pre-formatted message to stdout.
Arguments:
FormatId - Resource id for a printf style format string ... - all other arguments
Return Value:
None.
--*/
{ TCHAR buf[1024]; DWORD Count; va_list args;
va_start( args, FormatId );
Count = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE, NULL, FormatId, 0, buf, sizeof(buf), &args );
va_end( args );
DebugPrint(( TEXT("%s"), buf )); }
LPTSTR GetLastErrorText( DWORD ErrorCode )
/*++
Routine Description:
Gets a string for a given WIN32 error code.
Arguments:
ErrorCode - WIN32 error code.
Return Value:
Pointer to a string representing the ErrorCode.
--*/
{ static TCHAR ErrorBuf[256]; DWORD Count;
Count = FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY, NULL, ErrorCode, LANG_NEUTRAL, ErrorBuf, sizeof(ErrorBuf), NULL );
if (Count) { if (ErrorBuf[Count-1] == TEXT('\n')) { ErrorBuf[Count-1] = 0; } if ((Count>1) && (ErrorBuf[Count-2] == TEXT('\r'))) { ErrorBuf[Count-2] = 0; } }
return ErrorBuf; }
LPTSTR GetString( DWORD InternalId )
/*++
Routine Description:
Loads a resource string and returns a pointer to the string. The caller must free the memory.
Arguments:
ResourceId - resource string id
Return Value:
pointer to the string
--*/
{ DWORD i;
for (i=0; i<CountStringTable; i++) { if (StringTable[i].InternalId == InternalId) { return StringTable[i].String; } }
return NULL; }
BOOL InitializeFaxDirectories( VOID ) /*++
Routine Description:
Initializes the directories that fax will use. We call into the shell to get the correct base path for fax directories and then tack on a relative path.
Arguments:
None.
Return Value:
TRUE if successful. modifies path globals
--*/ { if (!GetSpecialPath( CSIDL_COMMON_APPDATA, FaxDir ) ) { DebugPrint(( TEXT("Couldn't GetSpecialPath, ec = %d\n"), GetLastError() )); return FALSE; }
wcscpy(FaxReceiveDir,FaxDir); wcscpy(FaxQueueDir,FaxDir);
ConcatenatePaths(FaxDir, FAX_DIR); ConcatenatePaths(FaxReceiveDir, FAX_RECEIVE_DIR); ConcatenatePaths(FaxQueueDir, FAX_QUEUE_DIR);
//
// BugBug remove me
//
DebugPrint(( TEXT("FaxDir : %s\n"), FaxDir )); DebugPrint(( TEXT("FaxReceiveDir : %s\n"), FaxReceiveDir )); DebugPrint(( TEXT("FaxQueueDir : %s\n"), FaxQueueDir ));
return TRUE;
}
DWORDLONG GenerateUniqueFileName( LPTSTR Directory, LPTSTR Extension, LPTSTR FileName, DWORD FileNameSize ) { SYSTEMTIME SystemTime; FILETIME FileTime; DWORD i; WORD FatDate; WORD FatTime; TCHAR TempPath[MAX_PATH]; FileName[0] = '\0';
GetLocalTime( &SystemTime ); SystemTimeToFileTime( &SystemTime, &FileTime ); FileTimeToDosDateTime( &FileTime, &FatDate, &FatTime );
if (!Directory) { GetTempPath( sizeof(TempPath)/sizeof(TCHAR), TempPath ); Directory = TempPath; }
if (Directory[_tcslen(Directory)-1] == TEXT('\\')) { Directory[_tcslen(Directory)-1] = 0; }
if (!Extension) { Extension = TEXT("tif"); }
//
// directory + '\' + 10 character filename + '.' + extension + NULL
// terminator
//
if ((_tcslen(Directory)+1+10+1+_tcslen(Extension)+1) > FileNameSize) { SetLastError(ERROR_INSUFFICIENT_BUFFER); return 0; }
for (i=0; i<256; i++) {
HANDLE hFile = INVALID_HANDLE_VALUE;
_stprintf( FileName, TEXT("%s\\%04x%04x%02x.%s"), Directory, FatTime, FatDate, i, Extension );
hFile = CreateFile( FileName, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
if (hFile == INVALID_HANDLE_VALUE) {
DWORD Error = GetLastError();
if (Error == ERROR_ALREADY_EXISTS || Error == ERROR_FILE_EXISTS) {
continue;
} else {
return 0;
}
} else {
CloseHandle( hFile ); break;
} }
if (i == 256) { SetLastError( ERROR_TOO_MANY_OPEN_FILES ); return 0; }
return MAKELONGLONG( MAKELONG( FatDate, FatTime ), i ); }
DWORD MessageBoxThread( IN PMESSAGEBOX_DATA MsgBox ) { DWORD Answer = (DWORD) MessageBox( NULL, MsgBox->Text, GetString( IDS_SERVICE_NAME ), MsgBox->Type | MB_SERVICE_NOTIFICATION );
if (MsgBox->Response) { *MsgBox->Response = Answer; }
MemFree( MsgBox->Text ); MemFree( MsgBox );
return 0; }
BOOL ServiceMessageBox( IN LPCTSTR MsgString, IN DWORD Type, IN BOOL UseThread, IN LPDWORD Response, IN ... ) { #define BUFSIZE 1024
PMESSAGEBOX_DATA MsgBox; DWORD ThreadId; HANDLE hThread; DWORD Answer; LPTSTR buf; va_list arg_ptr;
buf = (LPTSTR) MemAlloc( BUFSIZE ); if (!buf) { return FALSE; }
va_start( arg_ptr, Response ); _vsntprintf( buf, BUFSIZE, MsgString, arg_ptr ); va_end( arg_ptr );
if (UseThread) {
MsgBox = MemAlloc( sizeof(MESSAGEBOX_DATA) ); if (!MsgBox) { MemFree( buf ); return FALSE; }
MsgBox->Text = buf; MsgBox->Response = Response; MsgBox->Type = Type;
hThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE) MessageBoxThread, (LPVOID) MsgBox, 0, &ThreadId );
if (!hThread) { MemFree( buf ); MemFree( MsgBox ); return FALSE; }
CloseHandle( hThread );
return TRUE; }
Answer = MessageBox( NULL, buf, GetString( IDS_SERVICE_NAME ), Type | MB_SERVICE_NOTIFICATION ); if (Response) { *Response = Answer; }
MemFree( buf );
return TRUE; }
BOOL CreateFaxEvent( DWORD DeviceId, DWORD EventId, DWORD JobId ) { PFAX_EVENT FaxEvent;
Assert(EventId != 0);
FaxEvent = MemAlloc( sizeof(FAX_EVENT) ); if (!FaxEvent) { return FALSE; }
FaxEvent->SizeOfStruct = sizeof(FAX_EVENT); GetSystemTimeAsFileTime( &FaxEvent->TimeStamp ); FaxEvent->EventId = EventId; FaxEvent->DeviceId = DeviceId; FaxEvent->JobId = JobId;
PostQueuedCompletionStatus( StatusCompletionPortHandle, sizeof(FAX_EVENT), EVENT_COMPLETION_KEY, (LPOVERLAPPED) FaxEvent );
return TRUE; }
DWORD MapStatusIdToEventId( DWORD StatusId ) { DWORD EventId = 0;
switch( StatusId ) { case FS_INITIALIZING: EventId = FEI_INITIALIZING; break; case FS_DIALING: EventId = FEI_DIALING; break; case FS_TRANSMITTING: EventId = FEI_SENDING; break; case FS_RECEIVING: EventId = FEI_RECEIVING; break; case FS_COMPLETED: EventId = FEI_COMPLETED; break; case FS_HANDLED: EventId = FEI_HANDLED; break; case FS_LINE_UNAVAILABLE: EventId = FEI_LINE_UNAVAILABLE; break; case FS_BUSY: EventId = FEI_BUSY; break; case FS_NO_ANSWER: EventId = FEI_NO_ANSWER; break; case FS_BAD_ADDRESS: EventId = FEI_BAD_ADDRESS; break; case FS_NO_DIAL_TONE: EventId = FEI_NO_DIAL_TONE; break; case FS_DISCONNECTED: EventId = FEI_DISCONNECTED; break; case FS_FATAL_ERROR: EventId = FEI_FATAL_ERROR; break; case FS_NOT_FAX_CALL: EventId = FEI_NOT_FAX_CALL; break; case FS_CALL_DELAYED: EventId = FEI_CALL_DELAYED; break; case FS_CALL_BLACKLISTED: EventId = FEI_CALL_BLACKLISTED; break; case FS_USER_ABORT: EventId = FEI_ABORTING; break; case FS_ANSWERED: EventId = FEI_ANSWERED; break; }
return EventId;
}
VOID FaxLogSend( PFAX_SEND_ITEM FaxSendItem, BOOL Rslt, PFAX_DEV_STATUS FaxStatus, BOOL Retrying ) /*++
Routine Description:
Log a fax send event.
Arguments:
FaxSendItem - Pointer to FAX_SEND_ITEM structure for this fax. Rslt - BOOL returned from device provider. TRUE means fax was sent. FaxStatus - Pointer to FAX_DEV_STATUS for this fax. PrinterName - Name of fax printer. Retrying - TRUE if another send attempt will be made.
Return Value:
VOID
--*/
{ DWORD Level; DWORD FormatId; TCHAR PageCountStr[64]; TCHAR TimeStr[128]; BOOL fLog = TRUE;
FormatElapsedTimeStr( (FILETIME*)&FaxSendItem->JobEntry->ElapsedTime, TimeStr, 128 ); _ltot((LONG) FaxStatus->PageCount, PageCountStr, 10); if (Rslt) { FaxLog( FAXLOG_CATEGORY_OUTBOUND, FAXLOG_LEVEL_MED, 10, MSG_FAX_SEND_SUCCESS, FaxSendItem->SenderName, FaxSendItem->BillingCode, FaxSendItem->SenderCompany, FaxSendItem->SenderDept, FaxSendItem->RecipientName, FaxSendItem->JobEntry->PhoneNumber, FaxStatus->CSI, PageCountStr, TimeStr, FaxSendItem->JobEntry->LineInfo->DeviceName ); } else { switch (FaxStatus->StatusId) { case FS_FATAL_ERROR: Level = Retrying ? FAXLOG_LEVEL_MED : FAXLOG_LEVEL_MIN; FormatId = Retrying ? MSG_FAX_SEND_FATAL_RETRY : MSG_FAX_SEND_FATAL_ABORT; break; case FS_NO_DIAL_TONE: Level = Retrying ? FAXLOG_LEVEL_MED : FAXLOG_LEVEL_MIN; FormatId = Retrying ? MSG_FAX_SEND_NDT_RETRY : MSG_FAX_SEND_NDT_ABORT; break; case FS_NO_ANSWER: Level = Retrying ? FAXLOG_LEVEL_MED : FAXLOG_LEVEL_MIN; FormatId = Retrying ? MSG_FAX_SEND_NA_RETRY : MSG_FAX_SEND_NA_ABORT; break; case FS_DISCONNECTED: Level = Retrying ? FAXLOG_LEVEL_MED : FAXLOG_LEVEL_MIN; FormatId = Retrying ? MSG_FAX_SEND_INTERRUPT_RETRY : MSG_FAX_SEND_INTERRUPT_ABORT; break; case FS_NOT_FAX_CALL: Level = Retrying ? FAXLOG_LEVEL_MED : FAXLOG_LEVEL_MIN; FormatId = Retrying ? MSG_FAX_SEND_NOTFAX_RETRY : MSG_FAX_SEND_NOTFAX_ABORT; break; case FS_BUSY: Level = Retrying ? FAXLOG_LEVEL_MAX : FAXLOG_LEVEL_MIN; FormatId = Retrying ? MSG_FAX_SEND_BUSY_RETRY : MSG_FAX_SEND_BUSY_ABORT; break; case FS_USER_ABORT: Level = FAXLOG_LEVEL_MED; FormatId = MSG_FAX_SEND_USER_ABORT; break; default: fLog = FALSE; }
if(fLog) { FaxLog( FAXLOG_CATEGORY_OUTBOUND, Level, 7, FormatId, FaxSendItem->SenderName, FaxSendItem->BillingCode, FaxSendItem->SenderCompany, FaxSendItem->SenderDept, FaxSendItem->RecipientName, FaxSendItem->JobEntry->PhoneNumber, FaxSendItem->JobEntry->LineInfo->DeviceName ); } } }
BOOL SetServiceStart( LPTSTR ServiceName, DWORD StartType ) { BOOL rVal = FALSE; SC_HANDLE hSvcMgr; SC_HANDLE hService;
hSvcMgr = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); if (!hSvcMgr) { DebugPrint(( TEXT("could not open service manager: error code = %u"), GetLastError() )); goto exit; }
hService = OpenService( hSvcMgr, ServiceName, SERVICE_ALL_ACCESS );
if (!hService) { DebugPrint(( TEXT("could not open the %s service: error code = %u"), ServiceName, GetLastError() )); goto exit; }
if (!ChangeServiceConfig( hService, // handle to service
SERVICE_NO_CHANGE, // type of service
StartType, // when to start service
SERVICE_NO_CHANGE, // severity if service fails to start
NULL, // pointer to service binary file name
NULL, // pointer to load ordering group name
NULL, // pointer to variable to get tag identifier
NULL, // pointer to array of dependency names
NULL, // pointer to account name of service
NULL, // pointer to password for service account
NULL // pointer to display name
)) { DebugPrint(( TEXT("could not open change service configuration, ec=%d"), GetLastError() )); goto exit; }
rVal = TRUE;
exit: CloseServiceHandle( hService ); CloseServiceHandle( hSvcMgr );
return rVal; }
DWORD MyGetFileSize(LPCTSTR FileName) { HANDLE hFile = INVALID_HANDLE_VALUE; DWORD sizelow=0, sizehigh=0;
hFile = CreateFile( FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
if (hFile == INVALID_HANDLE_VALUE) { return 0; }
sizelow = GetFileSize(hFile,&sizehigh); if (sizehigh == 0xFFFFFFFFF) { sizelow = 0; } else if (sizehigh!=0) { sizelow=0xFFFFFFFF; }
CloseHandle(hFile);
return sizelow; }
extern CRITICAL_SECTION CsClients; extern CRITICAL_SECTION CsHandleTable; extern CRITICAL_SECTION CsJob; extern CRITICAL_SECTION CsLine; extern CRITICAL_SECTION CsPerfCounters; extern CRITICAL_SECTION CsQueue; extern CRITICAL_SECTION CsRouting; LPCWSTR szCsClients = L"CsClients"; LPCWSTR szCsHandleTable = L"CsHandleTable"; LPCWSTR szCsJob = L"CsJob"; LPCWSTR szCsLine = L"CsLine"; LPCWSTR szCsPerfCounters = L"CsPerfCounters"; LPCWSTR szCsQueue = L"CsQueue"; LPCWSTR szCsRouting = L"CsRouting"; LPCWSTR szCsUnknown = L"Other CS";
LPCWSTR GetSzCs( LPCRITICAL_SECTION cs ) {
if (cs == &CsClients) { return szCsClients; } else if (cs == &CsHandleTable) { return szCsHandleTable; } else if (cs == &CsJob) { return szCsJob; } else if (cs == &CsLine) { return szCsLine; } else if (cs == &CsPerfCounters) { return szCsPerfCounters; } else if (cs == &CsQueue) { return szCsQueue; } else if (cs == &CsRouting) { return szCsRouting; }
return szCsUnknown;
}
#if DBG
VOID AppendToLogFile( LPWSTR String ) { DWORD BytesWritten; LPSTR AnsiBuffer = UnicodeStringToAnsiString( String );
if (hLogFile != INVALID_HANDLE_VALUE) { WriteFile(hLogFile,(LPBYTE)AnsiBuffer,strlen(AnsiBuffer) * sizeof(CHAR),&BytesWritten,NULL); }
MemFree(AnsiBuffer);
}
VOID AppendFuncToLogFile( LPCRITICAL_SECTION cs, LPTSTR szFunc, DWORD line, LPTSTR file, PDBGCRITSEC CritSec ) { WCHAR Buffer[300]; LPWSTR FileName; LPCWSTR szcs = GetSzCs(cs);
FileName = wcsrchr(file,'\\'); if (!FileName) { FileName = TEXT("Unknown "); } else { FileName += 1; } if (CritSec) { wsprintf(Buffer,TEXT("%d\t%x\t%s\t%s\t%s\t%d\t%d\r\n"), GetTickCount(), (PULONG_PTR)cs, szcs, szFunc, FileName, line, CritSec->ReleasedTime - CritSec->AquiredTime); } else { wsprintf(Buffer,TEXT("%d\t%x\t%s\t%s\t%s\t%d\r\n"),GetTickCount(),(PULONG_PTR)cs,szcs,szFunc, FileName,line); } AppendToLogFile( Buffer ); return;
}
VOID pEnterCriticalSection( LPCRITICAL_SECTION cs, DWORD line, LPTSTR file ) { extern CRITICAL_SECTION CsJob; extern CRITICAL_SECTION CsQueue; //PDBGCRITSEC CritSec;
PDBGCRITSEC pCritSec = MemAlloc(sizeof(DBGCRITSEC)); pCritSec->CritSecAddr = (ULONG_PTR) cs; pCritSec->AquiredTime = GetTickCount(); pCritSec->ThreadId = GetCurrentThreadId();
InsertHeadList( &CritSecListHead, &pCritSec->ListEntry );
AppendFuncToLogFile(cs,TEXT("EnterCriticalSection"), line, file, NULL ); #ifdef EnterCriticalSection
#undef EnterCriticalSection
//
// check ordering of threads. ALWAYS aquire CsJob before aquiring CsQueue!!!
//
if ((LPCRITICAL_SECTION)cs == (LPCRITICAL_SECTION)&CsQueue) { if ((DWORD)GetCurrentThreadId() != PtrToUlong(CsJob.OwningThread)) { WCHAR DebugBuf[300]; wsprintf(DebugBuf, TEXT("%d : Attempting to aquire CsQueue (thread %x) without aquiring CsJob (thread %x, lock count %x) first, possible deadlock!\r\n"), GetTickCount(), GetCurrentThreadId(), CsJob.OwningThread, CsJob.LockCount ); AppendToLogFile( DebugBuf ); } } EnterCriticalSection(cs); #endif
}
VOID pLeaveCriticalSection( LPCRITICAL_SECTION cs, DWORD line, LPTSTR file ) { PDBGCRITSEC CritSec; PLIST_ENTRY Next = CritSecListHead.Flink; while ((ULONG_PTR)Next != (ULONG_PTR) &CritSecListHead) { CritSec = CONTAINING_RECORD( Next, DBGCRITSEC, ListEntry ); if ((ULONG_PTR)CritSec->CritSecAddr == (ULONG_PTR) cs && ( GetCurrentThreadId() == CritSec->ThreadId ) ) { CritSec->ReleasedTime = GetTickCount(); break; } Next = Next->Flink; }
AppendFuncToLogFile(cs,TEXT("LeaveCriticalSection"),line, file, CritSec );
if (CritSec) { RemoveEntryList( &CritSec->ListEntry ); MemFree( CritSec ); }
#ifdef LeaveCriticalSection
#undef LeaveCriticalSection
LeaveCriticalSection(cs); #endif
}
VOID pInitializeCriticalSection( LPCRITICAL_SECTION cs, DWORD line, LPTSTR file ) { AppendFuncToLogFile(cs,TEXT("InitializeCriticalSection"),line, file, NULL);
#ifdef InitializeCriticalSection
#undef InitializeCriticalSection
InitializeCriticalSection(cs); #endif
}
#endif
DWORD ValidateTiffFile( LPCWSTR TifFileName ) {
HANDLE hTiff; DWORD rc = ERROR_SUCCESS; TIFF_INFO TiffInfo;
//
// impersonate the client
//
if (RpcImpersonateClient(NULL) != RPC_S_OK) { rc = GetLastError(); goto e0; }
//
// make sure the client can see the file
//
if (GetFileAttributes(TifFileName) == 0xFFFFFFFF) { rc = GetLastError(); goto e1; }
//
// make sure the client has read-write access to the file
//
hTiff = TiffOpen( (LPWSTR)TifFileName, &TiffInfo, FALSE, FILLORDER_MSB2LSB ); if (!hTiff) { rc = GetLastError(); goto e1; } TiffClose( hTiff ); e1: RpcRevertToSelf(); e0: return rc;
}
|