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.

902 lines
22 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. nteapi.c
  5. Abstract:
  6. Routines for manipulating dynamic IP Network Table Entries (NTEs)
  7. and NBT devices (interfaces).
  8. Author:
  9. Mike Massa (mikemas) 18-Mar-1996
  10. Environment:
  11. User Mode - Win32
  12. Revision History:
  13. --*/
  14. #include "clusres.h"
  15. #include <winsock2.h>
  16. #include <ipexport.h>
  17. #include <ntddip.h>
  18. #include <nteapi.h>
  19. #include <nbtioctl.h>
  20. #include <clusdef.h>
  21. #include <ntddcnet.h>
  22. #include <clusrtl.h>
  23. //
  24. // Public Routines
  25. //
  26. DWORD
  27. TcpipAddNTE(
  28. IN LPWSTR AdapterId,
  29. IN IPAddr Address,
  30. IN IPMask SubnetMask,
  31. OUT PULONG NTEContext,
  32. OUT PULONG NTEInstance
  33. )
  34. /*++
  35. Routine Description:
  36. Adds a new NTE to a specified IP interface. The target IP interface is
  37. identified by the name of the adapter associated with it.
  38. Arguments:
  39. AdapterId - A unicode string identifying the adapter/interface to which
  40. to add the new NTE.
  41. Address - The IP address to assign to the new NTE.
  42. SubnetMask - The IP subnet mask to assign to the new NTE.
  43. NTEContext - On output, contains the context value identifying the new NTE.
  44. NTEInstance - On output, contains the instance ID of the new NTE.
  45. Return Value:
  46. ERROR_SUCCESS if the operation was successful.
  47. A Windows error code otherwise.
  48. --*/
  49. {
  50. NTSTATUS status;
  51. PCLRTL_NET_ADAPTER_INFO adapterInfo;
  52. PCLRTL_NET_ADAPTER_ENUM adapterEnum;
  53. HANDLE handle;
  54. IP_ADD_NTE_REQUEST requestBuffer;
  55. PIP_ADD_NTE_RESPONSE responseBuffer =
  56. (PIP_ADD_NTE_RESPONSE) &requestBuffer;
  57. DWORD requestBufferSize = sizeof(requestBuffer);
  58. DWORD responseBufferSize = sizeof(*responseBuffer);
  59. adapterEnum = ClRtlEnumNetAdapters();
  60. if (adapterEnum != NULL) {
  61. adapterInfo = ClRtlFindNetAdapterById(adapterEnum, AdapterId);
  62. if (adapterInfo != NULL) {
  63. status = ClusResOpenDriver(&handle, DD_CLUSNET_DEVICE_NAME);
  64. if ( status == ERROR_SUCCESS ) {
  65. requestBuffer.InterfaceContext = adapterInfo->Index;
  66. requestBuffer.Address = Address;
  67. requestBuffer.SubnetMask = SubnetMask;
  68. requestBuffer.InterfaceName.Length = 0;
  69. requestBuffer.InterfaceName.MaximumLength = 0;
  70. requestBuffer.InterfaceName.Buffer = NULL;
  71. status = ClusResDoIoctl(
  72. handle,
  73. IOCTL_CLUSNET_ADD_NTE,
  74. &requestBuffer,
  75. requestBufferSize,
  76. responseBuffer,
  77. &responseBufferSize
  78. );
  79. if (NT_SUCCESS(status)) {
  80. *NTEContext = (ULONG) responseBuffer->Context;
  81. *NTEInstance = responseBuffer->Instance;
  82. status = ERROR_SUCCESS;
  83. }
  84. CloseHandle(handle);
  85. }
  86. }
  87. else {
  88. status = ERROR_INVALID_PARAMETER;
  89. }
  90. ClRtlFreeNetAdapterEnum(adapterEnum);
  91. }
  92. else {
  93. status = GetLastError();
  94. }
  95. return(status);
  96. }
  97. DWORD
  98. TcpipDeleteNTE(
  99. IN ULONG NTEContext
  100. )
  101. /*++
  102. Routine Description:
  103. Deletes a specified NTE. The target NTE must have been added using
  104. TcpipAddNTE.
  105. Arguments:
  106. NTEContext - The context value identifying the NTE to delete.
  107. Return Value:
  108. ERROR_SUCCESS if the operation was successful.
  109. A Windows error code otherwise.
  110. --*/
  111. {
  112. NTSTATUS status;
  113. HANDLE handle;
  114. IP_DELETE_NTE_REQUEST requestBuffer;
  115. DWORD requestBufferSize = sizeof(requestBuffer);
  116. DWORD responseBufferSize = 0;
  117. status = ClusResOpenDriver(&handle, DD_CLUSNET_DEVICE_NAME);
  118. if ( status != ERROR_SUCCESS ) {
  119. return status;
  120. }
  121. requestBuffer.Context = (unsigned short) NTEContext;
  122. status = ClusResDoIoctl(
  123. handle,
  124. IOCTL_CLUSNET_DELETE_NTE,
  125. &requestBuffer,
  126. requestBufferSize,
  127. NULL,
  128. &responseBufferSize
  129. );
  130. CloseHandle(handle);
  131. if (NT_SUCCESS(status)) {
  132. return(ERROR_SUCCESS);
  133. }
  134. return(RtlNtStatusToDosError(status));
  135. }
  136. DWORD
  137. TcpipSetNTEAddress(
  138. DWORD NTEContext,
  139. IPAddr Address,
  140. IPMask SubnetMask
  141. )
  142. /*++
  143. Routine Description:
  144. Sets the address of a specified NTE.
  145. Arguments:
  146. NTEContext - The context value identifying the target NTE.
  147. Address - The IP address to assign to the NTE. Assigning 0.0.0.0
  148. invalidates the NTE.
  149. SubnetMask - The IP subnet mask to assign to the NTE.
  150. Return Value:
  151. ERROR_SUCCESS if the operation was successful.
  152. A Windows error code otherwise.
  153. --*/
  154. {
  155. NTSTATUS status;
  156. HANDLE handle;
  157. IP_SET_ADDRESS_REQUEST requestBuffer;
  158. DWORD requestBufferSize = sizeof(requestBuffer);
  159. DWORD responseBufferSize = 0;
  160. status = ClusResOpenDriver(&handle, DD_CLUSNET_DEVICE_NAME);
  161. if ( status != ERROR_SUCCESS ) {
  162. return status;
  163. }
  164. requestBuffer.Context = (unsigned short) NTEContext;
  165. requestBuffer.Address = Address;
  166. requestBuffer.SubnetMask = SubnetMask;
  167. status = ClusResDoIoctl(
  168. handle,
  169. IOCTL_CLUSNET_SET_NTE_ADDRESS,
  170. &requestBuffer,
  171. requestBufferSize,
  172. NULL,
  173. &responseBufferSize
  174. );
  175. CloseHandle(handle);
  176. if (NT_SUCCESS(status)) {
  177. return(ERROR_SUCCESS);
  178. }
  179. return(RtlNtStatusToDosError(status));
  180. }
  181. DWORD
  182. TcpipGetNTEInfo(
  183. IN ULONG NTEContext,
  184. OUT PTCPIP_NTE_INFO NTEInfo
  185. )
  186. /*++
  187. Routine Description:
  188. Gathers information about a specified NTE.
  189. Arguments:
  190. NTEContext - The context value identifying the NTE to query.
  191. Return Value:
  192. ERROR_SUCCESS if the operation was successful.
  193. A Windows error code otherwise.
  194. --*/
  195. {
  196. NTSTATUS status;
  197. HANDLE handle;
  198. IP_GET_NTE_INFO_REQUEST requestBuffer;
  199. DWORD requestBufferSize = sizeof(requestBuffer);
  200. IP_GET_NTE_INFO_RESPONSE responseBuffer;
  201. DWORD responseBufferSize = sizeof(responseBuffer);
  202. status = ClusResOpenDriver(&handle, L"\\Device\\Ip");
  203. if ( status != ERROR_SUCCESS ) {
  204. return status;
  205. }
  206. requestBuffer.Context = (unsigned short) NTEContext;
  207. status = ClusResDoIoctl(
  208. handle,
  209. IOCTL_IP_GET_NTE_INFO,
  210. &requestBuffer,
  211. requestBufferSize,
  212. &responseBuffer,
  213. &responseBufferSize
  214. );
  215. CloseHandle(handle);
  216. if (NT_SUCCESS(status)) {
  217. NTEInfo->Instance = responseBuffer.Instance;
  218. NTEInfo->Address = responseBuffer.Address;
  219. NTEInfo->SubnetMask = responseBuffer.SubnetMask;
  220. NTEInfo->Flags = responseBuffer.Flags;
  221. return(ERROR_SUCCESS);
  222. }
  223. return(RtlNtStatusToDosError(status));
  224. }
  225. DWORD
  226. NbtAddInterface(
  227. OUT LPWSTR DeviceName,
  228. IN OUT LPDWORD DeviceNameSize,
  229. OUT PULONG DeviceInstance
  230. )
  231. /*++
  232. Routine Description:
  233. Adds a new NBT interface.
  234. Arguments:
  235. DeviceName - A unicode string identifying the new NBT interface.
  236. DeviceNameSize - On input, the size of theh device name buffer.
  237. On output, the size of the device name string, or
  238. the size needed to accomodate the string.
  239. DeviceInstance - A pointer to a variable into which to place the
  240. instance ID associated with the new interface.
  241. Return Value:
  242. ERROR_SUCCESS if the operation was successful.
  243. A Windows error code otherwise.
  244. --*/
  245. {
  246. NTSTATUS status;
  247. HANDLE nbthandle = (HANDLE) NULL;
  248. HANDLE cnhandle = (HANDLE) NULL;
  249. PNETBT_ADD_DEL_IF requestBuffer = NULL;
  250. DWORD requestBufferSize = 0;
  251. PNETBT_ADD_DEL_IF responseBuffer = NULL;
  252. DWORD responseBufferSize = 0;
  253. HKEY key = NULL;
  254. LPWSTR NBTDeviceName;
  255. LPWSTR exportString = NULL;
  256. DWORD exportStringSize = 0;
  257. LONG valueType;
  258. //
  259. // get a handle to NetBT's Linkage key, query the size of the
  260. // export value, allocate a buffer large enough to hold it and
  261. // read it in
  262. //
  263. status = RegOpenKeyExW(
  264. HKEY_LOCAL_MACHINE,
  265. L"SYSTEM\\CurrentControlSet\\Services\\NetBT\\Linkage",
  266. 0,
  267. KEY_READ,
  268. &key);
  269. if (status != ERROR_SUCCESS) {
  270. goto error_exit;
  271. }
  272. status = RegQueryValueExW(
  273. key,
  274. L"Export",
  275. NULL,
  276. &valueType,
  277. NULL,
  278. &exportStringSize
  279. );
  280. if (status != ERROR_SUCCESS) {
  281. goto error_exit;
  282. }
  283. exportString = LocalAlloc( LMEM_FIXED, exportStringSize );
  284. if ( exportString == NULL ) {
  285. status = ERROR_NOT_ENOUGH_MEMORY;
  286. goto error_exit;
  287. }
  288. status = RegQueryValueExW(
  289. key,
  290. L"Export",
  291. NULL,
  292. &valueType,
  293. (LPBYTE)exportString,
  294. &exportStringSize
  295. );
  296. if (status != ERROR_SUCCESS) {
  297. goto error_exit;
  298. }
  299. //
  300. // Export is a multi-sz; loop through all the interfaces
  301. // until we find one that we can open successfully.
  302. //
  303. // Hold the handle until we are done with the ioctl so
  304. // that the NBT device doesn't go away.
  305. //
  306. NBTDeviceName = exportString;
  307. do {
  308. status = ClusResOpenDriver(&nbthandle, NBTDeviceName);
  309. if ( status == ERROR_FILE_NOT_FOUND ) {
  310. //
  311. // get the next device name from the export string
  312. //
  313. NBTDeviceName += ( lstrlenW( NBTDeviceName ) + 1 );
  314. if ( *NBTDeviceName == 0 ) {
  315. status = ERROR_FILE_NOT_FOUND;
  316. break;
  317. }
  318. }
  319. } while ( status == ERROR_FILE_NOT_FOUND );
  320. if ( status != ERROR_SUCCESS ) {
  321. goto error_exit;
  322. }
  323. requestBufferSize = FIELD_OFFSET(NETBT_ADD_DEL_IF, IfName[0])
  324. + lstrlenW( NBTDeviceName ) * sizeof(WCHAR)
  325. + sizeof(UNICODE_NULL);
  326. if (requestBufferSize < sizeof(NETBT_ADD_DEL_IF)) {
  327. requestBufferSize = sizeof(NETBT_ADD_DEL_IF);
  328. }
  329. requestBuffer = LocalAlloc(LMEM_FIXED, requestBufferSize);
  330. if (requestBuffer == NULL) {
  331. status = ERROR_NOT_ENOUGH_MEMORY;
  332. goto error_exit;
  333. }
  334. RtlZeroMemory( requestBuffer, requestBufferSize );
  335. requestBuffer->Length = lstrlenW( NBTDeviceName ) * sizeof(WCHAR)
  336. + sizeof(UNICODE_NULL);
  337. RtlCopyMemory(
  338. &requestBuffer->IfName[0],
  339. NBTDeviceName,
  340. requestBuffer->Length
  341. );
  342. responseBufferSize = FIELD_OFFSET(NETBT_ADD_DEL_IF, IfName[0]) +
  343. *DeviceNameSize;
  344. if (responseBufferSize < sizeof(NETBT_ADD_DEL_IF)) {
  345. responseBufferSize = sizeof(NETBT_ADD_DEL_IF);
  346. }
  347. responseBuffer = LocalAlloc(LMEM_FIXED, responseBufferSize);
  348. if (responseBuffer == NULL) {
  349. status = ERROR_NOT_ENOUGH_MEMORY;
  350. goto error_exit;
  351. }
  352. status = ClusResOpenDriver(&cnhandle, DD_CLUSNET_DEVICE_NAME);
  353. if ( status == ERROR_SUCCESS ) {
  354. status = ClusResDoIoctl(
  355. cnhandle,
  356. IOCTL_CLUSNET_ADD_NBT_INTERFACE,
  357. requestBuffer,
  358. requestBufferSize,
  359. responseBuffer,
  360. &responseBufferSize
  361. );
  362. if (NT_SUCCESS(status)) {
  363. *DeviceNameSize = responseBuffer->Length;
  364. if (NT_SUCCESS(responseBuffer->Status)) {
  365. wcscpy(DeviceName, &(responseBuffer->IfName[0]));
  366. *DeviceInstance = responseBuffer->InstanceNumber;
  367. status = ERROR_SUCCESS;
  368. }
  369. else {
  370. status = responseBuffer->Status;
  371. }
  372. }
  373. else {
  374. status = RtlNtStatusToDosError(status);
  375. }
  376. }
  377. error_exit:
  378. if ( key ) {
  379. RegCloseKey( key );
  380. }
  381. if ( requestBuffer ) {
  382. LocalFree( requestBuffer );
  383. }
  384. if ( responseBuffer ) {
  385. LocalFree( responseBuffer );
  386. }
  387. if ( nbthandle ) {
  388. CloseHandle( nbthandle );
  389. }
  390. if ( cnhandle ) {
  391. CloseHandle( cnhandle );
  392. }
  393. return(status);
  394. }
  395. DWORD
  396. NbtDeleteInterface(
  397. IN LPWSTR DeviceName
  398. )
  399. /*++
  400. Routine Description:
  401. Deletes an NBT interface.
  402. Arguments:
  403. DeviceName - A unicode string identifying the target NBT interface.
  404. Return Value:
  405. ERROR_SUCCESS if the operation was successful.
  406. A Windows error code otherwise.
  407. --*/
  408. {
  409. NTSTATUS status;
  410. HANDLE handle = (HANDLE) NULL;
  411. DWORD responseBufferSize = 0;
  412. PNETBT_ADD_DEL_IF requestBuffer = NULL;
  413. DWORD requestBufferSize = 0;
  414. requestBufferSize = FIELD_OFFSET(NETBT_ADD_DEL_IF, IfName[0])
  415. + lstrlenW( DeviceName ) * sizeof(WCHAR)
  416. + sizeof(UNICODE_NULL);
  417. if (requestBufferSize < sizeof(NETBT_ADD_DEL_IF)) {
  418. requestBufferSize = sizeof(NETBT_ADD_DEL_IF);
  419. }
  420. requestBuffer = LocalAlloc(LMEM_FIXED, requestBufferSize);
  421. if (requestBuffer == NULL) {
  422. status = ERROR_NOT_ENOUGH_MEMORY;
  423. goto error_exit;
  424. }
  425. RtlZeroMemory( requestBuffer, requestBufferSize );
  426. requestBuffer->Length = lstrlenW( DeviceName ) * sizeof(WCHAR)
  427. + sizeof(UNICODE_NULL);
  428. RtlCopyMemory(
  429. &requestBuffer->IfName[0],
  430. DeviceName,
  431. requestBuffer->Length
  432. );
  433. status = ClusResOpenDriver(&handle, DD_CLUSNET_DEVICE_NAME);
  434. if ( status != ERROR_SUCCESS ) {
  435. goto error_exit;
  436. }
  437. status = ClusResDoIoctl(
  438. handle,
  439. IOCTL_CLUSNET_DEL_NBT_INTERFACE,
  440. requestBuffer,
  441. requestBufferSize,
  442. NULL,
  443. &responseBufferSize
  444. );
  445. if (NT_SUCCESS(status)) {
  446. status = ERROR_SUCCESS;
  447. }
  448. else {
  449. status = RtlNtStatusToDosError(status);
  450. }
  451. error_exit:
  452. if (requestBuffer) {
  453. LocalFree(requestBuffer);
  454. }
  455. if (handle) {
  456. CloseHandle(handle);
  457. }
  458. return(status);
  459. }
  460. DWORD
  461. NbtBindInterface(
  462. IN LPWSTR DeviceName,
  463. IN IPAddr Address,
  464. IN IPMask SubnetMask
  465. )
  466. /*++
  467. Routine Description:
  468. Binds a specified NBT interface to a specified IP address.
  469. Arguments:
  470. DeviceName - A unicode string identifying the target NBT interface.
  471. Address - The IP address to which bind the interface. Assigning 0.0.0.0
  472. invalidates the interface.
  473. SubnetMask - The subnet mask of the IP interface.
  474. Return Value:
  475. ERROR_SUCCESS if the operation was successful.
  476. A Windows error code otherwise.
  477. --*/
  478. {
  479. NTSTATUS status;
  480. HANDLE handle;
  481. tNEW_IP_ADDRESS requestBuffer;
  482. DWORD requestBufferSize = sizeof(requestBuffer);
  483. DWORD responseBufferSize = 0;
  484. status = ClusResOpenDriver(&handle, DeviceName);
  485. if ( status != ERROR_SUCCESS ) {
  486. return status;
  487. }
  488. requestBuffer.IpAddress = Address;
  489. requestBuffer.SubnetMask = SubnetMask;
  490. status = ClusResDoIoctl(
  491. handle,
  492. IOCTL_NETBT_NEW_IPADDRESS,
  493. &requestBuffer,
  494. requestBufferSize,
  495. NULL,
  496. &responseBufferSize
  497. );
  498. CloseHandle(handle);
  499. if (NT_SUCCESS(status)) {
  500. return(ERROR_SUCCESS);
  501. }
  502. return(RtlNtStatusToDosError(status));
  503. }
  504. DWORD
  505. NbtSetWinsAddrInterface(
  506. IN LPWSTR DeviceName,
  507. IN IPAddr PrWinsAddress,
  508. IN IPAddr SecWinsAddress
  509. )
  510. /*++
  511. Routine Description:
  512. Sets the WINS addrs for a given Nbt Interface.
  513. Arguments:
  514. DeviceName - A unicode string identifying the target NBT interface.
  515. PrWinsAddress - Primary WINS addr
  516. SecWinsAddress - Secondary WINS addr
  517. Return Value:
  518. ERROR_SUCCESS if the operation was successful.
  519. A Windows error code otherwise.
  520. --*/
  521. {
  522. NTSTATUS status;
  523. HANDLE handle;
  524. NETBT_SET_WINS_ADDR requestBuffer;
  525. DWORD requestBufferSize = sizeof(requestBuffer);
  526. DWORD responseBufferSize = 0;
  527. status = ClusResOpenDriver(&handle, DeviceName);
  528. if ( status != ERROR_SUCCESS ) {
  529. return status;
  530. }
  531. requestBuffer.PrimaryWinsAddr = ntohl(PrWinsAddress);
  532. requestBuffer.SecondaryWinsAddr = ntohl(SecWinsAddress);
  533. status = ClusResDoIoctl(
  534. handle,
  535. IOCTL_NETBT_SET_WINS_ADDRESS,
  536. &requestBuffer,
  537. requestBufferSize,
  538. NULL,
  539. &responseBufferSize
  540. );
  541. CloseHandle(handle);
  542. if (NT_SUCCESS(status)) {
  543. return(ERROR_SUCCESS);
  544. }
  545. return(RtlNtStatusToDosError(status));
  546. }
  547. DWORD
  548. NbtGetWinsAddresses(
  549. IN LPWSTR DeviceName,
  550. OUT IPAddr * PrimaryWinsServer,
  551. OUT IPAddr * SecondaryWinsServer
  552. )
  553. /*++
  554. Routine Description:
  555. Returns the addresses of the WINS servers for which the specified device
  556. is configured.
  557. Arguments:
  558. DeviceName - A unicode string identifying the target NBT interface.
  559. PrimaryWinsServer - A pointer to a variable into which to place the address
  560. of the primary WINS server.
  561. SecondaryWinsServer - A pointer to a variable into which to place the address
  562. of the primary WINS server.
  563. Return Value:
  564. ERROR_SUCCESS if the operation was successful.
  565. A Windows error code otherwise.
  566. --*/
  567. {
  568. NTSTATUS status;
  569. HANDLE handle;
  570. tWINS_ADDRESSES responseBuffer;
  571. DWORD responseBufferSize = sizeof(responseBuffer);
  572. status = ClusResOpenDriver(&handle, DeviceName);
  573. if ( status != ERROR_SUCCESS ) {
  574. return status;
  575. }
  576. status = ClusResDoIoctl(
  577. handle,
  578. IOCTL_NETBT_GET_WINS_ADDR,
  579. NULL,
  580. 0,
  581. &responseBuffer,
  582. &responseBufferSize
  583. );
  584. CloseHandle(handle);
  585. if (NT_SUCCESS(status)) {
  586. *PrimaryWinsServer = htonl(responseBuffer.PrimaryWinsServer);
  587. *SecondaryWinsServer = htonl(responseBuffer.BackupWinsServer);
  588. return(ERROR_SUCCESS);
  589. }
  590. return(RtlNtStatusToDosError(status));
  591. }
  592. DWORD
  593. NbtGetInterfaceInfo(
  594. IN LPWSTR DeviceName,
  595. OUT IPAddr * Address,
  596. OUT PULONG DeviceInstance
  597. )
  598. /*++
  599. Routine Description:
  600. Returns the IP address to which an NBT interface is bound and the interface
  601. instance ID.
  602. Arguments:
  603. DeviceName - A unicode string identifying the target NBT interface.
  604. Address - A pointer to the location in which to store the address of the
  605. interface.
  606. DeviceInstance - A pointer to the location in which to store the instance ID
  607. associated with the interface.
  608. Return Value:
  609. ERROR_SUCCESS if the operation was successful.
  610. A Windows error code otherwise.
  611. --*/
  612. {
  613. NTSTATUS status;
  614. HANDLE handle;
  615. IPAddr address;
  616. NETBT_ADD_DEL_IF responseBuffer;
  617. DWORD responseBufferSize;
  618. status = ClusResOpenDriver(&handle, DeviceName);
  619. if ( status != ERROR_SUCCESS ) {
  620. return status;
  621. }
  622. responseBufferSize = sizeof(address);
  623. status = ClusResDoIoctl(
  624. handle,
  625. IOCTL_NETBT_GET_IP_ADDRS,
  626. NULL,
  627. 0,
  628. &address,
  629. &responseBufferSize
  630. );
  631. if (!((status == STATUS_SUCCESS) || (status == STATUS_BUFFER_OVERFLOW))) {
  632. CloseHandle(handle);
  633. return(RtlNtStatusToDosError(status));
  634. }
  635. *Address = htonl(address);
  636. responseBufferSize = sizeof(responseBuffer);
  637. status = ClusResDoIoctl(
  638. handle,
  639. IOCTL_NETBT_QUERY_INTERFACE_INSTANCE,
  640. NULL,
  641. 0,
  642. &responseBuffer,
  643. &responseBufferSize
  644. );
  645. CloseHandle(handle);
  646. if (status == STATUS_SUCCESS) {
  647. if (responseBuffer.Status == STATUS_SUCCESS) {
  648. *DeviceInstance = responseBuffer.InstanceNumber;
  649. }
  650. else {
  651. status = RtlNtStatusToDosError(responseBuffer.Status);
  652. }
  653. }
  654. else {
  655. status = RtlNtStatusToDosError(status);
  656. }
  657. return(status);
  658. }