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.

715 lines
18 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. nbtmgmt.c
  5. Abstract:
  6. Routines for managing NBT interfaces.
  7. Author:
  8. David Dion (daviddio) December 9, 1999
  9. Revision History:
  10. Who When What
  11. -------- -------- ----------------------------------------------
  12. daviddio 12-09-99 created
  13. Notes:
  14. --*/
  15. #include "clusnet.h"
  16. #include "nbtmgmt.tmh"
  17. //
  18. // Types
  19. //
  20. typedef struct _NBT_IF {
  21. LIST_ENTRY Linkage;
  22. ULONG InstanceNumber;
  23. PFILE_OBJECT FileObject;
  24. WCHAR IfName[1];
  25. } NBT_IF, *PNBT_IF;
  26. //
  27. // Data
  28. //
  29. LIST_ENTRY NbtIfList = {NULL,NULL};
  30. KSPIN_LOCK NbtIfListLock = 0;
  31. //
  32. // Local function prototypes
  33. //
  34. NTSTATUS
  35. NbtIfOpenDevice(
  36. IN LPWSTR DeviceName,
  37. OUT PFILE_OBJECT *FileObject
  38. );
  39. NTSTATUS
  40. NbtIfIssueDeviceControl(
  41. IN PFILE_OBJECT FileObject,
  42. IN ULONG IoControlCode,
  43. IN PVOID InputBuffer,
  44. IN ULONG InputBufferLength,
  45. IN PVOID OutputBuffer,
  46. IN ULONG OutputBufferLength
  47. );
  48. PNBT_IF
  49. NbtFindIf(
  50. IN LPWSTR DeviceName,
  51. IN ULONG Length
  52. );
  53. #ifdef ALLOC_PRAGMA
  54. #pragma alloc_text(INIT, NbtIfLoad)
  55. #pragma alloc_text(PAGE, NbtIfOpenDevice)
  56. #pragma alloc_text(PAGE, NbtIfIssueDeviceControl)
  57. #endif // ALLOC_PRAGMA
  58. NTSTATUS
  59. NbtIfIssueDeviceControl(
  60. IN PFILE_OBJECT FileObject,
  61. IN ULONG IoControlCode,
  62. IN PVOID InputBuffer,
  63. IN ULONG InputBufferLength,
  64. IN PVOID OutputBuffer,
  65. IN ULONG OutputBufferLength
  66. )
  67. /*++
  68. Routine Description:
  69. Arguments:
  70. Return Value:
  71. NTSTATUS -- Indicates the status of the request.
  72. --*/
  73. {
  74. NTSTATUS status = STATUS_SUCCESS;
  75. IO_STATUS_BLOCK iosb;
  76. KEVENT event;
  77. PIRP irp;
  78. PAGED_CODE();
  79. KeInitializeEvent(&event, SynchronizationEvent, FALSE);
  80. irp = IoBuildDeviceIoControlRequest(
  81. IoControlCode,
  82. IoGetRelatedDeviceObject(FileObject),
  83. InputBuffer,
  84. InputBufferLength,
  85. OutputBuffer,
  86. OutputBufferLength,
  87. FALSE,
  88. &event,
  89. &iosb
  90. );
  91. if (irp != NULL) {
  92. status = IoCallDriver(
  93. IoGetRelatedDeviceObject(FileObject),
  94. irp
  95. );
  96. if (status == STATUS_PENDING) {
  97. status = KeWaitForSingleObject(
  98. &event,
  99. Executive,
  100. KernelMode,
  101. FALSE,
  102. NULL
  103. );
  104. CnAssert(status == STATUS_SUCCESS);
  105. status = iosb.Status;
  106. }
  107. } else {
  108. status = STATUS_INSUFFICIENT_RESOURCES;
  109. IF_CNDBG(CN_DEBUG_NTE) {
  110. CNPRINT((
  111. "[Clusnet] Failed to build NBT request irp, status %lx\n",
  112. status
  113. ));
  114. }
  115. CnTrace(NTEMGMT_DETAIL, NbtIfIrpAllocFailed,
  116. "[Clusnet] Failed to build NBT request irp, status %!status!.",
  117. status // LOGSTATUS
  118. );
  119. }
  120. return(status);
  121. } // NbtIfIssueDeviceControl
  122. NTSTATUS
  123. NbtIfOpenDevice(
  124. IN LPWSTR DeviceName,
  125. OUT PFILE_OBJECT *FileObject
  126. )
  127. {
  128. UNICODE_STRING nameString;
  129. OBJECT_ATTRIBUTES objectAttributes;
  130. IO_STATUS_BLOCK iosb;
  131. HANDLE handle;
  132. NTSTATUS status;
  133. *FileObject = (PFILE_OBJECT) NULL;
  134. //
  135. // Open the NBT device.
  136. //
  137. RtlInitUnicodeString(&nameString, DeviceName);
  138. InitializeObjectAttributes(
  139. &objectAttributes,
  140. &nameString,
  141. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  142. (HANDLE) NULL,
  143. (PSECURITY_DESCRIPTOR) NULL
  144. );
  145. status = ZwCreateFile(
  146. &handle,
  147. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  148. &objectAttributes,
  149. &iosb,
  150. NULL,
  151. FILE_ATTRIBUTE_NORMAL,
  152. FILE_SHARE_READ | FILE_SHARE_WRITE,
  153. FILE_OPEN_IF,
  154. 0,
  155. NULL,
  156. 0
  157. );
  158. if (NT_SUCCESS(status)) {
  159. // Get a pointer to the corresponding file object. The file
  160. // object pointer is used to issue ioctls to the device.
  161. status = ObReferenceObjectByHandle(
  162. handle,
  163. 0,
  164. NULL,
  165. KernelMode,
  166. FileObject,
  167. NULL
  168. );
  169. if (!NT_SUCCESS(status)) {
  170. *FileObject = (PFILE_OBJECT) NULL;
  171. CnTrace(NTEMGMT_DETAIL, NbtIfObDerefFailed,
  172. "[Clusnet] Failed to deref NBT device handle %p "
  173. "for device %ls, status %!status!.",
  174. handle,
  175. DeviceName, // LOGWSTR
  176. status // LOGSTATUS
  177. );
  178. IF_CNDBG(CN_DEBUG_INIT) {
  179. CNPRINT(("[Clusnet] Failed to deref NBT device handle %p "
  180. "for device %S, status %lx\n",
  181. handle, DeviceName, status));
  182. }
  183. }
  184. ZwClose(handle);
  185. } else {
  186. CnTrace(NTEMGMT_DETAIL, NbtIfOpenDeviceFailed,
  187. "[Clusnet] Failed to open NBT device %ls, status %!status!.",
  188. DeviceName, // LOGWSTR
  189. status // LOGSTATUS
  190. );
  191. IF_CNDBG(CN_DEBUG_INIT) {
  192. CNPRINT(("[Clusnet] Failed to open NBT device %S, status %lx\n",
  193. DeviceName, status));
  194. }
  195. }
  196. return(status);
  197. } // NbtIfOpenDevice
  198. PNBT_IF
  199. NbtFindIf(
  200. LPWSTR DeviceName,
  201. ULONG Length
  202. )
  203. {
  204. PNBT_IF nbtif;
  205. PLIST_ENTRY entry;
  206. for ( entry = NbtIfList.Flink;
  207. entry != &NbtIfList;
  208. entry = entry->Flink
  209. )
  210. {
  211. nbtif = CONTAINING_RECORD(entry, NBT_IF, Linkage);
  212. if (RtlCompareMemory(
  213. &nbtif->IfName[0],
  214. DeviceName,
  215. Length - sizeof(UNICODE_NULL)
  216. ) == Length - sizeof(UNICODE_NULL)) {
  217. return(nbtif);
  218. }
  219. }
  220. return(NULL);
  221. } // NbtFindIf
  222. //
  223. // Public Routines
  224. //
  225. NTSTATUS
  226. NbtIfLoad(
  227. VOID
  228. )
  229. {
  230. IF_CNDBG(CN_DEBUG_INIT) {
  231. CNPRINT(("[Clusnet] NBT support loading.\n"));
  232. }
  233. KeInitializeSpinLock(&NbtIfListLock);
  234. InitializeListHead(&NbtIfList);
  235. return(STATUS_SUCCESS);
  236. } // NbtIfLoad
  237. VOID
  238. NbtIfShutdown(
  239. VOID
  240. )
  241. {
  242. NTSTATUS status;
  243. KIRQL irql;
  244. PLIST_ENTRY entry;
  245. PNBT_IF nbtif;
  246. LIST_ENTRY deletelist;
  247. IF_CNDBG(CN_DEBUG_INIT) {
  248. CNPRINT(("[Clusnet] Destroying all cluster NBT interfaces...\n"));
  249. }
  250. KeAcquireSpinLock( &NbtIfListLock, &irql );
  251. //
  252. // Move the contents of NbtIfList to the delete list
  253. //
  254. if (!IsListEmpty( &NbtIfList )) {
  255. RtlCopyMemory( &deletelist, &NbtIfList, sizeof(NbtIfList) );
  256. deletelist.Flink->Blink = &deletelist;
  257. deletelist.Blink->Flink = &deletelist;
  258. InitializeListHead( &NbtIfList );
  259. } else {
  260. InitializeListHead( &deletelist );
  261. }
  262. KeReleaseSpinLock( &NbtIfListLock, irql );
  263. while (!IsListEmpty( &deletelist )) {
  264. entry = RemoveHeadList( &deletelist );
  265. nbtif = CONTAINING_RECORD( entry, NBT_IF, Linkage );
  266. status = NbtIfIssueDeviceControl(
  267. nbtif->FileObject,
  268. IOCTL_NETBT_DELETE_INTERFACE,
  269. NULL, // request
  270. 0, // request size
  271. NULL, // response
  272. 0 // response size
  273. );
  274. if (status != STATUS_SUCCESS) {
  275. LPWSTR deviceName = (LPWSTR) &nbtif->IfName[0];
  276. CnTrace(NTEMGMT_DETAIL, NbtIfDeleteFailed,
  277. "[Clusnet] Failed to delete NBT interface %ls "
  278. "file object %p, status %!status!.",
  279. deviceName, // LOGWSTR
  280. nbtif->FileObject,
  281. status // LOGSTATUS
  282. );
  283. IF_CNDBG(CN_DEBUG_NTE) {
  284. CNPRINT(("[Clusnet] Failed to delete NBT interface %S "
  285. "file object %p, status %lx\n",
  286. deviceName,
  287. nbtif->FileObject,
  288. status
  289. ));
  290. }
  291. } else {
  292. LPWSTR deviceName = (LPWSTR) &nbtif->IfName[0];
  293. CnTrace(NTEMGMT_DETAIL, NbtIfDeleted,
  294. "[Clusnet] Delete NBT interface %ls.",
  295. deviceName // LOGWSTR
  296. );
  297. IF_CNDBG(CN_DEBUG_NTE) {
  298. CNPRINT(("[Clusnet] Deleted NBT interface %S.\n",
  299. deviceName
  300. ));
  301. }
  302. }
  303. // Release the reference that was taken when the NBT device
  304. // was created.
  305. ObDereferenceObject(nbtif->FileObject);
  306. CnFreePool(nbtif);
  307. }
  308. CnTrace(NTEMGMT_DETAIL, NbtIfShutdownIfsDeleted,
  309. "[Clusnet] All cluster NBT interfaces destroyed."
  310. );
  311. IF_CNDBG(CN_DEBUG_INIT) {
  312. CNPRINT(("[Clusnet] All cluster NBT interfaces destroyed.\n"));
  313. }
  314. return;
  315. } // NbtIfShutdown
  316. NTSTATUS
  317. NbtAddIf(
  318. IN PNETBT_ADD_DEL_IF Request,
  319. IN ULONG RequestSize,
  320. OUT PNETBT_ADD_DEL_IF Response,
  321. IN OUT PULONG ResponseSize
  322. )
  323. {
  324. NTSTATUS status;
  325. PFILE_OBJECT requestFileObject;
  326. PFILE_OBJECT responseFileObject;
  327. PNBT_IF nbtif;
  328. KIRQL irql;
  329. CnTrace(NTEMGMT_DETAIL, NbtIfAdding,
  330. "[Clusnet] Creating new NBT interface for NBT device %ls.",
  331. Request->IfName // LOGWSTR
  332. );
  333. IF_CNDBG(CN_DEBUG_NTE) {
  334. CNPRINT((
  335. "[Clusnet] Creating new NBT interface for NBT device %S...\n",
  336. Request->IfName
  337. ));
  338. }
  339. //
  340. // Open the NBT device specified in the request. This corresponds
  341. // to a particular TCP/IP interface.
  342. //
  343. status = NbtIfOpenDevice( Request->IfName, &requestFileObject );
  344. if (NT_SUCCESS(status)) {
  345. //
  346. // Allocate a record for the NBT interface
  347. //
  348. nbtif = CnAllocatePool(
  349. FIELD_OFFSET( NBT_IF, IfName[0] )
  350. + Response->Length
  351. );
  352. if (nbtif != NULL) {
  353. //
  354. // Issue an ioctl to create a new NBT interface.
  355. // The response contains the name of the new NBT
  356. // interface device object.
  357. //
  358. status = NbtIfIssueDeviceControl(
  359. requestFileObject,
  360. IOCTL_NETBT_ADD_INTERFACE,
  361. NULL,
  362. 0,
  363. Response,
  364. *ResponseSize
  365. );
  366. if (NT_SUCCESS(status)
  367. && NT_SUCCESS(Response->Status)) {
  368. //
  369. // Open the new NBT interface device object.
  370. //
  371. status = NbtIfOpenDevice(
  372. (LPWSTR) Response->IfName,
  373. &responseFileObject
  374. );
  375. if (NT_SUCCESS(status)) {
  376. LPWSTR deviceName = (LPWSTR) &Response->IfName[0];
  377. //
  378. // Store the interface name, instance, and
  379. // file object corresponding to the new NBT
  380. // interface device object.
  381. //
  382. RtlZeroMemory(
  383. nbtif,
  384. FIELD_OFFSET( NBT_IF, IfName[0] ) + Response->Length
  385. );
  386. RtlCopyMemory(
  387. &nbtif->IfName[0],
  388. deviceName,
  389. Response->Length
  390. );
  391. nbtif->InstanceNumber = Response->InstanceNumber;
  392. nbtif->FileObject = responseFileObject;
  393. KeAcquireSpinLock(&NbtIfListLock, &irql);
  394. InsertTailList(&NbtIfList, &(nbtif->Linkage));
  395. KeReleaseSpinLock(&NbtIfListLock, irql);
  396. CnTrace(NTEMGMT_DETAIL, NbtIfAdded,
  397. "[Clusnet] Created new NBT interface device %ls.",
  398. deviceName // LOGWSTR
  399. );
  400. IF_CNDBG(CN_DEBUG_NTE) {
  401. CNPRINT((
  402. "[Clusnet] Created new NBT interface "
  403. "device %S.\n",
  404. deviceName
  405. ));
  406. }
  407. } else {
  408. CnTrace(NTEMGMT_DETAIL, NbtIfAddOpenNewFailed,
  409. "[Clusnet] Failed to open NBT device for new "
  410. "interface %ls, status %!status!.",
  411. Request->IfName, // LOGWSTR
  412. status // LOGSTATUS
  413. );
  414. IF_CNDBG(CN_DEBUG_NTE) {
  415. CNPRINT((
  416. "[Clusnet] Failed to open NBT device for "
  417. "new interface %S: %x\n",
  418. Request->IfName,
  419. status
  420. ));
  421. }
  422. CnFreePool(nbtif);
  423. }
  424. } else {
  425. CnTrace(NTEMGMT_DETAIL, NbtIfAddFailed,
  426. "[Clusnet] Failed to add NBT interface for "
  427. "NBT device %ls, status %!status!, %!status!.",
  428. Request->IfName, // LOGWSTR
  429. status, // LOGSTATUS
  430. Response->Status // LOGSTATUS
  431. );
  432. IF_CNDBG(CN_DEBUG_NTE) {
  433. CNPRINT((
  434. "[Clusnet] Failed to add NBT interface "
  435. "for NBT device %S: %x, %x\n",
  436. Request->IfName,
  437. status,
  438. Response->Status
  439. ));
  440. }
  441. CnFreePool(nbtif);
  442. }
  443. } else {
  444. status = STATUS_INSUFFICIENT_RESOURCES;
  445. CnTrace(NTEMGMT_DETAIL, NbtIfAddAllocFailed,
  446. "[Clusnet] Failed to allocate record for NBT "
  447. "interface %ls, status %!status!.",
  448. Request->IfName, // LOGWSTR
  449. status // LOGSTATUS
  450. );
  451. }
  452. //
  453. // Release reference on NBT device object corresponding
  454. // to TCP/IP interface.
  455. //
  456. ObDereferenceObject(requestFileObject);
  457. } else {
  458. CnTrace(NTEMGMT_DETAIL, NbtIfAddOpenFailed,
  459. "[Clusnet] Failed to open NBT device %ls for add, "
  460. "status %!status!.",
  461. Request->IfName, // LOGWSTR
  462. status // LOGSTATUS
  463. );
  464. IF_CNDBG(CN_DEBUG_NTE) {
  465. CNPRINT((
  466. "[Clusnet] Failed to open NBT device %S: %x\n",
  467. Request->IfName,
  468. status
  469. ));
  470. }
  471. }
  472. return(status);
  473. } // NbtAddIf
  474. NTSTATUS
  475. NbtDeleteIf(
  476. IN PNETBT_ADD_DEL_IF Request,
  477. IN ULONG RequestSize
  478. )
  479. {
  480. NTSTATUS status;
  481. PNBT_IF nbtif;
  482. KIRQL irql;
  483. ULONG responseSize = 0;
  484. CnTrace(NTEMGMT_DETAIL, NbtIfDeleting,
  485. "[Clusnet] Deleting NBT interface %ls.",
  486. Request->IfName // LOGWSTR
  487. );
  488. IF_CNDBG(CN_DEBUG_NTE) {
  489. CNPRINT((
  490. "[Clusnet] Attempting to delete NBT interface %S...\n",
  491. (LPWSTR) &Request->IfName[0]
  492. ));
  493. }
  494. KeAcquireSpinLock(&NbtIfListLock, &irql);
  495. nbtif = NbtFindIf( (LPWSTR) &Request->IfName[0], Request->Length );
  496. if (nbtif != NULL) {
  497. RemoveEntryList(&(nbtif->Linkage));
  498. KeReleaseSpinLock(&NbtIfListLock, irql);
  499. status = NbtIfIssueDeviceControl(
  500. nbtif->FileObject,
  501. IOCTL_NETBT_DELETE_INTERFACE,
  502. NULL, // request
  503. 0, // request size
  504. NULL, // response
  505. 0 // response size
  506. );
  507. if (status != STATUS_SUCCESS) {
  508. LPWSTR deviceName = (LPWSTR) &nbtif->IfName[0];
  509. CnTrace(NTEMGMT_DETAIL, NbtIfDeleteFailed,
  510. "[Clusnet] Failed to delete NBT interface %ls "
  511. "file object %p, status %!status!.",
  512. deviceName, // LOGWSTR
  513. nbtif->FileObject,
  514. status // LOGSTATUS
  515. );
  516. IF_CNDBG(CN_DEBUG_NTE) {
  517. CNPRINT(("[Clusnet] Failed to delete NBT interface %S "
  518. "file object %p, status %lx\n",
  519. deviceName,
  520. nbtif->FileObject,
  521. status
  522. ));
  523. }
  524. } else {
  525. LPWSTR deviceName = (LPWSTR) &nbtif->IfName[0];
  526. CnTrace(NTEMGMT_DETAIL, NbtIfDeleted,
  527. "[Clusnet] Delete NBT interface %ls.",
  528. deviceName // LOGWSTR
  529. );
  530. IF_CNDBG(CN_DEBUG_NTE) {
  531. CNPRINT(("[Clusnet] Deleted NBT interface %S.\n",
  532. deviceName
  533. ));
  534. }
  535. }
  536. // Release the reference that was taken when the NBT device
  537. // was created.
  538. ObDereferenceObject(nbtif->FileObject);
  539. CnFreePool(nbtif);
  540. } else {
  541. KeReleaseSpinLock(&NbtIfListLock, irql);
  542. CnTrace(NTEMGMT_DETAIL, NbtIfDeleteNotFound,
  543. "[Clusnet] NBT interface %ls does not exist.",
  544. Request->IfName // LOGWSTR
  545. );
  546. IF_CNDBG(CN_DEBUG_NTE) {
  547. CNPRINT(("[Clusnet] NBT interface %S does not exist.\n",
  548. (LPWSTR) &Request->IfName[0]));
  549. }
  550. status = STATUS_UNSUCCESSFUL;
  551. }
  552. return (status);
  553. } // NbtDeleteIf