/*++ (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); } // // 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 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; 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 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 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 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 pRecallNotify; WsbAffirmHr(pRecallServer->QueryInterface(IID_IFsaRecallNotifySend, (void**)&pRecallNotify)); CComPtr 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); }