///////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2000-2002 Microsoft Corporation // // Module Name: // GetComputerNameSrc.cpp // // Description: // Getting and setting the computer name. // // Maintained By: // Galen Barbee (GalenB) 31-MAR-2000 // // Revision History: // // Notes: // ///////////////////////////////////////////////////////////////////////////// // #include // should be included by includer of this file #include // in case it isn't included by header file ///////////////////////////////////////////////////////////////////////////// //++ // // HrGetComputerName // // Description: // Get name of the computer on which this object is present. // // Arguments: // cnfIn // Code representing type of information to return. // // pbstrComputerNameOut // Buffer pointer for returning the computer or domain name. // Caller must deallocate this buffer using TraceSysFreeString. // // fBestEffortIn // TRUE = Attempt to return something even if DC is unavailable. // FALSE = Return all failures. // // Return Value: // S_OK // Success. // // Remarks: // DsGetDCName is used to get the domain name instead of just letting // GetComputerNameEx get it so that pre-Windows 2000 domains can be // supported. In a pre-Windows 2000 domain, GetComputerNameEx will not // return an FQDN or a domain name if that is what has been request. // To support this scenario, this routine gets the domain name using // DsGetDCName, gets the hostname label, then constructs the final name // using .. // //-- ////////////////////////////////////////////////////////////////////////////// HRESULT WINAPI HrGetComputerName( COMPUTER_NAME_FORMAT cnfIn , BSTR * pbstrComputerNameOut , BOOL fBestEffortIn ) { TraceFunc( "" ); HRESULT hr = S_OK; DWORD sc; size_t cchComputerName = 0; size_t cchBuffer = 0; BSTR bstrComputerName = NULL; BOOL fAppendDomain = FALSE; BOOL fSuccess; PDOMAIN_CONTROLLER_INFO pdci = NULL; if ( pbstrComputerNameOut == NULL ) { hr = THR( E_POINTER ); goto Cleanup; } // if: *pbstrComputerNameOut = NULL; // // Only get the domain name when there is a reason to get the domain name. // if ( ( cnfIn == ComputerNameDnsFullyQualified ) || ( cnfIn == ComputerNamePhysicalDnsFullyQualified ) || ( cnfIn == ComputerNameDnsDomain ) || ( cnfIn == ComputerNamePhysicalDnsDomain ) ) { // // DsGetDcName will give us access to a usable domain name, regardless of whether we are // currently in a W2k or a NT4 domain. On W2k and above, it will return a DNS domain name, // on NT4 it will return a NetBIOS name. // sc = DsGetDcName( NULL // ComputerName , NULL // DomainName , NULL // DomainGuid , NULL // SiteName , DS_DIRECTORY_SERVICE_PREFERRED , &pdci ); if ( ( sc == ERROR_NO_SUCH_DOMAIN ) && ( fBestEffortIn ) ) { fAppendDomain = FALSE; } // if: can't reach a DC else if ( sc != ERROR_SUCCESS ) { TW32( sc ); hr = HRESULT_FROM_WIN32( sc ); goto Cleanup; } // else if: DsGetDcName failed else { // // This handles the case when we are a member of a legacy (pre-W2k) Domain. // In this case, both FQDN and DnsDomain will not receive useful data from GetComputerNameEx. // What we actually want to get is . in every case. // switch ( cnfIn ) { case ComputerNameDnsFullyQualified: cnfIn = ComputerNameDnsHostname; break; case ComputerNamePhysicalDnsFullyQualified: cnfIn = ComputerNamePhysicalDnsHostname; break; case ComputerNameDnsDomain: case ComputerNamePhysicalDnsDomain: *pbstrComputerNameOut = TraceSysAllocString( pdci->DomainName ); if ( *pbstrComputerNameOut == NULL ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; } // if: goto Cleanup; } // switch: computer name format fAppendDomain = TRUE; } // else: DC contacted successfully } // if: computer name format requires domain name else { fAppendDomain = FALSE; } // else: computer name format does not require domain name // // Get the computer name. First get the size of the output buffer, // allocate a buffer, then get the name itself. // cchComputerName = 0; fSuccess = GetComputerNameExW( cnfIn, NULL, reinterpret_cast< DWORD * >( &cchComputerName ) ); if ( fSuccess == FALSE ) { cchBuffer = cchComputerName + 1; // // If error not buffer to small, we're done. // sc = GetLastError(); if ( sc != ERROR_MORE_DATA ) { TW32( sc ); hr = HRESULT_FROM_WIN32( sc ); LogMsg( "GetComputerNameEx failed. sc = %1!#08x!", sc ); goto Cleanup; } // if: error other than buffer too small // // Add on size of domain name and period separator. // if ( fAppendDomain ) { // Add space for the domain name and the period separator. cchBuffer += wcslen( pdci->DomainName ) + 1; } // if: appending domain name to computer name // // Allocate the output buffer. // bstrComputerName = TraceSysAllocStringLen( L"", static_cast< unsigned int >( cchBuffer ) ); if ( bstrComputerName == NULL ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; } // if: error allocating buffer for name // // Get the computer name into the output buffer. // fSuccess = GetComputerNameExW( cnfIn, bstrComputerName, reinterpret_cast< DWORD * >( &cchComputerName ) ); if ( fSuccess == FALSE ) { sc = TW32( GetLastError() ); hr = HRESULT_FROM_WIN32( sc ); LogMsg( "GetComputerNameEx failed. sc = %1!#08x!", sc ); goto Cleanup; } // if: error getting the computer name // // Append the period separator and domain name onto the computer name. // if ( fAppendDomain ) { // Append a dot (.) and the domain name after the computer name. hr = THR( StringCchCatW( bstrComputerName, cchBuffer, L"." ) ); if ( SUCCEEDED( hr ) ) { hr = THR( StringCchCatW( bstrComputerName, cchBuffer, pdci->DomainName ) ); } if ( FAILED( hr ) ) { LogMsg( "Error concatenating domain name, hr = %1!#08x!", hr ); goto Cleanup; } } // if: appending domain name to computer name // // Set output buffer pointer. // *pbstrComputerNameOut = bstrComputerName; bstrComputerName = NULL; } // if: error getting computer name else { AssertMsg( fSuccess == FALSE, "Expected GetComputerNameEx to fail with null buffer" ); } // else: GetComputerNameEx didn't fail as expected Cleanup: TraceSysFreeString( bstrComputerName ); if ( pdci != NULL ) { NetApiBufferFree( pdci ); } // if: HRETURN( hr ); } //*** HrGetComputerName