/****************************************************************** DfsReplica.CPP -- WMI provider class implementation Copyright (c) 2000-2001 Microsoft Corporation, All Rights Reserved DESCRIPTION DFS Provider ******************************************************************/ #include "precomp.h" #include CDfsReplica MyCDFSReplicaSet ( PROVIDER_NAME_DFSREPLICA , Namespace ) ; /***************************************************************************** * * FUNCTION : CDfsReplica::CDfsReplica * * DESCRIPTION : Constructor * *****************************************************************************/ CDfsReplica :: CDfsReplica ( LPCWSTR lpwszName, LPCWSTR lpwszNameSpace ) : Provider ( lpwszName , lpwszNameSpace ) { m_ComputerName = GetLocalComputerName(); } /***************************************************************************** * * FUNCTION : CDfsReplica::~CDfsReplica * * DESCRIPTION : Destructor * *****************************************************************************/ CDfsReplica :: ~CDfsReplica () { } /***************************************************************************** * * FUNCTION : CDfsReplica::EnumerateInstances * * DESCRIPTION : Returns all the instances of this class. * *****************************************************************************/ HRESULT CDfsReplica :: EnumerateInstances ( MethodContext *pMethodContext, long lFlags ) { HRESULT hRes = WBEM_S_NO_ERROR ; DWORD dwPropertiesReq = DFSREPLICA_ALL_PROPS; hRes = EnumerateAllReplicas ( pMethodContext, dwPropertiesReq ); return hRes ; } /***************************************************************************** * * FUNCTION : CDfsReplica::GetObject * * DESCRIPTION : Find a single instance based on the key properties for the * class. * *****************************************************************************/ HRESULT CDfsReplica :: GetObject ( CInstance *pInstance, long lFlags, CFrameworkQuery& Query ) { HRESULT hRes = WBEM_S_NO_ERROR; DWORD dwPropertiesReq = 0; CHString t_Link ; CHString t_Server; CHString t_Share; hRes = GetKeys(pInstance, t_Link, t_Server, t_Share); if ( SUCCEEDED ( hRes ) ) { if ( Query.AllPropertiesAreRequired() ) { dwPropertiesReq = DFSREPLICA_ALL_PROPS; } else { if ( Query.IsPropertyRequired ( LINKNAME ) ) { dwPropertiesReq |= DFSREPLICA_PROP_LinkName; } if ( Query.IsPropertyRequired ( SERVERNAME ) ) { dwPropertiesReq |= DFSREPLICA_PROP_ServerName; } if ( Query.IsPropertyRequired ( SHARENAME ) ) { dwPropertiesReq |= DFSREPLICA_PROP_ShareName; } if ( Query.IsPropertyRequired ( STATE ) ) { dwPropertiesReq |= DFSREPLICA_PROP_State; } } bool bRoot = false; hRes = FindAndSetDfsReplica ( t_Link, t_Server, t_Share, dwPropertiesReq, pInstance, eGet, bRoot ); } return hRes ; } /***************************************************************************** * * FUNCTION : CDfsReplica::PutInstance * * DESCRIPTION : PutInstance should be used in provider classes that can * write instance information back to the hardware or * software. For example: Win32_Environment will allow a * PutInstance to create or update an environment variable. * However, a class like MotherboardDevice will not allow * editing of the number of slots, since it is difficult for * a provider to affect that number. * *****************************************************************************/ HRESULT CDfsReplica :: PutInstance ( const CInstance &Instance, long lFlags ) { HRESULT hRes = WBEM_S_NO_ERROR; DWORD dwPropertiesReq = 0; CHString t_Link ; CHString t_Server; CHString t_Share; bool bRoot = false; // Get the Compound Key hRes = GetKeys(&Instance, t_Link, t_Server, t_Share); if ( SUCCEEDED ( hRes ) ) { hRes = FindAndSetDfsReplica ( t_Link, t_Server, t_Share, dwPropertiesReq, NULL, eAdd, bRoot ); } bool bFound; if (SUCCEEDED(hRes)) { bFound = true; } else if (hRes == WBEM_E_NOT_FOUND) { bFound = false; hRes = WBEM_S_NO_ERROR; } if (SUCCEEDED(hRes)) { DWORD dwOperationsReq = (WBEM_FLAG_CREATE_OR_UPDATE | WBEM_FLAG_CREATE_ONLY | WBEM_FLAG_UPDATE_ONLY); switch ( lFlags & dwOperationsReq ) { case WBEM_FLAG_CREATE_OR_UPDATE: { if (bFound) { hRes = WBEM_E_INVALID_PARAMETER; } else { if (NetDfsAdd ( t_Link.GetBuffer ( 0 ), t_Server.GetBuffer ( 0 ), t_Share.GetBuffer ( 0 ), L"", 0 ) == NERR_Success) { hRes = WBEM_S_NO_ERROR; } else { hRes = WBEM_E_FAILED; } } break; } case WBEM_FLAG_CREATE_ONLY: { if (!bFound) { if (NetDfsAdd ( t_Link.GetBuffer ( 0 ), t_Server.GetBuffer ( 0 ), t_Share.GetBuffer ( 0 ), L"", 0 ) == NERR_Success) { hRes = WBEM_S_NO_ERROR; } else { hRes = WBEM_E_FAILED; } } else { hRes = WBEM_E_ALREADY_EXISTS; } break; } default: { hRes = WBEM_E_INVALID_PARAMETER; } } } return hRes ; } /***************************************************************************** * * FUNCTION : CDfsReplica::DeleteInstance * * DESCRIPTION : DeleteInstance, like PutInstance, actually writes information * to the software or hardware. For most hardware devices, * DeleteInstance should not be implemented, but for software * configuration, DeleteInstance implementation is plausible. * *****************************************************************************/ HRESULT CDfsReplica :: DeleteInstance ( const CInstance &Instance, long lFlags ) { HRESULT hRes = WBEM_S_NO_ERROR; DWORD dwPropertiesReq = 0; CHString t_Link ; CHString t_Server; CHString t_Share; bool bRoot = false; // Get the Compound Key hRes = GetKeys(&Instance, t_Link, t_Server, t_Share); if ( SUCCEEDED ( hRes ) ) { hRes = FindAndSetDfsReplica ( t_Link, t_Server, t_Share, dwPropertiesReq, NULL, eDelete, bRoot ); } if ( SUCCEEDED ( hRes ) ) { NET_API_STATUS t_Status = NERR_Success; if (!bRoot) { t_Status = NetDfsRemove( t_Link.GetBuffer(0), t_Server.GetBuffer(0), t_Share.GetBuffer(0) ); if ( t_Status != NERR_Success ) { hRes = WBEM_E_FAILED; } } else { wchar_t *pEntryPath = t_Link.GetBuffer(0); if ((wcslen(pEntryPath) > 4) && (pEntryPath[0] == pEntryPath[1]) && (pEntryPath[0] == L'\\')) { wchar_t *pSlash = wcschr(&(pEntryPath[2]), L'\\'); if (pSlash > &(pEntryPath[2])) { wchar_t *pServer = new wchar_t[pSlash - &(pEntryPath[2]) + 1]; BOOL bRemove = FALSE; try { wcsncpy(pServer, &(pEntryPath[2]), pSlash - &(pEntryPath[2])); pServer[pSlash - &(pEntryPath[2])] = L'\0'; if (0 == m_ComputerName.CompareNoCase(pServer)) { bRemove = TRUE; } else { DWORD dwDnsName = 256; DWORD dwDnsNameSize = 256; wchar_t *pDnsName = new wchar_t[dwDnsName]; try { while (!ProviderGetComputerNameEx(ComputerNamePhysicalDnsHostname, pDnsName, &dwDnsName)) { if (GetLastError() != ERROR_MORE_DATA) { delete [] pDnsName; pDnsName = NULL; break; } else { delete [] pDnsName; pDnsName = NULL; dwDnsName = dwDnsNameSize * 2; dwDnsNameSize = dwDnsName; pDnsName = new wchar_t[dwDnsName]; } } } catch (...) { if (pDnsName) { delete [] pDnsName; pDnsName = NULL; } throw; } if (pDnsName) { if (_wcsicmp(pDnsName, pServer) == 0) { bRemove = TRUE; } delete [] pDnsName; pDnsName = NULL; } } } catch(...) { if (pServer) { delete [] pServer; } throw; } if (bRemove) { t_Status = NetDfsRemoveStdRoot( t_Server.GetBuffer(0), t_Share.GetBuffer(0), 0 ); if ( t_Status != NERR_Success ) { hRes = WBEM_E_FAILED; } } else { //can't delete roots not on this machine hRes = WBEM_E_PROVIDER_NOT_CAPABLE; } delete [] pServer; } else { hRes = WBEM_E_FAILED; } } else { hRes = WBEM_E_FAILED; } } } return hRes ; } /***************************************************************************** * * FUNCTION : CDfsReplica::EnumerateAllReplicas * * DESCRIPTION : Enumerates all the Dfs Replicas of all junction points * ******************************************************************************/ HRESULT CDfsReplica::EnumerateAllReplicas ( MethodContext *pMethodContext, DWORD dwPropertiesReq ) { HRESULT hRes = WBEM_S_NO_ERROR; BOOL bLoadReplicaFailure = FALSE; PDFS_STORAGE_INFO pRepBuf; PDFS_INFO_300 pData300 = NULL; DWORD er300 = 0; DWORD tr300 = 0; // Call the NetDfsEnum function, specifying level 300. DWORD res = NetDfsEnum( m_ComputerName.GetBuffer ( 0 ), 300, -1, (LPBYTE *) &pData300, &er300, &tr300 ); // If no error occurred, if(res==NERR_Success) { if ( pData300 != NULL ) { try { PDFS_INFO_300 p300 = pData300; CInstancePtr pInstance; for ( int i = 0; (i < er300) && SUCCEEDED( hRes ); i++, p300++ ) { DWORD er4 = 0; DWORD tr4 = 0; PDFS_INFO_4 pData4 = NULL; if (p300->DfsName != NULL) { if ( ( res = NetDfsEnum(p300->DfsName, 4, -1, (LPBYTE *) &pData4, &er4, &tr4) ) == NERR_Success) { if ( pData4 != NULL ) { try { PDFS_INFO_4 p4 = pData4; for ( int ii = 0; (ii < er4) && SUCCEEDED ( hRes ); ii++, p4++ ) { // Walk all the replicas on each link pRepBuf = p4->Storage; for ( int j = 0; j < p4->NumberOfStorages; j++, pRepBuf++ ) { pInstance.Attach(CreateNewInstance( pMethodContext )); hRes = LoadDfsReplica ( dwPropertiesReq, pInstance, p4->EntryPath, pRepBuf ); if ( SUCCEEDED ( hRes ) ) { hRes = pInstance->Commit(); } else { bLoadReplicaFailure = TRUE; } } } } catch(...) { NetApiBufferFree(pData4); pData4 = NULL; throw; } NetApiBufferFree(pData4); pData4 = NULL; } } // Check to see if there are ANY roots else if ( (res != ERROR_NO_MORE_ITEMS) && (res != ERROR_NO_SUCH_DOMAIN) && (res != ERROR_NOT_FOUND) && (res != ERROR_ACCESS_DENIED) ) { hRes = WBEM_E_FAILED; } } } } catch ( ... ) { NetApiBufferFree(pData300); pData300 = NULL; throw; } NetApiBufferFree(pData300); pData300 = NULL; } } else { if ( (res != ERROR_NO_MORE_ITEMS) && (res != ERROR_NO_SUCH_DOMAIN) && (res != ERROR_NOT_FOUND) ) // Check to see if there are ANY roots { if ( ERROR_ACCESS_DENIED == res ) { hRes = WBEM_E_ACCESS_DENIED ; } else { hRes = WBEM_E_FAILED ; } } // No replicas else if (res == ERROR_NO_MORE_ITEMS) { hRes = WBEM_S_NO_ERROR; } } if ( bLoadReplicaFailure ) { hRes = WBEM_E_PROVIDER_FAILURE; } return hRes; } /***************************************************************************** * * FUNCTION : CDfsReplica::FindAndSetDfsReplica * * DESCRIPTION : Finds an entry matching the dfsEntryPath and loads the * Instance if found or acts based on the Operation passed * ******************************************************************************/ HRESULT CDfsReplica::FindAndSetDfsReplica ( LPCWSTR a_EntryPath, LPCWSTR a_ServerName, LPCWSTR a_ShareName, DWORD dwPropertiesReq, CInstance *pInstance, DWORD eOperation, bool &bRoot ) { PDFS_STORAGE_INFO pRepBuf; HRESULT hRes = WBEM_E_NOT_FOUND; PDFS_INFO_300 pData300 = NULL; DWORD er300 = 0; DWORD tr300 = 0; DWORD res = NERR_Success; // Call the NetDfsEnum function, specifying level 300. if( ( res = NetDfsEnum( m_ComputerName.GetBuffer ( 0 ), 300, -1, (LPBYTE *) &pData300, &er300, &tr300 ) ) == NERR_Success ) { if ( pData300 != NULL ) { try { BOOL bContinue = TRUE; PDFS_INFO_300 p300 = pData300; for ( int i = 0; (i < er300) && bContinue; i++, p300++ ) { if ( p300->DfsName != NULL ) { PDFS_INFO_4 pData4 = NULL; DWORD er4=0; DWORD tr4=0; if ( ( res = NetDfsEnum(p300->DfsName, 4, -1, (LPBYTE *) &pData4, &er4, &tr4) ) == NERR_Success ) { if ( pData4 != NULL ) { try { BOOL bFound = FALSE; PDFS_INFO_4 p4 = pData4; for ( int jj = 0; (jj < er4) && bContinue; jj++, bContinue && (jj < er4) ? p4++ : p4 ) { if ( _wcsicmp ( a_EntryPath, p4->EntryPath ) == 0 ) { bFound = TRUE; bContinue = FALSE; } } if ( bFound ) { bFound = FALSE; bContinue = TRUE; pRepBuf = p4->Storage; for ( int j = 0; j < p4->NumberOfStorages && bContinue; j++, bContinue && (j < p4->NumberOfStorages) ? pRepBuf++ : pRepBuf ) { if ( ( _wcsicmp(a_ServerName, pRepBuf->ServerName ) == 0 ) && ( _wcsicmp(a_ShareName, pRepBuf->ShareName ) == 0 ) ) { bFound = TRUE; bRoot = (pData4 == p4); bContinue = FALSE; } } if ( bFound ) { switch ( eOperation ) { case eGet : { hRes = LoadDfsReplica ( dwPropertiesReq, pInstance, p4->EntryPath, pRepBuf ); break; } case eDelete: { hRes = WBEM_S_NO_ERROR; break; } case eAdd: { hRes = WBEM_S_NO_ERROR; break; } } } else { // we didn't find replica bContinue = FALSE; } } } catch(...) { NetApiBufferFree(pData4); pData4 = NULL; throw; } NetApiBufferFree(pData4); pData4 = NULL; } } // Check to see if there are ANY roots else if ( (res != ERROR_NO_MORE_ITEMS) && (res != ERROR_NO_SUCH_DOMAIN) && (res != ERROR_NOT_FOUND) && (res != ERROR_ACCESS_DENIED) ) { hRes = WBEM_E_FAILED; bContinue = FALSE; } } } } catch ( ... ) { NetApiBufferFree(pData300); pData300 = NULL; throw; } NetApiBufferFree(pData300); pData300 = NULL; } } else if ( (res != ERROR_NO_MORE_ITEMS) && (res != ERROR_NO_SUCH_DOMAIN) && (res != ERROR_NOT_FOUND) ) // Check to see if there are ANY roots { if ( ERROR_ACCESS_DENIED == res ) { hRes = WBEM_E_ACCESS_DENIED ; } else { hRes = WBEM_E_FAILED ; } } return hRes; } /***************************************************************************** * * FUNCTION : CDfsReplica::LoadDfsReplica * * DESCRIPTION : Loads a Dfs Replica into the instance * ******************************************************************************/ HRESULT CDfsReplica::LoadDfsReplica ( DWORD dwPropertiesReq, CInstance *pInstance, LPWSTR lpLinkName, PDFS_STORAGE_INFO pRepBuf ) { HRESULT hRes = WBEM_S_NO_ERROR; if ( dwPropertiesReq & DFSREPLICA_PROP_LinkName ) { if ( pInstance->SetCHString ( LINKNAME, lpLinkName ) == FALSE ) { hRes = WBEM_E_FAILED; } } if ( dwPropertiesReq & DFSREPLICA_PROP_ServerName ) { if ( pInstance->SetCHString ( SERVERNAME, pRepBuf->ServerName ) == FALSE ) { hRes = WBEM_E_FAILED; } } if ( dwPropertiesReq & DFSREPLICA_PROP_ShareName ) { if ( pInstance->SetCHString ( SHARENAME, pRepBuf->ShareName ) == FALSE ) { hRes = WBEM_E_FAILED; } } if ( dwPropertiesReq & DFSREPLICA_PROP_State ) { // need to check the state and then valuemap DWORD dwState = 0xffff; switch ( pRepBuf->State ) { case DFS_STORAGE_STATE_OFFLINE : { dwState = 0; break; } case DFS_STORAGE_STATE_ONLINE : { dwState = 1; break; } case DFS_STORAGE_STATE_ACTIVE : { dwState = 2; break; } } if ( !pInstance->SetDWORD ( STATE, dwState ) ) { hRes = WBEM_E_FAILED; } } return hRes; } /***************************************************************************** * * FUNCTION : CDfsReplica::GetKeys * * DESCRIPTION : Get the multi part key * *****************************************************************************/ HRESULT CDfsReplica::GetKeys(const CInstance *pInstance, CHString &sLink, CHString &sServer, CHString &sShare) { HRESULT hRes = WBEM_S_NO_ERROR; // Get the Compound Key if ( !pInstance->GetCHString ( LINKNAME , sLink ) || !pInstance->GetCHString ( SERVERNAME , sServer ) || !pInstance->GetCHString ( SHARENAME , sShare ) ) { hRes = WBEM_E_FAILED; } return hRes; }