Source code of Windows XP (NT5)
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.

434 lines
16 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000-2001 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // NameUtil.cpp
  7. //
  8. // Description:
  9. // Name resolution utility.
  10. //
  11. // Maintained By:
  12. // Galen Barbee (GalenB) 28-NOV-2000
  13. //
  14. //////////////////////////////////////////////////////////////////////////////
  15. #include "pch.h"
  16. #include "nameutil.h"
  17. #include <initguid.h>
  18. // {6968D735-ADBB-4748-A36E-7CEE0FE21116}
  19. DEFINE_GUID( TASKID_Minor_Multiple_DNS_Records_Found,
  20. 0x6968d735, 0xadbb, 0x4748, 0xa3, 0x6e, 0x7c, 0xee, 0xf, 0xe2, 0x11, 0x16);
  21. // {D86FAAD9-2514-451e-B359-435AF35E6038}
  22. DEFINE_GUID( TASKID_Minor_FQDN_DNS_Binding_Succeeded,
  23. 0xd86faad9, 0x2514, 0x451e, 0xb3, 0x59, 0x43, 0x5a, 0xf3, 0x5e, 0x60, 0x38);
  24. // {B2359972-F6B8-433d-949B-DB1CEE009321}
  25. DEFINE_GUID( TASKID_Minor_FQDN_DNS_Binding_Failed,
  26. 0xb2359972, 0xf6b8, 0x433d, 0x94, 0x9b, 0xdb, 0x1c, 0xee, 0x0, 0x93, 0x21);
  27. // {2FF4B2F0-800C-44db-9131-F60B30F76CB4}
  28. DEFINE_GUID( TASKID_Minor_NETBIOS_Binding_Failed,
  29. 0x2ff4b2f0, 0x800c, 0x44db, 0x91, 0x31, 0xf6, 0xb, 0x30, 0xf7, 0x6c, 0xb4);
  30. // {D40532E1-9286-4dbd-A559-B62DCC218929}
  31. DEFINE_GUID( TASKID_Minor_NETBIOS_Binding_Succeeded,
  32. 0xd40532e1, 0x9286, 0x4dbd, 0xa5, 0x59, 0xb6, 0x2d, 0xcc, 0x21, 0x89, 0x29);
  33. // {D0AB3284-8F62-4f55-8938-DA6A583604E0}
  34. DEFINE_GUID( TASKID_Minor_NETBIOS_Name_Conversion_Succeeded,
  35. 0xd0ab3284, 0x8f62, 0x4f55, 0x89, 0x38, 0xda, 0x6a, 0x58, 0x36, 0x4, 0xe0);
  36. // {66F8E4AA-DF71-4973-A4A3-115EB6FE9986}
  37. DEFINE_GUID( TASKID_Minor_NETBIOS_Name_Conversion_Failed,
  38. 0x66f8e4aa, 0xdf71, 0x4973, 0xa4, 0xa3, 0x11, 0x5e, 0xb6, 0xfe, 0x99, 0x86);
  39. // {5F18ED71-07EC-46d3-ADB9-71F1C7794DB2}
  40. DEFINE_GUID( TASKID_Minor_NETBIOS_Reset_Failed,
  41. 0x5f18ed71, 0x7ec, 0x46d3, 0xad, 0xb9, 0x71, 0xf1, 0xc7, 0x79, 0x4d, 0xb2);
  42. // {A6DCB5E1-1FDF-4c94-ADBA-EE18F72B8197}
  43. DEFINE_GUID( TASKID_Minor_NETBIOS_LanaEnum_Failed,
  44. 0xa6dcb5e1, 0x1fdf, 0x4c94, 0xad, 0xba, 0xee, 0x18, 0xf7, 0x2b, 0x81, 0x97);
  45. //////////////////////////////////////////////////////////////////////////////
  46. //
  47. // HRESULT
  48. // HrCreateBinding(
  49. // IClusCfgCallback * pcccbIn,
  50. // CLSID * pclsidLogIn,
  51. // BSTR bstrNameIn,
  52. // BSTR * pbstrBindingOut
  53. // )
  54. //
  55. //////////////////////////////////////////////////////////////////////////////
  56. HRESULT
  57. HrCreateBinding(
  58. IClusCfgCallback * pcccbIn,
  59. const CLSID * pclsidLogIn,
  60. BSTR bstrNameIn,
  61. BSTR * pbstrBindingOut
  62. )
  63. {
  64. TraceFunc1( "bstrNameIn = '%ws'", bstrNameIn );
  65. DNS_STATUS status;
  66. DWORD cch;
  67. BOOL bRet;
  68. bool fMadeNetBIOSName = false;
  69. WCHAR szNetBIOSName[ MAX_COMPUTERNAME_LENGTH + 1 ];
  70. UCHAR rgucNameBufer[ sizeof( FIND_NAME_HEADER ) + sizeof( FIND_NAME_BUFFER ) ];
  71. NCB ncb;
  72. LANA_ENUM leLanaEnum;
  73. UCHAR idx;
  74. FIND_NAME_HEADER * pfnh = (FIND_NAME_HEADER *) &rgucNameBufer[ 0 ];
  75. FIND_NAME_BUFFER * pfnb = (FIND_NAME_BUFFER *) &rgucNameBufer[ sizeof( FIND_NAME_HEADER ) ];
  76. HRESULT hr = E_FAIL;
  77. PDNS_RECORD pResults = NULL;
  78. BSTR bstrNotification = NULL;
  79. BSTR bstrNetBiosName = NULL;
  80. Assert( bstrNameIn != NULL );
  81. Assert( pbstrBindingOut != NULL );
  82. Assert( *pbstrBindingOut == NULL );
  83. status = DnsQuery( bstrNameIn, DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &pResults, NULL );
  84. if ( status == ERROR_SUCCESS )
  85. {
  86. LPSTR pszIP;
  87. pszIP = inet_ntoa( * (struct in_addr *) &pResults->Data.A.IpAddress );
  88. *pbstrBindingOut = TraceSysAllocStringLen( NULL, (UINT) strlen( pszIP ) + 1 );
  89. if ( *pbstrBindingOut == NULL )
  90. goto OutOfMemory;
  91. mbstowcs( *pbstrBindingOut, pszIP, strlen( pszIP ) + 1 );
  92. if ( pResults->pNext != NULL )
  93. {
  94. if ( pcccbIn != NULL )
  95. {
  96. THR( HrFormatStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_MULTIPLE_DNS_RECORDS_FOUND, &bstrNotification, bstrNameIn ) );
  97. hr = THR( pcccbIn->SendStatusReport( bstrNameIn,
  98. *pclsidLogIn,
  99. TASKID_Minor_Multiple_DNS_Records_Found,
  100. 0,
  101. 1,
  102. 1,
  103. S_FALSE,
  104. bstrNotification,
  105. NULL,
  106. NULL
  107. ) );
  108. // ignore error
  109. }
  110. }
  111. if ( pcccbIn != NULL )
  112. {
  113. THR( HrFormatStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_FQDN_DNS_BINDING_SUCCEEDED, &bstrNotification, bstrNameIn, *pbstrBindingOut ) );
  114. hr = THR( pcccbIn->SendStatusReport( bstrNameIn,
  115. *pclsidLogIn,
  116. TASKID_Minor_FQDN_DNS_Binding_Succeeded,
  117. 0,
  118. 1,
  119. 1,
  120. S_OK,
  121. bstrNotification,
  122. NULL,
  123. NULL
  124. ) );
  125. }
  126. else
  127. {
  128. hr = S_OK;
  129. }
  130. goto Cleanup; // done!
  131. } // if: DnsQuery() succeeded
  132. else if ( status == DNS_ERROR_RCODE_NAME_ERROR )
  133. {
  134. if ( pcccbIn != NULL )
  135. {
  136. THR( HrFormatStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_FQDN_DNS_BINDING_FAILED, &bstrNotification, bstrNameIn ) );
  137. hr = THR( pcccbIn->SendStatusReport( bstrNameIn,
  138. TASKID_Major_Client_And_Server_Log,
  139. TASKID_Minor_FQDN_DNS_Binding_Failed,
  140. 0,
  141. 1,
  142. 1,
  143. MAKE_HRESULT( 0, FACILITY_WIN32, status ),
  144. bstrNotification,
  145. NULL,
  146. NULL
  147. ) );
  148. if ( FAILED( hr ) )
  149. goto Cleanup;
  150. }
  151. cch = ARRAYSIZE( szNetBIOSName );
  152. Assert( cch == MAX_COMPUTERNAME_LENGTH + 1 );
  153. bRet = DnsHostnameToComputerName( bstrNameIn, szNetBIOSName, &cch );
  154. if ( !bRet )
  155. {
  156. hr = MAKE_HRESULT( 0, FACILITY_WIN32, TW32( GetLastError() ) );
  157. if ( pcccbIn != NULL )
  158. {
  159. THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_NETBIOS_NAME_CONVERSION_FAILED, &bstrNotification ) );
  160. hr = THR( pcccbIn->SendStatusReport( bstrNameIn,
  161. *pclsidLogIn,
  162. TASKID_Minor_NETBIOS_Name_Conversion_Failed,
  163. 0,
  164. 1,
  165. 1,
  166. hr,
  167. bstrNotification,
  168. NULL,
  169. NULL
  170. ) );
  171. if ( FAILED( hr ) )
  172. goto Cleanup;
  173. }
  174. goto SkipNetBios;
  175. }
  176. bstrNetBiosName = TraceSysAllocString( szNetBIOSName );
  177. if ( bstrNetBiosName == NULL )
  178. goto OutOfMemory;
  179. if ( pcccbIn != NULL )
  180. {
  181. THR( HrFormatStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_NETBIOS_NAME_CONVERSION_SUCCEEDED, &bstrNotification, bstrNameIn, bstrNetBiosName ) );
  182. hr = THR( pcccbIn->SendStatusReport( bstrNameIn,
  183. TASKID_Major_Client_And_Server_Log,
  184. TASKID_Minor_NETBIOS_Name_Conversion_Succeeded,
  185. 0,
  186. 1,
  187. 1,
  188. S_OK,
  189. bstrNotification,
  190. NULL,
  191. NULL
  192. ) );
  193. if ( FAILED( hr ) )
  194. goto Cleanup;
  195. }
  196. //
  197. // Try to find the name using NetBIOS.
  198. //
  199. ZeroMemory( &ncb, sizeof( ncb ) );
  200. //
  201. // Enumerate the network adapters
  202. //
  203. ncb.ncb_command = NCBENUM; // Enumerate LANA nums (wait)
  204. ncb.ncb_buffer = (PUCHAR) &leLanaEnum;
  205. ncb.ncb_length = sizeof( LANA_ENUM );
  206. Netbios( &ncb );
  207. if ( ncb.ncb_retcode != NRC_GOODRET )
  208. {
  209. hr = MAKE_HRESULT( 0, FACILITY_NULL, ncb.ncb_retcode );
  210. if ( pcccbIn != NULL )
  211. {
  212. THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_NETBIOS_LANAENUM_FAILED, &bstrNotification ) );
  213. hr = THR( pcccbIn->SendStatusReport( bstrNameIn,
  214. TASKID_Major_Client_And_Server_Log,
  215. TASKID_Minor_NETBIOS_LanaEnum_Failed,
  216. 0,
  217. 1,
  218. 1,
  219. hr,
  220. bstrNotification,
  221. NULL,
  222. NULL
  223. ) );
  224. if ( FAILED( hr ) )
  225. goto Cleanup;
  226. } // if:
  227. goto SkipNetBios;
  228. } // if:
  229. //
  230. // Reset each adapter and try to find the name.
  231. //
  232. for ( idx = 0; idx < leLanaEnum.length; idx++ )
  233. {
  234. //
  235. // Reset the adapter
  236. //
  237. ncb.ncb_command = NCBRESET;
  238. ncb.ncb_lana_num = leLanaEnum.lana[ idx ];
  239. Netbios( &ncb );
  240. if ( ncb.ncb_retcode != NRC_GOODRET )
  241. {
  242. hr = MAKE_HRESULT( 0, FACILITY_NULL, ncb.ncb_retcode );
  243. if ( pcccbIn != NULL )
  244. {
  245. THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_NETBIOS_RESET_FAILED, &bstrNotification ) );
  246. hr = THR( pcccbIn->SendStatusReport( bstrNameIn,
  247. TASKID_Major_Client_And_Server_Log,
  248. TASKID_Minor_NETBIOS_Reset_Failed,
  249. 0,
  250. 1,
  251. 1,
  252. hr,
  253. bstrNotification,
  254. NULL,
  255. NULL
  256. ) );
  257. if ( FAILED( hr ) )
  258. goto Cleanup;
  259. }
  260. //
  261. // Continue with the next adapter.
  262. //
  263. continue;
  264. }
  265. ncb.ncb_command = NCBFINDNAME;
  266. ncb.ncb_buffer = rgucNameBufer;
  267. ncb.ncb_length = sizeof( rgucNameBufer );
  268. pfnh->node_count = 1;
  269. // Fill with spaces
  270. memset( ncb.ncb_callname, 32, sizeof( ncb.ncb_callname ) );
  271. wcstombs( (CHAR *) ncb.ncb_callname, szNetBIOSName, wcslen( szNetBIOSName ) );
  272. Netbios( &ncb );
  273. if ( ncb.ncb_retcode == NRC_GOODRET )
  274. {
  275. LPSTR pszIP;
  276. struct in_addr sin;
  277. sin.S_un.S_addr = *((u_long UNALIGNED *) &pfnb->source_addr[ 2 ]);
  278. pszIP = inet_ntoa( sin );
  279. *pbstrBindingOut = TraceSysAllocStringLen( NULL, (UINT) strlen( pszIP ) + 1 );
  280. if ( *pbstrBindingOut == NULL )
  281. goto OutOfMemory;
  282. mbstowcs( *pbstrBindingOut, pszIP, strlen( pszIP ) + 1 );
  283. if ( pcccbIn != NULL )
  284. {
  285. THR( HrFormatStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_NETBIOS_BINDING_SUCCEEDED, &bstrNotification, bstrNetBiosName, *pbstrBindingOut ) );
  286. hr = THR( pcccbIn->SendStatusReport( bstrNameIn,
  287. *pclsidLogIn,
  288. TASKID_Minor_NETBIOS_Binding_Succeeded,
  289. 0,
  290. 1,
  291. 1,
  292. S_OK,
  293. bstrNotification,
  294. NULL,
  295. NULL
  296. ) );
  297. }
  298. else
  299. {
  300. hr = S_OK;
  301. }
  302. fMadeNetBIOSName = true;
  303. break; // done!
  304. }
  305. hr = MAKE_HRESULT( 0, FACILITY_NULL, ncb.ncb_retcode );
  306. if ( pcccbIn != NULL )
  307. {
  308. THR( HrFormatStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_NETBIOS_BINDING_FAILED, &bstrNotification, bstrNameIn ) );
  309. hr = THR( pcccbIn->SendStatusReport( bstrNameIn,
  310. TASKID_Major_Client_And_Server_Log,
  311. TASKID_Minor_NETBIOS_Binding_Failed,
  312. 0,
  313. 1,
  314. 1,
  315. hr,
  316. bstrNotification,
  317. NULL,
  318. NULL
  319. ) );
  320. if ( FAILED( hr ) )
  321. goto Cleanup;
  322. } // if:
  323. } // for:
  324. if ( fMadeNetBIOSName )
  325. {
  326. goto Cleanup;
  327. } // if:
  328. } // else if:
  329. else
  330. {
  331. TW32( status );
  332. } // else:
  333. SkipNetBios:
  334. //
  335. // If all else fails, use the name and attempt to bind to it.
  336. //
  337. *pbstrBindingOut = TraceSysAllocString( bstrNameIn );
  338. if ( *pbstrBindingOut == NULL )
  339. goto OutOfMemory;
  340. hr = S_FALSE;
  341. goto Cleanup;
  342. Cleanup:
  343. #ifdef DEBUG
  344. if ( FAILED( hr ) )
  345. {
  346. Assert( *pbstrBindingOut == NULL );
  347. }
  348. #endif
  349. TraceSysFreeString( bstrNotification );
  350. TraceSysFreeString( bstrNetBiosName );
  351. if ( pResults != NULL )
  352. {
  353. DnsRecordListFree( pResults, DnsFreeRecordListDeep );
  354. }
  355. HRETURN( hr );
  356. OutOfMemory:
  357. hr = E_OUTOFMEMORY;
  358. goto Cleanup;
  359. } //*** HrCreateBinding