/*++ (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 #include #include #include #include #include #include // #define MAC_SUPPORT // NOTE: You must define MAC_SUPPORT in fsafltr.cpp to enable all the code #ifdef MAC_SUPPORT #include #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); } 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 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 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 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; } 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("")); 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(). --*/ { #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 pRecallClient; 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 CloseHandle(m_identifyThread); m_identifyThread = NULL; 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 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; if( ! m_identified && ( m_identifyThread != NULL ) ) { // // Wait for up to 10 seconds for identify thread to complete if // Client not yet identified // WaitForMultipleObjects( 1, &m_identifyThread, FALSE, 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 pRecallServer; WsbAffirmHr(CoCreateInstance(CLSID_CFsaRecallNotifyServer, 0, CLSCTX_NO_FAILURE_LOG | CLSCTX_ALL, IID_IFsaRecallNotifyServer, (void**)&pRecallServer)); WsbAffirmHr(pRecallServer->Init(pRecall)); CComPtr pRecallClient; hr = GetNotifyClientInterface ( m_machineName, &pRecallClient ); if ( SUCCEEDED( hr ) ) { if (starting) { hr = pRecallClient->OnRecallStarted ( pRecallServer ); } else { hr = pRecallClient->OnRecallFinished ( pRecallServer, rHr ); } if (hr != S_OK) { WsbTrace(OLESTR("CFsaFilterClient::SendRecallInfo - Got the interface but failed in OnRecall... (%ls)\n"), WsbHrAsString(hr)); } } else { WsbTrace(OLESTR("CFsaFilterClient::SendRecallInfo - error getting notify client interface hr = %ls (%x)\n"), WsbHrAsString( hr ), hr); } } WsbCatchAndDo(hr, WsbTrace(OLESTR("CFsaFilterClient::SendRecallInfo - hr = %ls\n"), 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]; mbstowcs((WCHAR *) tSource, source, TOKEN_SOURCE_LENGTH); 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 // WsbGetComputerName( m_machineName ); m_identified = TRUE; WsbTrace(OLESTR("CHsmFilterClient::StartIdentify: Identified as %ls.\n"), (WCHAR *) m_machineName); WsbThrow( S_OK ); } else { // // Start the identification thread // if (NULL == m_identifyThread) { WsbTrace(OLESTR("CHsmFilterClient::StartIdentify: Starting ID thread.\n")); WsbAffirm((m_identifyThread = CreateThread(0, 0, FsaIdentifyThread, (void*) this, 0, &tid)) != 0, HRESULT_FROM_WIN32(GetLastError())); if (m_identifyThread == NULL) { WsbAssertHr(E_FAIL); // TBD What error to return here?? } } } } 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); }