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.
 
 
 
 
 
 

1203 lines
34 KiB

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
faxapi.c
Abstract:
This module contains the Win32 FAX APIs.
The function implemented here are simply very
thin wrappers around the RPC stubs. The wrappers
are necessary so that the last error value
is set properly.
Author:
Wesley Witt (wesw) 16-Jan-1996
Revision History:
--*/
#include "faxapi.h"
#pragma hdrstop
static
DWORD
ConnectToFaxServer(
PHANDLE_ENTRY pHandleEntry,
PFAX_HANDLE_DATA pFaxData
)
/*++
Routine Description:
Helper function that wrap RPC call for connecting to the fax service.
The function first attempt to call FAX_ConnectFaxServer in order to connect to .NET or XP fax servers,
if the call fails with RPC_S_PROCNUM_OUT_OF_RANGE, that indicates that we are dealing with BOS 2000, we try
to connect to BOS fax server with FAX_ConnectionRefCount.
Arguments:
pHandleEntry - [in/out] pointer to fax service handle entry.
the function will use the binding handle and update the context handle.
pFaxData - [in/out] pointer to fax handle data.
the function will update the server's API version within this handle data
Return Value:
Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DEBUG_FUNCTION_NAME(TEXT("ConnectToFaxServer"));
Assert (pHandleEntry);
Assert (pFaxData);
__try
{
dwRes = FAX_ConnectFaxServer( FH_FAX_HANDLE(pHandleEntry), // Binding handle
CURRENT_FAX_API_VERSION, // Our API version
&(pFaxData->dwReportedServerAPIVersion), // Server's API version
&FH_CONTEXT_HANDLE(pHandleEntry)); // Server's context handle
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
//
// For some reason we crashed.
//
dwRes = GetExceptionCode();
}
if (ERROR_SUCCESS != dwRes)
{
if (RPC_S_PROCNUM_OUT_OF_RANGE == dwRes)
{
//
// Got "The procedure number is out of range.".
// This is because we're trying to call an RPC function which doesn't exist in BOS 2000 Fax server.
// Try the 'old' FaxConnectionRefCount() call
//
DWORD dwShare; // Igonred
__try
{
dwRes = FAX_ConnectionRefCount( FH_FAX_HANDLE(pHandleEntry),
&FH_CONTEXT_HANDLE(pHandleEntry),
1,
&dwShare);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
//
// For some reason we crashed.
//
dwRes = GetExceptionCode();
}
if (ERROR_SUCCESS == dwRes)
{
//
// Hooray!!! This is a BOS 2000 Fax Server
//
pFaxData->dwReportedServerAPIVersion = FAX_API_VERSION_0;
}
else
{
DebugPrintEx(
DEBUG_ERR,
TEXT("Exception on RPC call to FAX_ConnectionRefCount. (ec: %lu)"),
dwRes);
DumpRPCExtendedStatus ();
}
}
else
{
DebugPrintEx(
DEBUG_ERR,
TEXT("Exception on RPC call to FAX_ConnectFaxServer. (ec: %lu)"),
dwRes);
DumpRPCExtendedStatus ();
}
}
return dwRes;
} // ConnectToFaxServer
//
// Note: the name of this function is actually a macro that expands to FaxConnectFaxServerW
// or FaxConnectFaxServerA depnding on the UNICODE macro.
//
BOOL
WINAPI
FaxConnectFaxServer(
IN LPCTSTR lpMachineName OPTIONAL,
OUT LPHANDLE FaxHandle
)
/*++
Routine Description:
Creates a connection to a FAX server. The binding handle that is
returned is used for all subsequent FAX API calls.
Arguments:
lpMachineName - Machine name, NULL, or "."
FaxHandle - Pointer to a FAX handle
Return Value:
TRUE - Success
FALSE - Failure, call GetLastError() for more error information.
--*/
{
PFAX_HANDLE_DATA pFaxData = NULL;
PHANDLE_ENTRY pHandleEntry = NULL;
DWORD dwRes = ERROR_SUCCESS;
BOOL bLocalConnection = IsLocalMachineName (lpMachineName);
DEBUG_FUNCTION_NAME(TEXT("FaxConnectFaxServer"));
if (!FaxHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
DebugPrintEx(DEBUG_ERR, _T("FaxHandle is NULL."));
return FALSE;
}
pFaxData = (PFAX_HANDLE_DATA)MemAlloc( sizeof(FAX_HANDLE_DATA) );
if (!pFaxData)
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
DebugPrintEx(DEBUG_ERR, _T("MemAlloc is failed."));
return FALSE;
}
ZeroMemory (pFaxData, sizeof(FAX_HANDLE_DATA));
pFaxData->bLocalConnection = bLocalConnection;
InitializeListHead( &pFaxData->HandleTableListHead );
//
// Create new Service handle, in case of an error
// after this function succeeded cleanup code must call CloseFaxHandle()
//
pHandleEntry = CreateNewServiceHandle( pFaxData );
if (!pHandleEntry)
{
dwRes = GetLastError ();
DebugPrintEx(DEBUG_ERR, _T("CreateNewServiceHandle() failed."));
MemFree(pFaxData);
return FALSE;
}
dwRes = FaxClientBindToFaxServer( lpMachineName, FAX_RPC_ENDPOINT, NULL, &pFaxData->FaxHandle );
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(DEBUG_ERR, _T("FaxClientBindToFaxServer() failed with %ld."), dwRes);
pFaxData->FaxHandle = NULL;
goto ErrorExit;
}
if (!bLocalConnection)
{
//
// This is not the local machine, Remove all \\ from machine name
//
LPCTSTR lpctstrDelim = _tcsrchr(lpMachineName, TEXT('\\'));
if (NULL == lpctstrDelim)
{
lpctstrDelim = lpMachineName;
}
else
{
lpctstrDelim = _tcsinc(lpctstrDelim);
}
pFaxData->MachineName = StringDup (lpctstrDelim);
if (!pFaxData->MachineName)
{
dwRes = ERROR_NOT_ENOUGH_MEMORY;
goto ErrorExit;
}
}
//
// Ask for the highest level of privacy (autnetication + encryption)
//
dwRes = RpcBindingSetAuthInfo (
FH_FAX_HANDLE(pHandleEntry), // RPC binding handle
RPC_SERVER_PRINCIPAL_NAME, // Server principal name
RPC_C_AUTHN_LEVEL_PKT_PRIVACY, // Authentication level - fullest
// Authenticates, verifies, and privacy-encrypts the arguments passed
// to every remote call.
RPC_C_AUTHN_WINNT, // Authentication service (NTLMSSP)
NULL, // Authentication identity - use currently logged on user
0); // Unused when Authentication service == RPC_C_AUTHN_WINNT
if (ERROR_SUCCESS != dwRes)
{
//
// Couldn't set RPC authentication mode
//
DebugPrintEx(
DEBUG_ERR,
TEXT("RpcBindingSetAuthInfo (RPC_C_AUTHN_LEVEL_PKT_PRIVACY) failed. (ec: %ld)"),
dwRes);
goto ErrorExit;
}
//
// On local connections make sure that the fax service is up
//
if (bLocalConnection)
{
if (!EnsureFaxServiceIsStarted (NULL))
{
dwRes = GetLastError ();
DebugPrintEx(
DEBUG_ERR,
TEXT("EnsureFaxServiceIsStarted failed (ec = %ld"),
dwRes);
goto ErrorExit;
}
else
{
//
// Wait till the RPC service is up an running
//
if (!WaitForServiceRPCServer (60 * 1000))
{
dwRes = GetLastError ();
DebugPrintEx(
DEBUG_ERR,
TEXT("WaitForServiceRPCServer failed (ec = %ld"),
dwRes);
goto ErrorExit;
}
}
}
//
// Here we tries to connect to the Fax service.
//
// We try to connect three times, two times using RPC_C_AUTHN_LEVEL_PKT_PRIVACY Authentication level
// and if we fail we drop to RPC_C_AUTHN_LEVEL_NONE Authentication level.
//
// We try twice with RPC_C_AUTHN_LEVEL_PKT_PRIVACY authentication level, because RPC runtime infrastructure might cache
// the service handle, and if the service was restarted the first RPC call will use the old cached data, and will fail.
// RPC cannot internally retry because we dealling with privacy authentication and thus we do the retry.
//
// If we fail to connect twice we drop the authentication level and retry. This is done to allow .NET clients to connect to
// Fax servers that does not use a secure channel.
// We do not need to retry the connection, beacuse RPC will do that internally.
//
dwRes = ConnectToFaxServer(pHandleEntry,pFaxData);
if (dwRes != ERROR_SUCCESS)
{
DebugPrintEx (DEBUG_WRN,
TEXT("fisrt call to ConnectToFaxServer failed with - %lu"),
dwRes);
dwRes = ConnectToFaxServer(pHandleEntry,pFaxData);
if (dwRes != ERROR_SUCCESS)
{
//
// We failed twice, Drop authentication level and retry.
//
DebugPrintEx (DEBUG_WRN,
TEXT("second call to ConnectToFaxServer failed with - %lu"),
dwRes);
DebugPrintEx (DEBUG_WRN,
TEXT("Warning!!! not using encryption anymore against remote server %s"),
lpMachineName);
dwRes = RpcBindingSetAuthInfo (
FH_FAX_HANDLE(pHandleEntry), // RPC binding handle
RPC_SERVER_PRINCIPAL_NAME, // Server principal name
RPC_C_AUTHN_LEVEL_NONE, // Authentication level - none
RPC_C_AUTHN_WINNT, // Authentication service (NTLMSSP)
NULL, // Authentication identity - use currently logged on user
0); // Unused when Authentication service == RPC_C_AUTHN_WINNT
if (ERROR_SUCCESS != dwRes)
{
//
// Couldn't set RPC authentication mode
//
DebugPrintEx(
DEBUG_ERR,
TEXT("RpcBindingSetAuthInfo (RPC_C_AUTHN_LEVEL_NONE) failed. (ec: %lu)"),
dwRes);
goto ErrorExit;
}
dwRes = ConnectToFaxServer(pHandleEntry,pFaxData);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx (DEBUG_ERR,
TEXT("third call to ConnectToFaxServer failed with - %lu"),
dwRes);
goto ErrorExit;
}
}
}
if (ERROR_SUCCESS == dwRes)
{
//
// Succeeded to connect
//
pFaxData->dwServerAPIVersion = pFaxData->dwReportedServerAPIVersion;
if (pFaxData->dwReportedServerAPIVersion > CURRENT_FAX_API_VERSION)
{
//
// This is the filtering.
// Assume we're talking to a Windows XP server since we have no knowledge of future servers.
//
pFaxData->dwServerAPIVersion = CURRENT_FAX_API_VERSION;
}
*FaxHandle = (LPHANDLE) pHandleEntry;
return TRUE;
}
ErrorExit:
Assert (ERROR_SUCCESS != dwRes);
if (NULL != pFaxData)
{
if (NULL != pFaxData->FaxHandle)
{
RpcBindingFree(&pFaxData->FaxHandle);
}
}
//
// clean up for CreateNewServiceHandle
//
CloseFaxHandle ( pHandleEntry );
SetLastError(dwRes);
return FALSE;
} // FaxConnectFaxServer
#ifdef UNICODE
BOOL
WINAPI
FaxConnectFaxServerA(
IN LPCSTR lpMachineName OPTIONAL,
OUT LPHANDLE FaxHandle
)
/*++
Routine Description:
Creates a connection to a FAX server. The binding handle that is
returned is used for all subsequent FAX API calls.
Arguments:
MachineName - Machine name, NULL, or "."
FaxHandle - Pointer to a FAX handle
Return Value:
TRUE - Success
FALSE - Failure, call GetLastError() for more error information.
--*/
{
PWCHAR lpwstrMachineName = NULL;
BOOL bRes;
DEBUG_FUNCTION_NAME(TEXT("FaxConnectFaxServerA"));
if (lpMachineName)
{
//
// Create Unicode machine name
//
lpwstrMachineName = AnsiStringToUnicodeString (lpMachineName);
if (!lpwstrMachineName)
{
return FALSE;
}
}
bRes = FaxConnectFaxServerW (lpwstrMachineName, FaxHandle);
MemFree (lpwstrMachineName);
return bRes;
} // FaxConnectFaxServerA
#else
//
// When compiling this code to ANSI we do not want to support the Unicode version.
//
BOOL
WINAPI
FaxConnectFaxServerW(
IN LPCWSTR lpMachineName OPTIONAL,
OUT LPHANDLE FaxHandle
)
{
UNREFERENCED_PARAMETER(lpMachineName);
UNREFERENCED_PARAMETER(FaxHandle);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
#endif
BOOL
WINAPI
FaxGetDeviceStatusW(
IN const HANDLE FaxHandle,
OUT PFAX_DEVICE_STATUSW *DeviceStatus
)
/*++
Routine Description:
Obtains a status report for the FAX devices being
used by the FAX server.
Arguments:
FaxHandle - FAX handle obtained from FaxConnectFaxServer.
StatusBuffer - Buffer for the status data
BufferSize - Size of the StatusBuffer
Return Value:
TRUE - Success
FALSE - Failure, call GetLastError() for more error information.
--*/
{
#define FixupString(_s) FixupStringPtrW(DeviceStatus,_s)
error_status_t ec;
DWORD BufferSize = 0;
DEBUG_FUNCTION_NAME(TEXT("FaxGetDeviceStatusW"));
if (!ValidateFaxHandle(FaxHandle, FHT_PORT)) {
SetLastError(ERROR_INVALID_HANDLE);
DebugPrintEx(DEBUG_ERR, _T("ValidateFaxHandle() is failed."));
return FALSE;
}
if (!DeviceStatus) {
SetLastError(ERROR_INVALID_PARAMETER);
DebugPrintEx(DEBUG_ERR, _T("DeviceStatus is NULL."));
return FALSE;
}
*DeviceStatus = NULL;
__try
{
ec = FAX_GetDeviceStatus(
FH_PORT_HANDLE(FaxHandle),
(LPBYTE*)DeviceStatus,
&BufferSize
);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
//
// For some reason we crashed.
//
ec = GetExceptionCode();
DebugPrintEx(
DEBUG_ERR,
TEXT("Exception on RPC call to FAX_GetDeviceStatus. (ec: %ld)"),
ec);
}
if (ec)
{
DumpRPCExtendedStatus ();
SetLastError( ec );
return FALSE;
}
FixupString( (*DeviceStatus)->CallerId );
FixupString( (*DeviceStatus)->Csid );
FixupString( (*DeviceStatus)->DeviceName );
FixupString( (*DeviceStatus)->DocumentName );
FixupString( (*DeviceStatus)->PhoneNumber );
FixupString( (*DeviceStatus)->RoutingString );
FixupString( (*DeviceStatus)->SenderName );
FixupString( (*DeviceStatus)->RecipientName );
FixupString( (*DeviceStatus)->StatusString );
FixupString( (*DeviceStatus)->Tsid );
FixupString( (*DeviceStatus)->UserName );
return TRUE;
}
BOOL
WINAPI
FaxGetDeviceStatusA(
IN const HANDLE FaxHandle,
OUT PFAX_DEVICE_STATUSA *DeviceStatus
)
/*++
Routine Description:
Obtains a status report for the FAX devices being
used by the FAX server.
Arguments:
FaxHandle - FAX handle obtained from FaxConnectFaxServer.
StatusBuffer - Buffer for the status data
BufferSize - Size of the StatusBuffer
Return Value:
TRUE - Success
FALSE - Failure, call GetLastError() for more error information.
--*/
{
//
// no need to validate parameters, FaxGetDeviceStatusW() will do that
//
DEBUG_FUNCTION_NAME(TEXT("FaxGetDeviceStatusA"));
if (!FaxGetDeviceStatusW( FaxHandle, (PFAX_DEVICE_STATUSW *)DeviceStatus ))
{
return FALSE;
}
if (!ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->CallerId ) ||
!ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->Csid ) ||
!ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->DeviceName ) ||
!ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->DocumentName ) ||
!ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->PhoneNumber ) ||
!ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->RoutingString ) ||
!ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->SenderName ) ||
!ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->RecipientName ) ||
!ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->StatusString ) ||
!ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->Tsid ) ||
!ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->UserName ))
{
DebugPrintEx(DEBUG_ERR, _T("ConvertUnicodeStringInPlace failed, ec = %ld."), GetLastError());
MemFree (*DeviceStatus);
return FALSE;
}
(*DeviceStatus)->SizeOfStruct = sizeof(FAX_DEVICE_STATUSA);
return TRUE;
} // FaxGetDeviceStatusA
BOOL
WINAPI
FaxClose(
IN const HANDLE FaxHandle
)
{
error_status_t ec;
PHANDLE_ENTRY pHandleEntry = (PHANDLE_ENTRY) FaxHandle;
HANDLE TmpFaxPortHandle;
DWORD CanShare;
DEBUG_FUNCTION_NAME(TEXT("FaxClose"));
if (!FaxHandle || IsBadReadPtr ((LPVOID)FaxHandle, sizeof (HANDLE_ENTRY)))
{
SetLastError(ERROR_INVALID_HANDLE);
DebugPrintEx(DEBUG_ERR, _T("!FaxHandle || IsBadReadPtr(FaxHandle)."));
return FALSE;
}
switch (pHandleEntry->Type)
{
case FHT_SERVICE:
__try
{
ec = FAX_ConnectionRefCount( FH_FAX_HANDLE(FaxHandle), &FH_CONTEXT_HANDLE(FaxHandle), 0, &CanShare );
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
//
// For some reason we crashed.
//
ec = GetExceptionCode();
DebugPrintEx(
DEBUG_ERR,
TEXT("Exception on RPC call to FAX_ConnectionRefCount. (ec: %ld)"),
ec);
}
if (ERROR_SUCCESS != ec)
{
DumpRPCExtendedStatus ();
}
__try
{
ec = FaxClientUnbindFromFaxServer( (RPC_BINDING_HANDLE *) pHandleEntry->FaxData->FaxHandle );
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
ec = GetExceptionCode();
}
EnterCriticalSection( &pHandleEntry->FaxData->CsHandleTable );
//
// Zero the binding handle so that no further RPC calls will be made with floating handles
// that still hold the FAX_HANDLE_DATA (e.g. from FaxOpenPort).
//
pHandleEntry->FaxData->FaxHandle = 0;
#if DBG
if (pHandleEntry->FaxData->dwRefCount > 1)
{
//
// The user closed the binding handle (called FaxClose (hFax)) before closing all context
// handles (e.g. FaxClose (hPort)).
// This is not a real problem - the reference count mechanism will take care of it.
//
DebugPrintEx(
DEBUG_WRN,
TEXT("User called FaxClose with a service handle but still has live context handles (port or message enum)"));
}
#endif
LeaveCriticalSection( &pHandleEntry->FaxData->CsHandleTable );
CloseFaxHandle ( pHandleEntry );
return TRUE;
case FHT_PORT:
TmpFaxPortHandle = pHandleEntry->hGeneric;
CloseFaxHandle( pHandleEntry );
__try
{
ec = FAX_ClosePort( &TmpFaxPortHandle );
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
//
// For some reason we crashed.
//
ec = GetExceptionCode();
DebugPrintEx(
DEBUG_ERR,
TEXT("Exception on RPC call to FAX_ClosePort. (ec: %ld)"),
ec);
}
if (ec)
{
DumpRPCExtendedStatus ();
SetLastError( ec );
return FALSE;
}
break;
default:
SetLastError( ERROR_INVALID_HANDLE );
return FALSE;
}
return TRUE;
}
BOOL
WINAPI
FaxGetSecurityEx(
IN HANDLE hFaxHandle,
IN SECURITY_INFORMATION SecurityInformation,
OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor
)
/*++
Routine name : FaxGetSecurityEx
Routine description:
Gets the server's security descriptor
Author:
Eran Yariv (EranY), Nov, 1999
Arguments:
hFaxHandle [in ] - Handle to fax server
SECURITY_INFORMATION [in ] - Defines the desired entries in the security descriptor (Bit wise OR )
ppSecurityDescriptor [out] - Pointer to receive buffer
Return Value:
TRUE - Success
FALSE - Failure, call GetLastError() for more error information.
--*/
{
error_status_t ec;
DWORD BufferSize = 0;
DEBUG_FUNCTION_NAME(TEXT("FaxGetSecurityEx"));
DWORD dwSecInfo = ( OWNER_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION |
DACL_SECURITY_INFORMATION |
SACL_SECURITY_INFORMATION );
if (!ValidateFaxHandle(hFaxHandle,FHT_SERVICE))
{
SetLastError(ERROR_INVALID_HANDLE);
DebugPrintEx(DEBUG_ERR, _T("ValidateFaxHandle() is failed."));
return FALSE;
}
if (0 == (SecurityInformation & dwSecInfo))
{
SetLastError( ERROR_INVALID_PARAMETER );
DebugPrintEx(DEBUG_ERR, _T("SecurityInformation is invalid - No valid bit type indicated"));
return FALSE;
}
if (0 != (SecurityInformation & ~dwSecInfo))
{
SetLastError( ERROR_INVALID_PARAMETER );
DebugPrintEx(DEBUG_ERR, _T("SecurityInformation is invalid - contains invalid securtiy information bits"));
return FALSE;
}
if (!ppSecurityDescriptor)
{
SetLastError(ERROR_INVALID_PARAMETER);
DebugPrintEx(DEBUG_ERR, _T("ppSecurityDescriptor is NULL."));
return FALSE;
}
if (FAX_API_VERSION_1 > FH_SERVER_VER(hFaxHandle))
{
//
// Servers of API version 0 don't support FAX_GetSecurityEx
//
DebugPrintEx(DEBUG_MSG,
_T("Server version is %ld - doesn't support FAX_GetSecurityEx."),
FH_SERVER_VER(hFaxHandle));
__try
{
ec = FAX_GetSecurity (
FH_FAX_HANDLE(hFaxHandle),
(LPBYTE *)ppSecurityDescriptor,
&BufferSize
);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
//
// For some reason we got an exception.
//
ec = GetExceptionCode();
DebugPrintEx(
DEBUG_ERR,
TEXT("Exception on RPC call to FAX_GetSecurity. (ec: %ld)"),
ec);
}
}
else
{
__try
{
ec = FAX_GetSecurityEx (
FH_FAX_HANDLE(hFaxHandle),
SecurityInformation,
(LPBYTE *)ppSecurityDescriptor,
&BufferSize
);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
//
// For some reason we got an exception.
//
ec = GetExceptionCode();
DebugPrintEx(
DEBUG_ERR,
TEXT("Exception on RPC call to FAX_GetSecurityEx. (ec: %ld)"),
ec);
}
}
if (ERROR_SUCCESS != ec)
{
DumpRPCExtendedStatus ();
SetLastError(ec);
return FALSE;
}
return TRUE;
} // FaxGetSecurityEx
BOOL
WINAPI
FaxGetSecurity(
IN HANDLE hFaxHandle,
OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor
)
/*++
Routine name : FaxGetSecurity
Routine description:
Gets the server's security descriptor
Author:
Eran Yariv (EranY), Nov, 1999
Arguments:
hFaxHandle [in ] - Handle to fax server
ppSecurityDescriptor [out] - Pointer to receive buffer
Return Value:
TRUE - Success
FALSE - Failure, call GetLastError() for more error information.
--*/
{
error_status_t ec;
DWORD BufferSize = 0;
DEBUG_FUNCTION_NAME(TEXT("FaxGetSecurity"));
if (!ValidateFaxHandle(hFaxHandle,FHT_SERVICE))
{
SetLastError(ERROR_INVALID_HANDLE);
DebugPrintEx(DEBUG_ERR, _T("ValidateFaxHandle() is failed."));
return FALSE;
}
if (!ppSecurityDescriptor)
{
SetLastError(ERROR_INVALID_PARAMETER);
DebugPrintEx(DEBUG_ERR, _T("ppSecurityDescriptor is NULL."));
return FALSE;
}
__try
{
ec = FAX_GetSecurity (
FH_FAX_HANDLE(hFaxHandle),
(LPBYTE *)ppSecurityDescriptor,
&BufferSize
);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
//
// For some reason we got an exception.
//
ec = GetExceptionCode();
DebugPrintEx(
DEBUG_ERR,
TEXT("Exception on RPC call to FAX_GetSecurity. (ec: %ld)"),
ec);
}
if (ERROR_SUCCESS != ec)
{
DumpRPCExtendedStatus ();
SetLastError(ec);
return FALSE;
}
return TRUE;
} // FaxGetSecurity
BOOL
WINAPI
FaxSetSecurity(
IN HANDLE hFaxHandle,
SECURITY_INFORMATION SecurityInformation,
IN PSECURITY_DESCRIPTOR pSecurityDescriptor
)
/*++
Routine name : FaxGetSecurity
Routine description:
Sets the server's security descriptor
Author:
Eran Yariv (EranY), Nov, 1999
Arguments:
hFaxHandle [in] - Handle to fax server
SecurityInformation [in] - Defines the valid entries in the security descriptor (Bit wise OR )
pSecurityDescriptor [in] - New security descriptor to set.
Must be self-relative.
Return Value:
TRUE - Success
FALSE - Failure, call GetLastError() for more error information.
--*/
{
error_status_t ec;
DWORD dwBufferSize;
DWORD dwRevision;
SECURITY_DESCRIPTOR_CONTROL sdControl;
DEBUG_FUNCTION_NAME(TEXT("FaxSetSecurity"));
DWORD dwSecInfo = ( OWNER_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION |
DACL_SECURITY_INFORMATION |
SACL_SECURITY_INFORMATION );
if (!ValidateFaxHandle(hFaxHandle,FHT_SERVICE))
{
SetLastError(ERROR_INVALID_HANDLE);
DebugPrintEx(DEBUG_ERR, _T("ValidateFaxHandle() is failed."));
return FALSE;
}
if (!pSecurityDescriptor)
{
SetLastError(ERROR_INVALID_PARAMETER);
DebugPrintEx(DEBUG_ERR, _T("pSecurityDescriptor is NULL."));
return FALSE;
}
if (0 == (SecurityInformation & dwSecInfo))
{
SetLastError( ERROR_INVALID_PARAMETER );
DebugPrintEx(DEBUG_ERR, _T("SecurityInformation is invalid - No valid bit type indicated"));
return FALSE;
}
if (0 != (SecurityInformation & ~dwSecInfo))
{
SetLastError( ERROR_INVALID_PARAMETER );
DebugPrintEx(DEBUG_ERR, _T("SecurityInformation is invalid - contains invalid securtiy information bits"));
return FALSE;
}
if (!IsValidSecurityDescriptor(pSecurityDescriptor))
{
SetLastError( ERROR_INVALID_SECURITY_DESCR );
DebugPrintEx(DEBUG_ERR, _T("Got invalid security descriptor"));
return FALSE;
}
if (!GetSecurityDescriptorControl (
pSecurityDescriptor,
&sdControl,
&dwRevision
))
{
DebugPrintEx(
DEBUG_ERR,
TEXT("Error on GetSecurityDescriptorControl (ec = %ld)"),
GetLastError());
return FALSE;
}
if (!(sdControl & SE_SELF_RELATIVE))
{
//
// Got a non-self-relative security descriptor - bad!!!
//
DebugPrintEx(DEBUG_ERR, _T("Got non-self-relative security descriptor"));
SetLastError( ERROR_INVALID_SECURITY_DESCR );
return FALSE;
}
dwBufferSize = GetSecurityDescriptorLength(pSecurityDescriptor);
__try
{
ec = FAX_SetSecurity(
FH_FAX_HANDLE(hFaxHandle),
SecurityInformation,
(LPBYTE)pSecurityDescriptor,
dwBufferSize
);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
//
// For some reason we got an exception.
//
ec = GetExceptionCode();
DebugPrintEx(
DEBUG_ERR,
TEXT("Exception on RPC call to FAX_SetSecurity. (ec: %ld)"),
ec);
}
if (ec != ERROR_SUCCESS)
{
DumpRPCExtendedStatus ();
SetLastError(ec);
return FALSE;
}
return TRUE;
} // FaxSetSecurity
BOOL
WINAPI
FaxRelease(
IN const HANDLE FaxHandle
)
/*++
Routine name : FaxRelease
Routine description:
The Fax Service counts all the clients connected to it. When this reference count reaches zero,
the Fax Service can download itself.
There are some connections that do not want to prevent from the service to download,
like Task Bar Monitor.
These clients should call this function.
It adds the indication on the handle that it is "Released" and decrements the total reference count.
Author:
Iv Garber (IvG), Jan, 2001
Arguments:
FaxHandle [in] - the client connection handle that do not want to prevent the service from downloading.
Return Value:
BOOL - TRUE if operation is successfull, otherwise FALSE.
--*/
{
error_status_t ec;
DWORD CanShare;
DEBUG_FUNCTION_NAME(TEXT("FaxRelease"));
if (!ValidateFaxHandle(FaxHandle,FHT_SERVICE))
{
SetLastError(ERROR_INVALID_HANDLE);
DebugPrintEx(DEBUG_ERR, _T("ValidateFaxHandle() is failed."));
return FALSE;
}
if (FAX_API_VERSION_1 > FH_SERVER_VER(FaxHandle))
{
//
// Servers of API version 0 don't support FAX_ConnectionRefCount(...,2,...)
//
DebugPrintEx(DEBUG_ERR,
_T("Server version is %ld - doesn't support this call"),
FH_SERVER_VER(FaxHandle));
SetLastError(FAX_ERR_VERSION_MISMATCH);
return FALSE;
}
//
// Decrement the Reference Count
//
__try
{
ec = FAX_ConnectionRefCount( FH_FAX_HANDLE(FaxHandle), &FH_CONTEXT_HANDLE(FaxHandle), 2, &CanShare );
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
//
// For some reason we crashed.
//
ec = GetExceptionCode();
DebugPrintEx(DEBUG_ERR, _T("Exception on RPC call to FAX_ConnectionRefCount. (ec: %ld)"), ec);
}
if (ec != ERROR_SUCCESS)
{
DumpRPCExtendedStatus ();
SetLastError(ec);
return FALSE;
}
return TRUE;
}
WINFAXAPI
BOOL
WINAPI
FaxGetReportedServerAPIVersion (
IN HANDLE hFaxHandle,
OUT LPDWORD lpdwReportedServerAPIVersion
)
/*++
Routine name : FaxGetReportedServerAPIVersion
Routine description:
Extracts the reported (non-filtered) fax server API version from an active connection handle
Author:
Eran Yariv (EranY), Mar, 2001
Arguments:
hFaxHandle [in] - Connection handle
lpdwReportedServerAPIVersion [out] - Fax server API version
Return Value:
BOOL - TRUE if operation is successfull, otherwise FALSE.
--*/
{
DEBUG_FUNCTION_NAME(TEXT("FaxGetReportedServerAPIVersion"));
if (!ValidateFaxHandle(hFaxHandle, FHT_SERVICE))
{
SetLastError(ERROR_INVALID_HANDLE);
DebugPrintEx(DEBUG_ERR, _T("ValidateFaxHandle() is failed."));
return FALSE;
}
*lpdwReportedServerAPIVersion = FH_REPORTED_SERVER_VER(hFaxHandle);
return TRUE;
} // FaxGetReportedServerAPIVersion