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.
 
 
 
 
 
 

1622 lines
38 KiB

/*++
(c) 1998 Seagate Software, Inc. All rights reserved.
Module Name:
fsaftclt.cpp
Abstract:
This class represents a user who the filter has detected accessing a file with placeholder information.
Author:
Chuck Bardeen [cbardeen] 12-Feb-1997
Revision History:
--*/
#include "stdafx.h"
extern "C" {
#include <ntseapi.h>
#include <wchar.h>
#include <lmaccess.h>
#include <lmserver.h>
#include <lmshare.h>
#include <lmapibuf.h>
#include <lmerr.h>
// #define MAC_SUPPORT // NOTE: You must define MAC_SUPPORT in fsafltr.cpp to enable all the code
#ifdef MAC_SUPPORT
#include <macfile.h>
#endif
}
#define WSB_TRACE_IS WSB_TRACE_BIT_FSA
#include "wsb.h"
#include "fsa.h"
#include "fsaftclt.h"
static USHORT iCountFtclt = 0; // Count of existing objects
//
// We need to dynamically load the DLL for MAC support because it is not there if
// the MAC service is not installed.
//
#ifdef MAC_SUPPORT
HANDLE FsaDllSfm = 0;
BOOL FsaMacSupportInstalled = FALSE;
extern "C" {
DWORD (*pAfpAdminConnect) (LPWSTR lpwsServerName, PAFP_SERVER_HANDLE phAfpServer);
VOID (*pAfpAdminDisconnect) (AFP_SERVER_HANDLE hAfpServer);
VOID (*pAfpAdminBufferFree) (PVOID pBuffer);
DWORD (*pAfpAdminSessionEnum) (AFP_SERVER_HANDLE hAfpServer, LPBYTE *lpbBuffer,
DWORD dwPrefMaxLen, LPDWORD lpdwEntriesRead, LPDWORD lpdwTotalEntries,
LPDWORD lpdwResumeHandle);
}
#endif
DWORD FsaIdentifyThread(void *pNotifyInterface);
DWORD FsaIdentifyThread(
void* pVoid
)
/*++
Entry point of the thread that performs identify operation with remote clients.
--*/
{
HRESULT hr;
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
hr = ((CFsaFilterClient*) pVoid)->IdentifyThread();
CoUninitialize();
return(hr);
}
//
// Get RsNotify interface (being used here in identify thread -
// similar utility function is being used in RsLnk)
//
static
HRESULT
GetNotifyClientInterface(
IN OLECHAR * machineName,
OUT IFsaRecallNotifyClient ** ppClient
)
{
HRESULT hr = S_OK;
try {
//
// Make sure parameters OK and OUTs initially cleared
//
WsbAffirmPointer ( ppClient );
*ppClient = 0;
//
// If connecting local, things work better to use NULL
// for the computer name
//
if ( machineName ) {
CWsbStringPtr localMachine;
WsbAffirmHr( WsbGetComputerName( localMachine ) );
if( _wcsicmp( localMachine, machineName ) == 0 ) {
machineName = 0;
}
}
//
// Set server info
//
COSERVERINFO csi;
COAUTHINFO cai;
memset ( &csi, 0, sizeof ( csi ) );
memset ( &cai, 0, sizeof ( cai ) );
// Set machine name
csi.pwszName = machineName;
// Create a proxy with security settings of no authentication (note that RsNotify is running with this security)
cai.dwAuthnSvc = RPC_C_AUTHN_WINNT;
cai.dwAuthzSvc = RPC_C_AUTHZ_DEFAULT;
cai.pwszServerPrincName = NULL;
cai.dwImpersonationLevel = RPC_C_IMP_LEVEL_IMPERSONATE;
cai.pAuthIdentityData = NULL;
cai.dwCapabilities = EOAC_NONE;
cai.dwAuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
csi.pAuthInfo = &cai;
//
// We want IFsaRecallNotifyClient back
//
MULTI_QI mqi;
memset ( &mqi, 0, sizeof ( mqi ) );
mqi.pIID = &IID_IFsaRecallNotifyClient;
//
// Make the connection...
//
WsbAffirmHr ( CoCreateInstanceEx (
CLSID_CFsaRecallNotifyClient, 0,
CLSCTX_NO_FAILURE_LOG | ( machineName ? CLSCTX_REMOTE_SERVER : CLSCTX_LOCAL_SERVER ),
&csi, 1, &mqi ) );
WsbAffirmHr ( mqi.hr );
//
// We need to make sure we clean up correctly if any interface
// post-processing fails, so assign over to a smart pointer for
// the time being
//
CComPtr<IFsaRecallNotifyClient> pClientTemp = (IFsaRecallNotifyClient*)mqi.pItf;
mqi.pItf->Release ( );
//
// Finally, we need to set the security on the procy to allow the
// anonymous connection. Values should be the same as above (COAUTHINFO)
// We need to make sure this is a remote machine first. Otherwise, we
// get an error of E_INVALIDARG.
//
if( machineName ) {
CComPtr<IClientSecurity> pSecurity;
WsbAffirmHr( pClientTemp->QueryInterface( IID_IClientSecurity, (void**)&pSecurity ) );
WsbAffirmHr( pSecurity->SetBlanket ( pClientTemp, RPC_C_AUTHN_NONE, RPC_C_AUTHZ_NONE, 0, RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IDENTIFY, 0, 0 ) );
}
//
// Finally, assign over and AddRef the return.
//
*ppClient = pClientTemp;
(*ppClient)->AddRef ( );
} WsbCatch ( hr );
return ( hr );
}
HRESULT
CFsaFilterClient::CheckRecallLimit(
IN DWORD minRecallInterval,
IN DWORD maxRecalls,
IN BOOLEAN exemptAdmin
)
/*++
Implements:
IWsbCollectable::CheckRecallLimit().
--*/
{
HRESULT hr = S_OK;
FILETIME now, last;
LARGE_INTEGER tNow, tLast;
ULONG rCount;
WsbTraceIn(OLESTR("CFsaFilterClient::CheckRecallLimit"), OLESTR(""));
try {
//
// Now check for runaway recall limits if the user is not
// an administrator
//
if ((!m_isAdmin) || (!exemptAdmin)) {
//
// See if the time since the end of the last recall is
// less than m_minRecallInterval (in seconds) and if so,
// increment the count.
// If not, then reset the count (if we were not
// already triggered).
// If the count is equal to the max then set the trigger.
//
WsbTrace(OLESTR("CHsmFilter::IoctlThread: Not an administrator or admin is not exempt.\n"));
GetSystemTimeAsFileTime(&now);
tNow.LowPart = now.dwLowDateTime;
tNow.HighPart = now.dwHighDateTime;
GetLastRecallTime(&last);
tLast.LowPart = last.dwLowDateTime;
tLast.HighPart = last.dwHighDateTime;
//
// Get the time (in 100 nano-second units)
// from the end of the last recall until now.
//
tNow.QuadPart -= tLast.QuadPart;
//
// Convert to seconds and check against the interval time
//
tNow.QuadPart /= (LONGLONG) 10000000;
if (tNow.QuadPart < (LONGLONG) minRecallInterval) {
//
// This one counts - increment the count
// and check for a trigger.
//
GetRecallCount(&rCount);
rCount++;
SetRecallCount(rCount);
WsbTrace(OLESTR("CHsmFilterClient::CheckRecallLimit: Recall count bumped to %ls.\n"),
WsbLongAsString(rCount));
if (rCount >= maxRecalls) {
//
// Hit the runaway recall limit. Set the
// limit flag.
//
WsbTrace(OLESTR("CHsmFilter::IoctlThread: Hit the runaway recall limit!!!.\n"));
SetHitRecallLimit(TRUE);
}
} else {
//
// Reset the count if they are not already triggered.
// If they are triggered then reset the trigger and
// limit if it has been a respectable time.
// TBD - What is a respectable time??
//
if (HitRecallLimit() != S_FALSE) {
if (tNow.QuadPart > (LONGLONG) minRecallInterval * 100) {
//
// A respectable time has passed - reset the trigger and count.
//
WsbTrace(OLESTR("CHsmFilterClient::CheckRecallLimit: Resetting recall limit trigger and count.\n"));
SetHitRecallLimit(FALSE);
SetRecallCount(0);
m_loggedLimitError = FALSE;
}
} else {
//
// This one did not count and they were not already triggered.
// Reset the count to zero.
//
WsbTrace(OLESTR("CHsmFilterClient::CheckRecallLimit: Resetting recall count.\n"));
SetRecallCount(0);
}
}
//
// Fail if the limit is hit.
//
WsbAffirm(HitRecallLimit() == S_FALSE, FSA_E_HIT_RECALL_LIMIT);
}
} WsbCatch(hr);
// NOTE - IF RUNAWAY RECALL BEHAVIOR CHANGES TO TRUNCATE ON CLOSE, CHANGE
// FSA_MESSAGE_HIT_RECALL_LIMIT_ACCESSDENIED TO FSA_MESSAGE_HIT_RECALL_LIMIT_TRUNCATEONCLOSE.
if ( (hr == FSA_E_HIT_RECALL_LIMIT) && (!m_loggedLimitError)) {
WsbLogEvent(FSA_MESSAGE_HIT_RECALL_LIMIT_ACCESSDENIED, 0, NULL, (WCHAR *) m_userName, NULL);
m_loggedLimitError = TRUE;
}
WsbTraceOut(OLESTR("CHsmFilterClient::CheckRecallLimit"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return(hr);
}
HRESULT
CFsaFilterClient::CompareBy(
FSA_FILTERCLIENT_COMPARE by
)
/*++
Implements:
IFsaFilterClient::CompareBy().
--*/
{
HRESULT hr = S_OK;
m_compareBy = by;
m_isDirty = TRUE;
return(hr);
}
HRESULT
CFsaFilterClient::CompareTo(
IN IUnknown* pUnknown,
OUT SHORT* pResult
)
/*++
Implements:
IWsbCollectable::CompareTo().
--*/
{
HRESULT hr = S_OK;
CComPtr<IFsaFilterClient> pClient;
WsbTraceIn(OLESTR("CFsaFilterClient::CompareTo"), OLESTR(""));
try {
// Did they give us a valid item to compare to?
WsbAssert(0 != pUnknown, E_POINTER);
// We need the IWsbBool interface to get the value of the object.
WsbAffirmHr(pUnknown->QueryInterface(IID_IFsaFilterClient, (void**) &pClient));
// Compare the rules.
hr = CompareToIClient(pClient, pResult);
} WsbCatch(hr);
WsbTraceOut(OLESTR("CHsmFilterClient::CompareTo"), OLESTR("hr = <%ls>, result = <%ls>"), WsbHrAsString(hr), WsbPtrToShortAsString(pResult));
return(hr);
}
HRESULT
CFsaFilterClient::CompareToAuthenticationId(
IN LONG luidHigh,
IN ULONG luidLow,
OUT SHORT* pResult
)
/*++
Implements:
IFsaFilterClient::CompareToAuthenticationId().
--*/
{
HRESULT hr = S_OK;
SHORT aResult;
WsbTraceIn(OLESTR("CFsaFilterClient::CompareToAuthenticationId"), OLESTR(""));
try {
if (m_luidHigh > luidHigh) {
aResult = 1;
} else if (m_luidHigh < luidHigh) {
aResult = -1;
} else if (m_luidLow > luidLow) {
aResult = 1;
} else if (m_luidLow < luidLow) {
aResult = -1;
} else {
aResult = 0;
}
if (0 != aResult) {
hr = S_FALSE;
}
if (0 != pResult) {
*pResult = aResult;
}
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaFilterClient::CompareToAuthenticationId"), OLESTR("hr = <%ls>, result = <%d>"), WsbHrAsString(hr), aResult);
return(hr);
}
HRESULT
CFsaFilterClient::CompareToIClient(
IN IFsaFilterClient* pClient,
OUT SHORT* pResult
)
/*++
Implements:
IFsaFilterClient::CompareToIClient().
--*/
{
HRESULT hr = S_OK;
CWsbStringPtr name;
LONG luidHigh;
ULONG luidLow;
WsbTraceIn(OLESTR("CFsaFilterClient::CompareToIClient"), OLESTR(""));
try {
// Did they give us a valid item to compare to?
WsbAssert(0 != pClient, E_POINTER);
switch (m_compareBy) {
case FSA_FILTERCLIENT_COMPARE_ID:
WsbAffirmHr(pClient->GetAuthenticationId(&luidHigh, &luidLow));
hr = CompareToAuthenticationId(luidHigh, luidLow, pResult);
break;
case FSA_FILTERCLIENT_COMPARE_MACHINE:
WsbAffirmHr(pClient->GetMachineName(&name, 0));
hr = CompareToMachineName(name, pResult);
break;
default:
WsbAssert(FALSE, E_UNEXPECTED);
}
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaFilterClient::CompareToIClient"), OLESTR("hr = <%ls>, result = <%ls>"), WsbHrAsString(hr), WsbPtrToShortAsString(pResult));
return(hr);
}
HRESULT
CFsaFilterClient::CompareToMachineName(
IN OLECHAR* name,
OUT SHORT* pResult
)
/*++
Implements:
IFsaFilterClient::CompareToMachineName().
--*/
{
HRESULT hr = S_OK;
SHORT aResult;
WsbTraceIn(OLESTR("CFsaFilterClient::CompareToMachineName"), OLESTR(""));
try {
aResult = (SHORT)wcscmp(name, m_machineName); // TBD - Case sensitive or not?
if (0 != aResult) {
hr = S_FALSE;
}
if (0 != pResult) {
*pResult = aResult;
}
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaFilterClient::CompareToMachineName"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return(hr);
}
HRESULT
CFsaFilterClient::FinalConstruct(
void
)
/*++
Implements:
CComObjectRoot::FinalConstruct().
--*/
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CFsaFilterClient::FinalConstruct"),OLESTR(""));
try {
WsbAffirmHr(CWsbCollectable::FinalConstruct());
m_compareBy = FSA_FILTERCLIENT_COMPARE_ID;
m_luidHigh = 0;
m_luidLow = 0;
m_hasRecallDisabled = FALSE;
m_hitRecallLimit = FALSE;
m_lastRecallTime.dwLowDateTime = 0;
m_lastRecallTime.dwHighDateTime = 0;
m_identified = FALSE;
m_tokenSource = L"";
m_msgCounter = 1;
m_identifyThread = NULL;
m_isAdmin = FALSE;
m_loggedLimitError = FALSE;
m_recallCount = 0;
} WsbCatch(hr);
iCountFtclt++;
WsbTraceOut(OLESTR("CFsaFilterClient::FinalConstruct"),OLESTR("Count is <%d>"), iCountFtclt);
return(hr);
}
void
CFsaFilterClient::FinalRelease(
void
)
/*++
Implements:
CComObjectRoot::FinalRelease().
--*/
{
WsbTraceIn(OLESTR("CFsaFilterClient::FinalRelease"),OLESTR(""));
if (NULL != m_identifyThread) {
CloseHandle(m_identifyThread);
m_identifyThread = NULL;
}
CWsbCollectable::FinalRelease();
iCountFtclt--;
WsbTraceOut(OLESTR("CFsaFilterClient::FinalRelease"),OLESTR("Count is <%d>"), iCountFtclt);
}
HRESULT
CFsaFilterClient::GetClassID(
OUT CLSID* pClsid
)
/*++
Implements:
IPersist::GetClassID().
--*/
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CFsaFilterClient::GetClassID"), OLESTR(""));
try {
WsbAssert(0 != pClsid, E_POINTER);
*pClsid = CLSID_CFsaFilterClientNTFS;
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaFilterClient::GetClassID"), OLESTR("hr = <%ls>, CLSID = <%ls>"), WsbHrAsString(hr), WsbGuidAsString(*pClsid));
return(hr);
}
HRESULT
CFsaFilterClient::GetAuthenticationId(
OUT LONG* pLuidHigh,
OUT ULONG* pLuidLow
)
/*++
Implements:
IFsaFilterClient::GetAuthenticationId().
--*/
{
HRESULT hr = S_OK;
try {
WsbAssert(0 != pLuidHigh, E_POINTER);
WsbAssert(0 != pLuidLow, E_POINTER);
*pLuidHigh = m_luidHigh;
*pLuidLow = m_luidLow;
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaFilterClient::GetDomainName(
OUT OLECHAR** pName,
IN ULONG bufferSize
)
/*++
Implements:
IFsaFilterClient::GetDomainName().
--*/
{
HRESULT hr = S_OK;
try {
WsbAssert(0 != pName, E_POINTER);
WsbAffirmHr(m_domainName.CopyTo(pName, bufferSize));
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaFilterClient::GetIsAdmin(
OUT BOOLEAN *pIsAdmin
)
/*++
Implements:
IPersist::GetIsAdmin().
--*/
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CFsaFilterClient::GetIsAdmin"), OLESTR(""));
try {
WsbAssert(0 != pIsAdmin, E_POINTER);
*pIsAdmin = m_isAdmin;
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaFilterClient::GetIsAdmin"), OLESTR("hr = <%ls>, isAdmin = <%u>"), WsbHrAsString(hr), *pIsAdmin);
return(hr);
}
HRESULT
CFsaFilterClient::GetLastRecallTime(
OUT FILETIME* pTime
)
/*++
Implements:
IFsaFilterClient::GetLastRecallTime().
--*/
{
HRESULT hr = S_OK;
try {
WsbAssert(0 != pTime, E_POINTER);
*pTime = m_lastRecallTime;
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaFilterClient::GetMachineName(
OUT OLECHAR** pName,
IN ULONG bufferSize
)
/*++
Implements:
IFsaFilterClient::GetMachineName().
--*/
{
HRESULT hr = S_OK;
try {
WsbAssert(0 != pName, E_POINTER);
WsbAffirmHr(m_machineName.CopyTo(pName, bufferSize));
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaFilterClient::GetRecallCount(
OUT ULONG* pCount
)
/*++
Implements:
IFsaFilterClient::GetRecallCount().
--*/
{
HRESULT hr = S_OK;
try {
WsbAssert(0 != pCount, E_POINTER);
*pCount = m_recallCount;
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaFilterClient::GetUserName(
OUT OLECHAR** pName,
IN ULONG bufferSize
)
/*++
Implements:
IFsaFilterClient::GetUserName().
--*/
{
HRESULT hr = S_OK;
try {
WsbAssert(0 != pName, E_POINTER);
WsbAffirmHr(m_userName.CopyTo(pName, bufferSize));
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaFilterClient::GetSizeMax(
OUT ULARGE_INTEGER* pSize
)
/*++
Implements:
IPersistStream::GetSizeMax().
--*/
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CFsaFilterClient::GetSizeMax"), OLESTR(""));
try {
WsbAssert(0 != pSize, E_POINTER);
pSize->QuadPart = 0;
// WE don't need to persist these.
hr = E_NOTIMPL;
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaFilterClient::GetSizeMax"), OLESTR("hr = <%ls>, Size = <%ls>"), WsbHrAsString(hr), WsbPtrToUliAsString(pSize));
return(hr);
}
HRESULT
CFsaFilterClient::HasRecallDisabled(
void
)
/*++
Implements:
IFsaFilterClient::HasRecallDisabled().
--*/
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CFsaFilterClient::HasRecallDisabled"), OLESTR(""));
if (!m_hasRecallDisabled) {
hr = S_FALSE;
}
WsbTraceOut(OLESTR("CHsmFilterClient::HasRecallDisabled"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return(hr);
}
HRESULT
CFsaFilterClient::HitRecallLimit(
void
)
/*++
Implements:
IFsaFilterClient::HitRecallLimit().
--*/
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CFsaFilterClient::HitRecallLimit"), OLESTR(""));
if (!m_hitRecallLimit) {
hr = S_FALSE;
}
WsbTraceOut(OLESTR("CHsmFilterClient::HitRecallLimit"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return(hr);
}
HRESULT
CFsaFilterClient::IdentifyThread(
void
)
/*++
Implements:
CFsaFilterClient::IdentifyThread().
Notes:
Unlike recall start/stop messages that were moved to RsLnk.exe (bugs 570471, 571109),
the identification is still being done from RsServ for the following reasons:
1) There is only one IdentifyThread - moving this thread to RsLnk solves nothing
2) The notification process actally needs to know whether an identification is taking
place, so it could delay the notification (wait for the thread to be done).
--*/
{
#define WSB_BUFF_SIZE 1024
HRESULT hr = S_OK;
BOOL done, guestUser, noUser;
DWORD res, totalEnt, numEnt;
UCHAR *buff = NULL;
NET_API_STATUS status;
SESSION_INFO_1 *sess;
CWsbStringPtr pipePath;
ULONG holdOff = 0;
#ifdef MAC_SUPPORT
LPBYTE macBuff = NULL;
PAFP_SESSION_INFO macInfo;
AFP_SERVER_HANDLE macHandle = 0;
DWORD macResume = 0;
DWORD macTotalEntries, macTotalRead;
DWORD result;
#endif
WsbTraceIn(OLESTR("CFsaFilterClient::IdentifyThread"), OLESTR(""));
try {
WsbTrace(OLESTR("CFsaFilterClient::IdentifyThread Flag: %x Client ID: %x:%x Source: %ls\n"),
m_identified, m_luidHigh, m_luidLow, (WCHAR *) m_tokenSource);
//
// If already identified then we bail out here.
//
WsbAffirm(m_identified == FALSE, S_OK);
done = FALSE;
res = 0;
noUser = FALSE;
if (_wcsicmp(m_userName, L"GUEST") == 0) {
/* It is the guest user - find all sessions and
send to ones marked guest */
guestUser = TRUE;
} else {
guestUser = FALSE;
if (wcslen(m_userName) == 0) {
noUser = TRUE;
}
}
CComPtr<IFsaRecallNotifyClient> pRecallClient;
WsbAffirmHr(WsbGetComputerName( pipePath ));
WsbAffirmHr(pipePath.Prepend("\\\\"));
WsbAffirmHr(pipePath.Append("\\pipe\\"));
WsbAffirmHr(pipePath.Append(WSB_PIPE_NAME));
while ( done == FALSE ) {
if ( (guestUser == FALSE) && (noUser == FALSE) ) {
// If NetSessionEnum fails, try calling again for all users
status = NetSessionEnum(NULL, NULL, m_userName, 1, &buff,
WSB_BUFF_SIZE, &numEnt, &totalEnt, &res);
if (status != 0) {
status = NetSessionEnum(NULL, NULL, NULL, 1, &buff,
WSB_BUFF_SIZE, &numEnt, &totalEnt, &res);
}
} else {
status = NetSessionEnum( NULL, NULL, NULL, 1, &buff,
WSB_BUFF_SIZE, &numEnt, &totalEnt, &res );
}
if ((status == NERR_Success) || (status == ERROR_MORE_DATA)) {
WsbTrace(OLESTR("CHsmFilterClient::IdentifyThread: NetSessionEnum output: Total entries=%ls , Read entries=%ls \n"),
WsbLongAsString(totalEnt), WsbLongAsString(numEnt));
if (status != ERROR_MORE_DATA) {
done = TRUE;
}
sess = (SESSION_INFO_1 *) buff;
while ( numEnt != 0 ) {
//
// If the request was made from the user GUEST then
// we enumerate all sessions and send the
// identification request to all the machines with
// sessions marked as GUEST. This is because the
// session may have some other user name but the
// request could still have GUEST access.
//
if (((guestUser) && (sess->sesi1_user_flags & SESS_GUEST)) ||
(!guestUser)) {
//
// Send the identify request message
//
WsbTrace(OLESTR("CFsaFilterClient::IdentifyThread - Sending identify request to %ls (local machine = %ls)\n"),
sess->sesi1_cname, (WCHAR *) pipePath);
hr = GetNotifyClientInterface ( sess->sesi1_cname, &pRecallClient );
if ( SUCCEEDED ( hr ) ) {
hr = pRecallClient->IdentifyWithServer( pipePath );
if (hr != S_OK) {
WsbTrace(OLESTR("CFsaFilterClient::IdentifyThread - error Identifing (%ls)\n"),
WsbHrAsString(hr));
}
} else {
WsbTrace(OLESTR("CFsaFilterClient::IdentifyThread - error getting notify client interface hr = %ls (%x)\n"),
WsbHrAsString( hr ), hr);
}
hr = S_OK;
pRecallClient.Release ( );
}
sess++;
numEnt--;
}
NetApiBufferFree(buff);
buff = NULL;
} else {
done = TRUE;
}
}
#ifdef MAC_SUPPORT
//
// Done with LAN manager scan, now do a MAC scan.
//
if ( (FsaMacSupportInstalled) && ((pAfpAdminConnect)(NULL, &macHandle) == NO_ERROR) ) {
//
// We have connected to the MAC service - do a session enumeration
//
macResume = 0;
done = FALSE;
while (done == FALSE) {
result = (pAfpAdminSessionEnum)(macHandle, &macBuff, -1,
&macTotalRead, &macTotalEntries, &macResume);
if ((result == NO_ERROR) || (result == ERROR_MORE_DATA)) {
//
// Read some entries - send the message to each one
//
if (macTotalRead == macTotalEntries) {
done = TRUE;
}
macInfo = (PAFP_SESSION_INFO) macBuff;
while ( macTotalRead != 0 ) {
//
// Send to each matching user
//
if ( ( NULL != macInfo->afpsess_ws_name ) &&
( _wcsicmp(m_userName, macInfo->afpsess_username ) == 0 ) ) {
WsbTrace(OLESTR("CHsmFilterClient::IdentifyThread: Send Identify to MAC %ls.\n"),
macInfo->afpsess_ws_name);
//
// Send the identify request message
//
hr = GetNotifyClientInterface ( sess->sesi1_cname, &pRecallClient );
if ( SUCCEEDED ( hr ) ) {
pRecallClient->IdentifyWithServer ( pipePath );
}
hr = S_OK;
pRecallClient.Release ( );
}
macInfo++;
macTotalRead--;
}
(pAfpAdminBufferFree)(macBuff);
macBuff = NULL;
} else {
done = TRUE;
}
(pAfpAdminDisconnect)(macHandle);
macHandle = 0;
}
}
#endif
} WsbCatch(hr);
if (buff != NULL) {
NetApiBufferFree(buff);
}
#ifdef MAC_SUPPORT
if (FsaMacSupportInstalled) {
if (macBuff != NULL) {
(pAfpAdminBufferFree)(macBuff);
}
if (macHandle != 0) {
(pAfpAdminDisconnect)(macHandle);
}
}
#endif
WsbTraceOut(OLESTR("CFsaFilterClient::IdentifyThread"), OLESTR("hr = %ls"), WsbHrAsString(hr));
return(hr);
}
HRESULT
CFsaFilterClient::Load(
IN IStream* pStream
)
/*++
Implements:
IPersistStream::Load().
--*/
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CFsaFilterClient::Load"), OLESTR(""));
try {
WsbAssert(0 != pStream, E_POINTER);
// No persistence.
hr = E_NOTIMPL;
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaFilterClient::Load"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return(hr);
}
HRESULT
CFsaFilterClient::Save(
IN IStream* pStream,
IN BOOL clearDirty
)
/*++
Implements:
IPersistStream::Save().
--*/
{
HRESULT hr = S_OK;
CComPtr<IPersistStream> pPersistStream;
WsbTraceIn(OLESTR("CFsaFilterClient::Save"), OLESTR("clearDirty = <%ls>"), WsbBoolAsString(clearDirty));
try {
WsbAssert(0 != pStream, E_POINTER);
// No persistence.
hr = E_NOTIMPL;
// If we got it saved and we were asked to clear the dirty bit, then
// do so now.
if (clearDirty) {
m_isDirty = FALSE;
}
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaFilterClient::Save"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return(hr);
}
HRESULT
CFsaFilterClient::SendRecallInfo(
IFsaFilterRecall *pRecall,
BOOL starting,
HRESULT rHr
)
/*++
Implements:
CFsaFilterClient::SendRecallInfo
--*/
{
HRESULT hr = E_FAIL;
WsbTraceIn(OLESTR("CFsaFilterClient::SendRecallInfo"), OLESTR(""));
if( ! m_identified && ( m_identifyThread != NULL ) ) {
//
// Wait for up to 10 seconds for identify thread to complete if
// Client not yet identified
// Note that after fix to 570399, once the thread is created, the handle will only be valid
// (till the object is destructed), only that if the thread is not running, the handle would
// be signaled and the wait will finish immediately
//
WaitForSingleObject( m_identifyThread, 10000 );
}
//
// Let the client know that the recall is starting or is finished
//
if ( m_identified ) {
try {
WsbTrace(OLESTR("CFsaFilterClient::SendRecallInfo - Client (%ls) is being notified of recall status (starting = %u hr = %x).\n"),
(WCHAR *) m_machineName, starting, rHr);
//
// Create intermediate server object which will be the client's
// connection back to the service. This object acts as a middle
// man to overcome the admin-only access into the FSA service.
//
CComPtr<IFsaRecallNotifyServer> pRecallServer;
WsbAffirmHr(CoCreateInstance(CLSID_CFsaRecallNotifyServer, 0, CLSCTX_NO_FAILURE_LOG | CLSCTX_ALL, IID_IFsaRecallNotifyServer, (void**)&pRecallServer));
WsbAffirmHr(pRecallServer->Init(pRecall));
//
// Use same object (different interface) to send the notifications
// (bugs 570471, 571109)
//
CComPtr<IFsaRecallNotifySend> pRecallNotify;
WsbAffirmHr(pRecallServer->QueryInterface(IID_IFsaRecallNotifySend, (void**)&pRecallNotify));
CComPtr<IFsaRecallNotifyClient> pRecallClient;
hr = pRecallNotify->SendNotification(m_machineName, starting, rHr);
if (hr != S_OK) {
WsbTrace(OLESTR("CFsaFilterClient::SendRecallInfo - failed in SendNotification (%ls)\n"),
WsbHrAsString(hr));
}
} WsbCatch(hr);
}
WsbTraceOut(OLESTR("CFsaFilterClient::SendRecallInfo"), OLESTR("hr = %ls"), WsbHrAsString(hr));
return(hr);
}
HRESULT
CFsaFilterClient::SetAuthenticationId(
IN LONG luidHigh,
IN ULONG luidLow
)
/*++
Implements:
IFsaFilterClient::SetAuthenticationId().
--*/
{
m_luidHigh = luidHigh;
m_luidLow = luidLow;
return(S_OK);
}
HRESULT
CFsaFilterClient::SetDomainName(
IN OLECHAR* name
)
/*++
Implements:
IFsaFilterClient::SetDomainName().
--*/
{
HRESULT hr = S_OK;
try {
m_domainName = name;
WsbAssert(m_domainName != 0, E_UNEXPECTED);
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaFilterClient::SetIsAdmin(
IN BOOLEAN isAdmin
)
/*++
Implements:
IFsaFilterClient::SetIsAdmin().
--*/
{
m_isAdmin = isAdmin;
return(S_OK);
}
HRESULT
CFsaFilterClient::SetLastRecallTime(
IN FILETIME time
)
/*++
Implements:
IFsaFilterClient::SetLastRecallTime().
--*/
{
m_lastRecallTime = time;
return(S_OK);
}
HRESULT
CFsaFilterClient::SetMachineName(
IN OLECHAR* name
)
/*++
Implements:
IFsaFilterClient::SetMachineName().
--*/
{
HRESULT hr = S_OK;
try {
WsbAssert(name != 0, E_UNEXPECTED);
m_machineName = name;
m_identified = TRUE;
WsbTrace(OLESTR("CFsaFilterClient::SetMachineName Flag: %x Client ID: %x:%x Source: %ls == %ls\n"),
m_identified, m_luidLow, m_luidHigh, (WCHAR *) m_tokenSource, (WCHAR *) m_machineName);
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaFilterClient::SetRecallCount(
IN ULONG count
)
/*++
Implements:
IFsaFilterClient::SetRecallCount().
--*/
{
m_recallCount = count;
return(S_OK);
}
HRESULT
CFsaFilterClient::SetUserName(
IN OLECHAR* name
)
/*++
Implements:
IFsaFilterClient::SetUserName().
--*/
{
HRESULT hr = S_OK;
try {
m_userName = _wcsupr(name);
WsbAssert(m_userName != 0, E_UNEXPECTED);
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaFilterClient::SetHasRecallDisabled(
IN BOOL hasBeen
)
/*++
Implements:
IFsaFilterClient::SetHasRecallDisabled().
--*/
{
m_hasRecallDisabled = hasBeen;
return(S_OK);
}
HRESULT
CFsaFilterClient::SetHitRecallLimit(
IN BOOL hasBeen
)
/*++
Implements:
IFsaFilterClient::SetHitRecallLimit().
--*/
{
m_hitRecallLimit = hasBeen;
return(S_OK);
}
HRESULT
CFsaFilterClient::SetTokenSource(
IN CHAR *source
)
/*++
Implements:
IFsaFilterClient::SetTokenSource()
--*/
{
OLECHAR tSource[TOKEN_SOURCE_LENGTH + 1];
memset (tSource, 0, sizeof (tSource));
if (-1 == mbstowcs((WCHAR *) tSource, source, TOKEN_SOURCE_LENGTH)) {
return E_INVALIDARG;
}
m_tokenSource = tSource;
return(S_OK);
}
HRESULT
CFsaFilterClient::StartIdentify(
void
)
/*++
Implements:
CFsaFilterClient::StartIdentify().
--*/
{
#define WSB_BUFF_SIZE 1024
HRESULT hr = S_OK;
DWORD tid;
WsbTraceIn(OLESTR("CFsaFilterClient::StartIdentify"), OLESTR(""));
try {
WsbTrace(OLESTR("CFsaFilterClient::StartIdentify Flag: %x Client ID: %x:%x Source: %ls\n"),
m_identified, m_luidHigh, m_luidLow, (WCHAR *) m_tokenSource);
//
// If already identified then we bail out here.
//
WsbAffirm(m_identified == FALSE, S_OK);
//
// If the request is from User32 then it is local
//
if (_wcsicmp(m_tokenSource, L"User32") == 0) {
//
// Identified as the local machine.
// Set the name and bail out with S_OK
//
WsbAffirmHr(WsbGetComputerName( m_machineName ));
m_identified = TRUE;
WsbTrace(OLESTR("CHsmFilterClient::StartIdentify: Identified as %ls.\n"),
(WCHAR *) m_machineName);
WsbThrow( S_OK );
} else {
//
// This code assumes that only one thread (IoctlThread) can execute
// (otherwise, it should be protected by a CS)
//
// Start the identification thread (if one is not running yet)
//
DWORD dwWaitStatus = 0;
if ( (NULL == m_identifyThread) ||
((dwWaitStatus = WaitForSingleObject(m_identifyThread, 0)) == WAIT_OBJECT_0) ) {
// Thread is not running
WsbTrace(OLESTR("CHsmFilterClient::StartIdentify: Starting ID thread.\n"));
HANDLE hTempThread = NULL;
WsbAffirm((hTempThread = CreateThread(0, 0, FsaIdentifyThread, (void*) this, 0, &tid)) != 0, HRESULT_FROM_WIN32(GetLastError()));
if (hTempThread == NULL) {
WsbAssertHr(E_FAIL);
}
HANDLE hPrevThread = (HANDLE)InterlockedExchangePointer(&(void *)m_identifyThread, (void *)hTempThread);
if (hPrevThread != NULL) {
CloseHandle(hPrevThread);
}
} else {
WsbTrace(OLESTR("CFsaFilterClient::StartIdentify: thread is null or waut failed. thread=%p wait=%lu err=%lu\n"),
(void *)m_identifyThread, dwWaitStatus, GetLastError());
}
}
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaFilterClient::StartIdentify"), OLESTR("hr = %ls"), WsbHrAsString(hr));
return(hr);
}
HRESULT
CFsaFilterClient::Test(
USHORT* passed,
USHORT* failed
)
/*++
Implements:
IWsbTestable::Test().
--*/
{
HRESULT hr = S_OK;
try {
WsbAssert(0 != passed, E_POINTER);
WsbAssert(0 != failed, E_POINTER);
*passed = 0;
*failed = 0;
} WsbCatch(hr);
return(hr);
}