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.

496 lines
11 KiB

  1. /*++
  2. Copyright (c) 1991-1992 Microsoft Corporation
  3. Module Name:
  4. brwins.c
  5. Abstract:
  6. This module contains the routines to interface with the WINS name server.
  7. Author:
  8. Larry Osterman
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. //
  14. // Addresses of procedures in winsrpc.dll
  15. //
  16. DWORD (__RPC_API *BrWinsGetBrowserNames)( PWINSINTF_BIND_DATA_T, PWINSINTF_BROWSER_NAMES_T);
  17. VOID (__RPC_API *BrWinsFreeMem)(LPVOID);
  18. CHAR BrWinsScopeId[256];
  19. NET_API_STATUS
  20. BrOpenNetwork (
  21. IN PUNICODE_STRING NetworkName,
  22. OUT PHANDLE NetworkHandle
  23. )
  24. /*++
  25. Routine Description:
  26. This routine opens the NT LAN Man Datagram Receiver driver.
  27. Arguments:
  28. None.
  29. Return Value:
  30. NET_API_STATUS - NERR_Success or reason for failure.
  31. --*/
  32. {
  33. NTSTATUS ntstatus;
  34. IO_STATUS_BLOCK IoStatusBlock;
  35. OBJECT_ATTRIBUTES ObjectAttributes;
  36. //
  37. // Open the transport device directly.
  38. //
  39. InitializeObjectAttributes(
  40. &ObjectAttributes,
  41. NetworkName,
  42. OBJ_CASE_INSENSITIVE,
  43. NULL,
  44. NULL
  45. );
  46. ntstatus = NtOpenFile(
  47. NetworkHandle,
  48. SYNCHRONIZE,
  49. &ObjectAttributes,
  50. &IoStatusBlock,
  51. 0,
  52. 0
  53. );
  54. if (NT_SUCCESS(ntstatus)) {
  55. ntstatus = IoStatusBlock.Status;
  56. }
  57. if (! NT_SUCCESS(ntstatus)) {
  58. KdPrint(("NtOpenFile network driver failed: 0x%08lx\n",
  59. ntstatus));
  60. }
  61. return NetpNtStatusToApiStatus(ntstatus);
  62. }
  63. NET_API_STATUS
  64. BrGetWinsServerName(
  65. IN PUNICODE_STRING NetworkName,
  66. OUT LPWSTR *PrimaryWinsServerAddress,
  67. OUT LPWSTR *SecondaryWinsServerAddress
  68. )
  69. {
  70. NET_API_STATUS status;
  71. HANDLE netHandle;
  72. tWINS_ADDRESSES winsAddresses;
  73. DWORD bytesReturned;
  74. PCHAR p;
  75. DWORD count;
  76. status = BrOpenNetwork(NetworkName, &netHandle);
  77. if (status != NERR_Success) {
  78. return status;
  79. }
  80. if (!DeviceIoControl(netHandle,
  81. IOCTL_NETBT_GET_WINS_ADDR,
  82. NULL, 0,
  83. &winsAddresses, sizeof(winsAddresses),
  84. &bytesReturned, NULL)) {
  85. status = GetLastError();
  86. CloseHandle(netHandle);
  87. return status;
  88. }
  89. CloseHandle(netHandle);
  90. *PrimaryWinsServerAddress = MIDL_user_allocate((3+1+3+1+3+1+3+1) * sizeof(TCHAR));
  91. if (*PrimaryWinsServerAddress == NULL) {
  92. return ERROR_NOT_ENOUGH_MEMORY;
  93. }
  94. p = (PCHAR)&winsAddresses.PrimaryWinsServer;
  95. count = swprintf(*PrimaryWinsServerAddress, L"%d.%d.%d.%d", p[3] & 0xff, p[2] & 0xff, p[1] & 0xff, p[0] & 0xff);
  96. ASSERT (count < 3 + 1 + 3 + 1 + 3 + 1 + 3 + 1);
  97. *SecondaryWinsServerAddress = MIDL_user_allocate((3+1+3+1+3+1+3+1) * sizeof(TCHAR));
  98. if (*SecondaryWinsServerAddress == NULL) {
  99. MIDL_user_free(*PrimaryWinsServerAddress);
  100. *PrimaryWinsServerAddress = NULL;
  101. return ERROR_NOT_ENOUGH_MEMORY;
  102. }
  103. p = (PCHAR)&winsAddresses.BackupWinsServer;
  104. count = swprintf(*SecondaryWinsServerAddress, L"%d.%d.%d.%d", p[3] & 0xff, p[2] & 0xff, p[1] & 0xff, p[0] & 0xff);
  105. ASSERT (count < 3 + 1 + 3 + 1 + 3 + 1 + 3 + 1);
  106. return NERR_Success;
  107. }
  108. VOID
  109. BrWinsGetScopeId(
  110. VOID
  111. )
  112. /*++
  113. Routine Description:
  114. This code was stolen from the nbtstat command.
  115. This procedure save the netbt scope id in the global variable BrWinsScopeId.
  116. On any error, a NULL scope ID will be used.
  117. Arguments:
  118. Return Value:
  119. 0 if successful, -1 otherwise.
  120. --*/
  121. {
  122. DWORD WinStatus;
  123. HKEY Key;
  124. DWORD BufferSize;
  125. DWORD Type;
  126. //
  127. // Open the registry key containing the scope id.
  128. //
  129. WinStatus = RegOpenKeyExA(
  130. HKEY_LOCAL_MACHINE,
  131. "system\\currentcontrolset\\services\\netbt\\parameters",
  132. 0,
  133. KEY_READ,
  134. &Key);
  135. if ( WinStatus != ERROR_SUCCESS) {
  136. *BrWinsScopeId = '\0';
  137. return;
  138. }
  139. //
  140. // Read the scope id value.
  141. //
  142. BufferSize = sizeof(BrWinsScopeId)-1;
  143. WinStatus = RegQueryValueExA(
  144. Key,
  145. "ScopeId",
  146. NULL,
  147. &Type,
  148. (LPBYTE) &BrWinsScopeId[1],
  149. &BufferSize );
  150. (VOID) RegCloseKey( Key );
  151. if ( WinStatus != ERROR_SUCCESS) {
  152. *BrWinsScopeId = '\0';
  153. return;
  154. }
  155. //
  156. // If there is no scope id (just a zero byte),
  157. // just return an empty string.
  158. // otherise
  159. // return a '.' in front of the scope id.
  160. //
  161. // This matches what WINS returns from WinsGetBrowserNames.
  162. //
  163. if ( BufferSize == 0 || BrWinsScopeId[1] == '\0' ) {
  164. *BrWinsScopeId = '\0';
  165. } else {
  166. *BrWinsScopeId = '.';
  167. }
  168. return;
  169. }
  170. DWORD
  171. BrLoadWinsrpcDll(
  172. VOID
  173. )
  174. /*++
  175. Routine Description:
  176. This routine loads the WinsRpc DLL and locates all the procedures the browser calls
  177. Arguments:
  178. None.
  179. Return Value:
  180. Status of the operation
  181. --*/
  182. {
  183. DWORD WinStatus;
  184. HANDLE hModule;
  185. //
  186. // If the library is already loaded,
  187. // just return.
  188. //
  189. if (BrWinsGetBrowserNames != NULL) {
  190. return NERR_Success;
  191. }
  192. //
  193. // Load the library.
  194. //
  195. hModule = LoadLibraryA("winsrpc");
  196. if (NULL == hModule) {
  197. WinStatus = GetLastError();
  198. return WinStatus;
  199. }
  200. //
  201. // Locate all of the procedures needed.
  202. //
  203. BrWinsGetBrowserNames =
  204. (DWORD (__RPC_API *)( PWINSINTF_BIND_DATA_T, PWINSINTF_BROWSER_NAMES_T))
  205. GetProcAddress( hModule, "WinsGetBrowserNames" );
  206. if (BrWinsGetBrowserNames == NULL) {
  207. WinStatus = GetLastError();
  208. FreeLibrary( hModule );
  209. return WinStatus;
  210. }
  211. BrWinsFreeMem =
  212. (VOID (__RPC_API *)(LPVOID))
  213. GetProcAddress( hModule, "WinsFreeMem" );
  214. if (BrWinsFreeMem == NULL) {
  215. WinStatus = GetLastError();
  216. FreeLibrary( hModule );
  217. return WinStatus;
  218. }
  219. //
  220. // Initialize BrWinsScopeId
  221. //
  222. BrWinsGetScopeId();
  223. return NERR_Success;
  224. }
  225. NET_API_STATUS
  226. BrQuerySpecificWinsServer(
  227. IN LPWSTR WinsServerAddress,
  228. OUT PVOID *WinsServerList,
  229. OUT PDWORD EntriesInList,
  230. OUT PDWORD TotalEntriesInList
  231. )
  232. {
  233. WINSINTF_BIND_DATA_T bindData;
  234. NET_API_STATUS status;
  235. PVOID winsDomainInformation = NULL;
  236. PSERVER_INFO_101 serverInfo;
  237. WINSINTF_BROWSER_NAMES_T names;
  238. DWORD i,j;
  239. LPWSTR serverInfoEnd;
  240. LPWSTR SavedServerInfoEnd;
  241. DWORD bufferSize;
  242. //
  243. // Load winsrpc.dll
  244. //
  245. status = BrLoadWinsrpcDll();
  246. if (status != NERR_Success) {
  247. return status;
  248. }
  249. //
  250. // Get the list of domain names from WINS
  251. //
  252. bindData.fTcpIp = TRUE;
  253. bindData.pServerAdd = (LPSTR)WinsServerAddress;
  254. names.pInfo = NULL;
  255. status = (*BrWinsGetBrowserNames)(&bindData, &names);
  256. if ( status != NERR_Success ) {
  257. return status;
  258. }
  259. //
  260. // Convert the WINS domain list into server list format.
  261. //
  262. bufferSize = (sizeof(SERVER_INFO_101) + ((CNLEN + 1) *sizeof(WCHAR))) * names.EntriesRead;
  263. (*WinsServerList) = winsDomainInformation = MIDL_user_allocate( bufferSize );
  264. if (winsDomainInformation == NULL) {
  265. (*BrWinsFreeMem)(names.pInfo);
  266. return ERROR_NOT_ENOUGH_MEMORY;
  267. }
  268. serverInfo = winsDomainInformation;
  269. serverInfoEnd = (LPWSTR)((PCHAR)winsDomainInformation + bufferSize);
  270. *TotalEntriesInList = names.EntriesRead;
  271. *EntriesInList = 0;
  272. for (i = 0; i < names.EntriesRead ; i += 1) {
  273. OEM_STRING OemString;
  274. UNICODE_STRING UnicodeString;
  275. CHAR WinsName[CNLEN+1];
  276. WCHAR UnicodeWinsName[CNLEN+1];
  277. //
  278. // Make up information about this domain.
  279. //
  280. serverInfo->sv101_platform_id = PLATFORM_ID_NT;
  281. serverInfo->sv101_version_major = 0;
  282. serverInfo->sv101_version_minor = 0;
  283. serverInfo->sv101_type = SV_TYPE_DOMAIN_ENUM | SV_TYPE_NT;
  284. //
  285. // Ignore entries that don't have a 1B as the 16th byte.
  286. // (They really do, but they have a zero byte in the name. So,
  287. // it probably isn't a domain name, just a name that happens to have a
  288. // 1B in the sixteenth byte.)
  289. //
  290. if ( lstrlenA(names.pInfo[i].pName) < NETBIOS_NAME_LEN ) {
  291. continue;
  292. }
  293. //
  294. // Filter out those entries whose scope id doesn't match ours
  295. //
  296. if ( lstrcmpA( &names.pInfo[i].pName[NETBIOS_NAME_LEN], BrWinsScopeId) != 0 ) {
  297. continue;
  298. }
  299. //
  300. // Truncate the 0x1b and spaces from the domain name.
  301. //
  302. lstrcpynA(WinsName, names.pInfo[i].pName, sizeof(WinsName) );
  303. WinsName[CNLEN] = '\0';
  304. for (j = CNLEN-1 ; j ; j -= 1 ) {
  305. if (WinsName[j] != ' ') {
  306. break;
  307. }
  308. }
  309. WinsName[j+1] = '\0';
  310. RtlInitString(&OemString, WinsName);
  311. UnicodeString.Buffer = UnicodeWinsName;
  312. UnicodeString.MaximumLength = sizeof(UnicodeWinsName);
  313. status = RtlOemStringToUnicodeString(&UnicodeString, &OemString, FALSE);
  314. if (!NT_SUCCESS(status)) {
  315. //
  316. // Ignore bogus entries
  317. //
  318. continue;
  319. }
  320. serverInfo->sv101_name = UnicodeString.Buffer;
  321. SavedServerInfoEnd = serverInfoEnd;
  322. if (NetpPackString(&serverInfo->sv101_name,
  323. (PCHAR)(serverInfo+1),
  324. &serverInfoEnd)) {
  325. // Set an empty comment simply by using the existing 0 on the end
  326. // of the server name.
  327. serverInfo->sv101_comment = SavedServerInfoEnd - 1;
  328. *EntriesInList += 1;
  329. }
  330. serverInfo += 1;
  331. }
  332. (*BrWinsFreeMem)(names.pInfo);
  333. return NERR_Success;
  334. }
  335. NET_API_STATUS
  336. BrQueryWinsServer(
  337. IN LPWSTR PrimaryWinsServerAddress,
  338. IN LPWSTR SecondaryWinsServerAddress,
  339. OUT PVOID WinsServerList,
  340. OUT PDWORD EntriesInList,
  341. OUT PDWORD TotalEntriesInList
  342. )
  343. {
  344. NET_API_STATUS status;
  345. status = BrQuerySpecificWinsServer(PrimaryWinsServerAddress,
  346. WinsServerList,
  347. EntriesInList,
  348. TotalEntriesInList);
  349. if (status == NERR_Success) {
  350. return status;
  351. }
  352. status = BrQuerySpecificWinsServer(SecondaryWinsServerAddress,
  353. WinsServerList,
  354. EntriesInList,
  355. TotalEntriesInList);
  356. return status;
  357. }