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.

261 lines
8.2 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000-2002 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // GetComputerNameSrc.cpp
  7. //
  8. // Description:
  9. // Getting and setting the computer name.
  10. //
  11. // Maintained By:
  12. // Galen Barbee (GalenB) 31-MAR-2000
  13. //
  14. // Revision History:
  15. //
  16. // Notes:
  17. //
  18. /////////////////////////////////////////////////////////////////////////////
  19. // #include <Pch.h> // should be included by includer of this file
  20. #include <StrSafe.h> // in case it isn't included by header file
  21. /////////////////////////////////////////////////////////////////////////////
  22. //++
  23. //
  24. // HrGetComputerName
  25. //
  26. // Description:
  27. // Get name of the computer on which this object is present.
  28. //
  29. // Arguments:
  30. // cnfIn
  31. // Code representing type of information to return.
  32. //
  33. // pbstrComputerNameOut
  34. // Buffer pointer for returning the computer or domain name.
  35. // Caller must deallocate this buffer using TraceSysFreeString.
  36. //
  37. // fBestEffortIn
  38. // TRUE = Attempt to return something even if DC is unavailable.
  39. // FALSE = Return all failures.
  40. //
  41. // Return Value:
  42. // S_OK
  43. // Success.
  44. //
  45. // Remarks:
  46. // DsGetDCName is used to get the domain name instead of just letting
  47. // GetComputerNameEx get it so that pre-Windows 2000 domains can be
  48. // supported. In a pre-Windows 2000 domain, GetComputerNameEx will not
  49. // return an FQDN or a domain name if that is what has been request.
  50. // To support this scenario, this routine gets the domain name using
  51. // DsGetDCName, gets the hostname label, then constructs the final name
  52. // using <computername>.<DomainName>.
  53. //
  54. //--
  55. //////////////////////////////////////////////////////////////////////////////
  56. HRESULT
  57. WINAPI
  58. HrGetComputerName(
  59. COMPUTER_NAME_FORMAT cnfIn
  60. , BSTR * pbstrComputerNameOut
  61. , BOOL fBestEffortIn
  62. )
  63. {
  64. TraceFunc( "" );
  65. HRESULT hr = S_OK;
  66. DWORD sc;
  67. size_t cchComputerName = 0;
  68. size_t cchBuffer = 0;
  69. BSTR bstrComputerName = NULL;
  70. BOOL fAppendDomain = FALSE;
  71. BOOL fSuccess;
  72. PDOMAIN_CONTROLLER_INFO pdci = NULL;
  73. if ( pbstrComputerNameOut == NULL )
  74. {
  75. hr = THR( E_POINTER );
  76. goto Cleanup;
  77. } // if:
  78. *pbstrComputerNameOut = NULL;
  79. //
  80. // Only get the domain name when there is a reason to get the domain name.
  81. //
  82. if ( ( cnfIn == ComputerNameDnsFullyQualified )
  83. || ( cnfIn == ComputerNamePhysicalDnsFullyQualified )
  84. || ( cnfIn == ComputerNameDnsDomain )
  85. || ( cnfIn == ComputerNamePhysicalDnsDomain )
  86. )
  87. {
  88. //
  89. // DsGetDcName will give us access to a usable domain name, regardless of whether we are
  90. // currently in a W2k or a NT4 domain. On W2k and above, it will return a DNS domain name,
  91. // on NT4 it will return a NetBIOS name.
  92. //
  93. sc = DsGetDcName(
  94. NULL // ComputerName
  95. , NULL // DomainName
  96. , NULL // DomainGuid
  97. , NULL // SiteName
  98. , DS_DIRECTORY_SERVICE_PREFERRED
  99. , &pdci
  100. );
  101. if ( ( sc == ERROR_NO_SUCH_DOMAIN )
  102. && ( fBestEffortIn )
  103. )
  104. {
  105. fAppendDomain = FALSE;
  106. } // if: can't reach a DC
  107. else if ( sc != ERROR_SUCCESS )
  108. {
  109. TW32( sc );
  110. hr = HRESULT_FROM_WIN32( sc );
  111. goto Cleanup;
  112. } // else if: DsGetDcName failed
  113. else
  114. {
  115. //
  116. // This handles the case when we are a member of a legacy (pre-W2k) Domain.
  117. // In this case, both FQDN and DnsDomain will not receive useful data from GetComputerNameEx.
  118. // What we actually want to get is <computername>.<DomainName> in every case.
  119. //
  120. switch ( cnfIn )
  121. {
  122. case ComputerNameDnsFullyQualified:
  123. cnfIn = ComputerNameDnsHostname;
  124. break;
  125. case ComputerNamePhysicalDnsFullyQualified:
  126. cnfIn = ComputerNamePhysicalDnsHostname;
  127. break;
  128. case ComputerNameDnsDomain:
  129. case ComputerNamePhysicalDnsDomain:
  130. *pbstrComputerNameOut = TraceSysAllocString( pdci->DomainName );
  131. if ( *pbstrComputerNameOut == NULL )
  132. {
  133. hr = THR( E_OUTOFMEMORY );
  134. goto Cleanup;
  135. } // if:
  136. goto Cleanup;
  137. } // switch: computer name format
  138. fAppendDomain = TRUE;
  139. } // else: DC contacted successfully
  140. } // if: computer name format requires domain name
  141. else
  142. {
  143. fAppendDomain = FALSE;
  144. } // else: computer name format does not require domain name
  145. //
  146. // Get the computer name. First get the size of the output buffer,
  147. // allocate a buffer, then get the name itself.
  148. //
  149. cchComputerName = 0;
  150. fSuccess = GetComputerNameExW( cnfIn, NULL, reinterpret_cast< DWORD * >( &cchComputerName ) );
  151. if ( fSuccess == FALSE )
  152. {
  153. cchBuffer = cchComputerName + 1;
  154. //
  155. // If error not buffer to small, we're done.
  156. //
  157. sc = GetLastError();
  158. if ( sc != ERROR_MORE_DATA )
  159. {
  160. TW32( sc );
  161. hr = HRESULT_FROM_WIN32( sc );
  162. LogMsg( "GetComputerNameEx failed. sc = %1!#08x!", sc );
  163. goto Cleanup;
  164. } // if: error other than buffer too small
  165. //
  166. // Add on size of domain name and period separator.
  167. //
  168. if ( fAppendDomain )
  169. {
  170. // Add space for the domain name and the period separator.
  171. cchBuffer += wcslen( pdci->DomainName ) + 1;
  172. } // if: appending domain name to computer name
  173. //
  174. // Allocate the output buffer.
  175. //
  176. bstrComputerName = TraceSysAllocStringLen( L"", static_cast< unsigned int >( cchBuffer ) );
  177. if ( bstrComputerName == NULL )
  178. {
  179. hr = THR( E_OUTOFMEMORY );
  180. goto Cleanup;
  181. } // if: error allocating buffer for name
  182. //
  183. // Get the computer name into the output buffer.
  184. //
  185. fSuccess = GetComputerNameExW( cnfIn, bstrComputerName, reinterpret_cast< DWORD * >( &cchComputerName ) );
  186. if ( fSuccess == FALSE )
  187. {
  188. sc = TW32( GetLastError() );
  189. hr = HRESULT_FROM_WIN32( sc );
  190. LogMsg( "GetComputerNameEx failed. sc = %1!#08x!", sc );
  191. goto Cleanup;
  192. } // if: error getting the computer name
  193. //
  194. // Append the period separator and domain name onto the computer name.
  195. //
  196. if ( fAppendDomain )
  197. {
  198. // Append a dot (.) and the domain name after the computer name.
  199. hr = THR( StringCchCatW( bstrComputerName, cchBuffer, L"." ) );
  200. if ( SUCCEEDED( hr ) )
  201. {
  202. hr = THR( StringCchCatW( bstrComputerName, cchBuffer, pdci->DomainName ) );
  203. }
  204. if ( FAILED( hr ) )
  205. {
  206. LogMsg( "Error concatenating domain name, hr = %1!#08x!", hr );
  207. goto Cleanup;
  208. }
  209. } // if: appending domain name to computer name
  210. //
  211. // Set output buffer pointer.
  212. //
  213. *pbstrComputerNameOut = bstrComputerName;
  214. bstrComputerName = NULL;
  215. } // if: error getting computer name
  216. else
  217. {
  218. AssertMsg( fSuccess == FALSE, "Expected GetComputerNameEx to fail with null buffer" );
  219. } // else: GetComputerNameEx didn't fail as expected
  220. Cleanup:
  221. TraceSysFreeString( bstrComputerName );
  222. if ( pdci != NULL )
  223. {
  224. NetApiBufferFree( pdci );
  225. } // if:
  226. HRETURN( hr );
  227. } //*** HrGetComputerName