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.

422 lines
10 KiB

  1. /*++
  2. Copyright (c) 1996-2000 Microsoft Corporation
  3. Module Name:
  4. namechk.c
  5. Abstract:
  6. Check on network names given by the cluster network name resource dll.
  7. Author:
  8. Rod Gamache (rodga) 1-Aug-1997
  9. Environment:
  10. User Mode
  11. Revision History:
  12. --*/
  13. #define UNICODE 1
  14. #include <nt.h>
  15. #include <ntdef.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <windows.h>
  19. #include <stdlib.h>
  20. #include <nb30.h>
  21. #include <lmaccess.h>
  22. #include "namechk.h"
  23. #include "resapi.h"
  24. #include "netname.h"
  25. #include "nameutil.h"
  26. #include "clusres.h"
  27. #define NET_NAME_SVC L"LanmanServer"
  28. #define BUFF_SIZE 650
  29. #define NBT_MAXIMUM_BINDINGS 20
  30. NTSTATUS
  31. CheckNbtName(
  32. IN HANDLE Fd,
  33. IN LPCWSTR Name,
  34. IN ULONG Type,
  35. IN RESOURCE_HANDLE ResourceHandle
  36. );
  37. NTSTATUS
  38. ReadRegistry(
  39. IN UCHAR pDeviceName[][MAX_PATH_SIZE]
  40. );
  41. NTSTATUS
  42. OpenNbt(
  43. IN char path[][MAX_PATH_SIZE],
  44. OUT PHANDLE pHandle
  45. );
  46. DWORD
  47. NetNameCheckNbtName(
  48. IN LPCWSTR NetName,
  49. IN DWORD NameHandleCount,
  50. IN HANDLE * NameHandleList,
  51. IN RESOURCE_HANDLE ResourceHandle
  52. )
  53. /*++
  54. Routine Description:
  55. Checks a network name.
  56. Arguments:
  57. NetName - pointer to the network name to validate.
  58. Return Value:
  59. ERROR_SUCCESS if successful.
  60. A Win32 error code on failure.
  61. --*/
  62. {
  63. DWORD status = ERROR_SUCCESS;
  64. NTSTATUS ntStatus;
  65. //
  66. // loop through the list of handles we acquired when bringing the
  67. // name online and check that our netname is still registered
  68. // on each device
  69. //
  70. while ( NameHandleCount-- ) {
  71. //
  72. // Check the workstation name. If this fails, immediate failure!
  73. //
  74. ntStatus = CheckNbtName(
  75. *NameHandleList,
  76. NetName,
  77. 0x00,
  78. ResourceHandle
  79. );
  80. if ( !NT_SUCCESS(ntStatus) ) {
  81. status = RtlNtStatusToDosError(ntStatus);
  82. return(status);
  83. }
  84. //
  85. // Check the server name. If this fails, then only fail if Srv service
  86. // is not running.
  87. //
  88. ntStatus = CheckNbtName(
  89. *NameHandleList,
  90. NetName,
  91. 0x20,
  92. ResourceHandle
  93. );
  94. if ( !NT_SUCCESS(ntStatus) ) {
  95. if ( ResUtilVerifyResourceService( NET_NAME_SVC) == ERROR_SUCCESS ) {
  96. status = ERROR_RESOURCE_FAILED;
  97. }
  98. }
  99. ++NameHandleList;
  100. }
  101. return(status);
  102. } // NetNameCheckName
  103. NTSTATUS
  104. CheckNbtName(
  105. IN HANDLE fd,
  106. IN LPCWSTR Name,
  107. IN ULONG Type,
  108. IN RESOURCE_HANDLE ResourceHandle
  109. )
  110. /*++
  111. Routine Description:
  112. This procedure does an adapter status query to get the local name table.
  113. Arguments:
  114. Return Value:
  115. 0 if successful, -1 otherwise.
  116. --*/
  117. {
  118. LONG Count;
  119. ULONG BufferSize = sizeof( tADAPTERSTATUS );
  120. tADAPTERSTATUS staticBuffer;
  121. PVOID pBuffer = (PVOID)&staticBuffer;
  122. NTSTATUS status;
  123. tADAPTERSTATUS *pAdapterStatus;
  124. NAME_BUFFER *pNames;
  125. ULONG Ioctl;
  126. TDI_REQUEST_QUERY_INFORMATION QueryInfo;
  127. PVOID pInput;
  128. ULONG SizeInput;
  129. UCHAR netBiosName[NETBIOS_NAME_SIZE +4];
  130. OEM_STRING netBiosNameString;
  131. UNICODE_STRING unicodeName;
  132. NTSTATUS ntStatus;
  133. //
  134. // set the correct Ioctl for the call to NBT, to get either
  135. // the local name table or the remote name table
  136. //
  137. Ioctl = IOCTL_TDI_QUERY_INFORMATION;
  138. QueryInfo.QueryType = TDI_QUERY_ADAPTER_STATUS; // node status or whatever
  139. SizeInput = sizeof(TDI_REQUEST_QUERY_INFORMATION);
  140. pInput = &QueryInfo;
  141. do {
  142. status = DeviceIoCtrl(fd,
  143. pBuffer,
  144. BufferSize,
  145. Ioctl,
  146. pInput,
  147. SizeInput);
  148. if (status == STATUS_BUFFER_OVERFLOW) {
  149. if ( pBuffer != &staticBuffer ) {
  150. LocalFree(pBuffer);
  151. }
  152. BufferSize += sizeof( staticBuffer.Names );
  153. pBuffer = LocalAlloc(LMEM_FIXED, BufferSize);
  154. if (!pBuffer || (BufferSize >= 0xFFFF)) {
  155. LocalFree(pBuffer);
  156. (NetNameLogEvent)(
  157. ResourceHandle,
  158. LOG_ERROR,
  159. L"Unable to allocate memory for name query.\n"
  160. );
  161. return(STATUS_INSUFFICIENT_RESOURCES);
  162. }
  163. }
  164. } while (status == STATUS_BUFFER_OVERFLOW);
  165. if (status != STATUS_SUCCESS) {
  166. (NetNameLogEvent)(
  167. ResourceHandle,
  168. LOG_ERROR,
  169. L"Name query request failed, status %1!u!.\n",
  170. status
  171. );
  172. goto error_exit;
  173. }
  174. pAdapterStatus = (tADAPTERSTATUS *)pBuffer;
  175. Count = pAdapterStatus->AdapterInfo.name_count;
  176. pNames = pAdapterStatus->Names;
  177. status = STATUS_NOT_FOUND;
  178. if (Count == 0) {
  179. (NetNameLogEvent)(
  180. ResourceHandle,
  181. LOG_ERROR,
  182. L"Name query request returned zero entries.\n"
  183. );
  184. goto error_exit;
  185. }
  186. //
  187. // Convert the ServerName to an OEM string
  188. //
  189. RtlInitUnicodeString( &unicodeName, Name );
  190. netBiosNameString.Buffer = (PCHAR)netBiosName;
  191. netBiosNameString.MaximumLength = sizeof( netBiosName );
  192. ntStatus = RtlUpcaseUnicodeStringToOemString(
  193. &netBiosNameString,
  194. &unicodeName,
  195. FALSE
  196. );
  197. if (ntStatus != STATUS_SUCCESS) {
  198. status = RtlNtStatusToDosError(ntStatus);
  199. (NetNameLogEvent)(
  200. ResourceHandle,
  201. LOG_ERROR,
  202. L"Unable to convert name %1!ws! to an OEM string, status %2!u!\n",
  203. Name,
  204. status
  205. );
  206. return(status);
  207. }
  208. //
  209. // blank fill the name
  210. //
  211. memset(&netBiosName[netBiosNameString.Length],
  212. ' ',
  213. NETBIOS_NAME_SIZE - netBiosNameString.Length);
  214. while ( Count-- ) {
  215. //
  216. // Make sure the type and name matches
  217. //
  218. if ( (pNames->name[NETBIOS_NAME_SIZE-1] == Type) &&
  219. (memcmp(pNames->name, netBiosName, NETBIOS_NAME_SIZE-1) == 0) )
  220. {
  221. switch(pNames->name_flags & 0x0F) {
  222. case REGISTERING:
  223. case REGISTERED:
  224. status = STATUS_SUCCESS;
  225. break;
  226. case DUPLICATE_DEREG:
  227. case DUPLICATE:
  228. (NetNameLogEvent)(
  229. ResourceHandle,
  230. LOG_ERROR,
  231. L"Name %1!ws!<%2!x!> is in conflict.\n",
  232. Name,
  233. Type
  234. );
  235. status = STATUS_DUPLICATE_NAME;
  236. break;
  237. case DEREGISTERED:
  238. (NetNameLogEvent)(
  239. ResourceHandle,
  240. LOG_ERROR,
  241. L"Name %1!ws!<%2!x!> was deregistered.\n",
  242. Name,
  243. Type
  244. );
  245. status = STATUS_NOT_FOUND;
  246. break;
  247. default:
  248. (NetNameLogEvent)(
  249. ResourceHandle,
  250. LOG_ERROR,
  251. L"Name %1!ws!<%2!x!> is in unknown state %3!x!.\n",
  252. Name,
  253. Type,
  254. (pNames->name_flags & 0x0F)
  255. );
  256. status = STATUS_UNSUCCESSFUL;
  257. break;
  258. }
  259. }
  260. pNames++;
  261. }
  262. if (status == STATUS_NOT_FOUND) {
  263. (NetNameLogEvent)(
  264. ResourceHandle,
  265. LOG_ERROR,
  266. L"Name %1!ws!<%2!x!> is no longer registered with NBT.\n",
  267. Name,
  268. Type
  269. );
  270. }
  271. error_exit:
  272. if ( pBuffer != &staticBuffer ) {
  273. LocalFree(pBuffer);
  274. }
  275. return(status);
  276. } // CheckNbtName
  277. //------------------------------------------------------------------------
  278. NTSTATUS
  279. DeviceIoCtrl(
  280. IN HANDLE fd,
  281. IN PVOID ReturnBuffer,
  282. IN ULONG BufferSize,
  283. IN ULONG Ioctl,
  284. IN PVOID pInput,
  285. IN ULONG SizeInput
  286. )
  287. /*++
  288. Routine Description:
  289. This procedure performs an ioctl(I_STR) on a stream.
  290. Arguments:
  291. fd - NT file handle
  292. iocp - pointer to a strioctl structure
  293. Return Value:
  294. 0 if successful, -1 otherwise.
  295. --*/
  296. {
  297. NTSTATUS status;
  298. int retval;
  299. ULONG QueryType;
  300. IO_STATUS_BLOCK iosb;
  301. status = NtDeviceIoControlFile(
  302. fd, // Handle
  303. NULL, // Event
  304. NULL, // ApcRoutine
  305. NULL, // ApcContext
  306. &iosb, // IoStatusBlock
  307. Ioctl, // IoControlCode
  308. pInput, // InputBuffer
  309. SizeInput, // InputBufferSize
  310. (PVOID) ReturnBuffer, // OutputBuffer
  311. BufferSize); // OutputBufferSize
  312. if (status == STATUS_PENDING)
  313. {
  314. status = NtWaitForSingleObject(
  315. fd, // Handle
  316. TRUE, // Alertable
  317. NULL); // Timeout
  318. if (NT_SUCCESS(status))
  319. {
  320. status = iosb.Status;
  321. }
  322. }
  323. return(status);
  324. } // DeviceIoCtrl