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.

604 lines
16 KiB

  1. //++
  2. //
  3. // Copyright (C) Microsoft Corporation, 1987 - 1999
  4. //
  5. // Module Name:
  6. //
  7. // global.c
  8. //
  9. // Abstract:
  10. //
  11. // Test to ensure that a workstation has network (IP) connectivity to
  12. // the outside.
  13. //
  14. // Author:
  15. //
  16. // 15-Dec-1997 (cliffv)
  17. // Anilth - 4-20-1998
  18. //
  19. // Environment:
  20. //
  21. // User mode only.
  22. // Contains NT-specific code.
  23. //
  24. // Revision History:
  25. //
  26. // 1-June-1998 (denisemi) add DnsServerHasDCRecords to check DC dns records
  27. // registration
  28. //
  29. // 26-June-1998 (t-rajkup) add general tcp/ip , dhcp and routing,
  30. // winsock, ipx, wins and netbt information.
  31. //--
  32. //
  33. // Common include files.
  34. //
  35. #include "precomp.h"
  36. #include "ipcfgtest.h"
  37. /*!--------------------------------------------------------------------------
  38. WsaInitialize
  39. Initialize winsock.
  40. Author: NSun
  41. ---------------------------------------------------------------------------*/
  42. int
  43. WsaInitialize(
  44. NETDIAG_PARAMS * pParams,
  45. NETDIAG_RESULT *pResults
  46. )
  47. {
  48. int iStatus;
  49. WORD wVersionRequested;
  50. int err;
  51. WSADATA wsaData;
  52. // Requesting version 1.1
  53. // ----------------------------------------------------------------
  54. wVersionRequested = MAKEWORD( 1, 1 );
  55. iStatus = WSAStartup( wVersionRequested, &wsaData );
  56. if (iStatus != 0)
  57. {
  58. PrintMessage(pParams, IDS_GLOBAL_WSA_WSAStartup_Failed);
  59. // TracePrintf(_T("WSAStartup (1.1) failed with WinSock error %d"),
  60. // iStatus);
  61. return iStatus;
  62. }
  63. if ( (LOBYTE( wsaData.wVersion ) != 1) ||
  64. (HIBYTE( wsaData.wVersion ) != 1) )
  65. {
  66. WSACleanup();
  67. PrintMessage(pParams, IDS_GLOBAL_WSA_BadWSAVersion,
  68. wsaData.wVersion);
  69. return WSANOTINITIALISED;
  70. }
  71. // Set the results of the WSA call into the results structure
  72. // ----------------------------------------------------------------
  73. pResults->Global.wsaData = wsaData;
  74. return NO_ERROR;
  75. }
  76. NET_API_STATUS
  77. BrDgReceiverIoControl(
  78. IN HANDLE FileHandle,
  79. IN ULONG DgReceiverControlCode,
  80. IN PLMDR_REQUEST_PACKET Drp,
  81. IN ULONG DrpSize,
  82. IN PVOID SecondBuffer OPTIONAL,
  83. IN ULONG SecondBufferLength,
  84. OUT PULONG Information OPTIONAL
  85. )
  86. /*++
  87. Routine Description:
  88. Arguments:
  89. FileHandle - Supplies a handle to the file or device on which the service
  90. is being performed.
  91. DgReceiverControlCode - Supplies the NtDeviceIoControlFile function code
  92. given to the datagram receiver.
  93. Drp - Supplies the datagram receiver request packet.
  94. DrpSize - Supplies the length of the datagram receiver request packet.
  95. SecondBuffer - Supplies the second buffer in call to NtDeviceIoControlFile.
  96. SecondBufferLength - Supplies the length of the second buffer.
  97. Information - Returns the information field of the I/O status block.
  98. Return Value:
  99. NET_API_STATUS - NERR_Success or reason for failure.
  100. --*/
  101. {
  102. NTSTATUS ntstatus;
  103. IO_STATUS_BLOCK IoStatusBlock;
  104. PLMDR_REQUEST_PACKET RealDrp;
  105. HANDLE CompletionEvent;
  106. LPBYTE Where;
  107. if (FileHandle == NULL) {
  108. return ERROR_NOT_SUPPORTED;
  109. }
  110. //
  111. // Allocate a copy of the request packet where we can put the transport and
  112. // emulated domain name in the packet itself.
  113. //
  114. RealDrp = Malloc( DrpSize+
  115. Drp->TransportName.Length+sizeof(WCHAR)+
  116. Drp->EmulatedDomainName.Length+sizeof(WCHAR) );
  117. if (RealDrp == NULL) {
  118. return ERROR_NOT_ENOUGH_MEMORY;
  119. }
  120. ZeroMemory( RealDrp, DrpSize+
  121. Drp->TransportName.Length+sizeof(WCHAR)+
  122. Drp->EmulatedDomainName.Length+sizeof(WCHAR) );
  123. //
  124. // Copy the request packet into the local copy.
  125. //
  126. RtlCopyMemory(RealDrp, Drp, DrpSize);
  127. RealDrp->Version = LMDR_REQUEST_PACKET_VERSION_DOM;
  128. Where = (LPBYTE)RealDrp+DrpSize;
  129. if (Drp->TransportName.Length != 0) {
  130. RealDrp->TransportName.Buffer = (LPWSTR)Where;
  131. RealDrp->TransportName.MaximumLength = Drp->TransportName.Length+sizeof(WCHAR);
  132. RtlCopyUnicodeString(&RealDrp->TransportName, &Drp->TransportName);
  133. Where += RealDrp->TransportName.MaximumLength;
  134. }
  135. if (Drp->EmulatedDomainName.Length != 0) {
  136. RealDrp->EmulatedDomainName.Buffer = (LPWSTR)Where;
  137. RealDrp->EmulatedDomainName.MaximumLength = Drp->EmulatedDomainName.Length+sizeof(WCHAR);
  138. RtlCopyUnicodeString(&RealDrp->EmulatedDomainName, &Drp->EmulatedDomainName);
  139. Where += RealDrp->EmulatedDomainName.MaximumLength;
  140. }
  141. //
  142. // Create a completion event
  143. //
  144. CompletionEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  145. if (CompletionEvent == NULL) {
  146. Free(RealDrp);
  147. return(GetLastError());
  148. }
  149. //
  150. // Send the request to the Datagram Receiver DD.
  151. //
  152. ntstatus = NtDeviceIoControlFile(
  153. FileHandle,
  154. CompletionEvent,
  155. NULL,
  156. NULL,
  157. &IoStatusBlock,
  158. DgReceiverControlCode,
  159. RealDrp,
  160. (ULONG)(Where-(LPBYTE)RealDrp),
  161. SecondBuffer,
  162. SecondBufferLength
  163. );
  164. if (NT_SUCCESS(ntstatus)) {
  165. //
  166. // If pending was returned, then wait until the request completes.
  167. //
  168. if (ntstatus == STATUS_PENDING) {
  169. do {
  170. ntstatus = WaitForSingleObjectEx(CompletionEvent, 0xffffffff, TRUE);
  171. } while ( ntstatus == WAIT_IO_COMPLETION );
  172. }
  173. if (NT_SUCCESS(ntstatus)) {
  174. ntstatus = IoStatusBlock.Status;
  175. }
  176. }
  177. if (ARGUMENT_PRESENT(Information)) {
  178. *Information = (ULONG)IoStatusBlock.Information;
  179. }
  180. Free(RealDrp);
  181. CloseHandle(CompletionEvent);
  182. return NetpNtStatusToApiStatus(ntstatus);
  183. }
  184. NET_API_STATUS
  185. DeviceControlGetInfo(
  186. IN HANDLE FileHandle,
  187. IN ULONG DeviceControlCode,
  188. IN PVOID RequestPacket,
  189. IN ULONG RequestPacketLength,
  190. OUT LPVOID *OutputBuffer,
  191. IN ULONG PreferedMaximumLength,
  192. IN ULONG BufferHintSize,
  193. OUT PULONG Information OPTIONAL
  194. )
  195. /*++
  196. Routine Description:
  197. This function allocates the buffer and fill it with the information
  198. that is retrieved from the datagram receiver.
  199. Arguments:
  200. DeviceDriverType - Supplies the value which indicates whether to call
  201. the datagram receiver.
  202. FileHandle - Supplies a handle to the file or device of which to get
  203. information about.
  204. DeviceControlCode - Supplies the NtFsControlFile or NtIoDeviceControlFile
  205. function control code.
  206. RequestPacket - Supplies a pointer to the device request packet.
  207. RrequestPacketLength - Supplies the length of the device request packet.
  208. OutputBuffer - Returns a pointer to the buffer allocated by this routine
  209. which contains the use information requested. This pointer is set to
  210. NULL if return code is not NERR_Success.
  211. PreferedMaximumLength - Supplies the number of bytes of information to
  212. return in the buffer. If this value is MAXULONG, we will try to
  213. return all available information if there is enough memory resource.
  214. BufferHintSize - Supplies the hint size of the output buffer so that the
  215. memory allocated for the initial buffer will most likely be large
  216. enough to hold all requested data.
  217. Information - Returns the information code from the NtFsControlFile or
  218. NtIoDeviceControlFile call.
  219. Return Value:
  220. NET_API_STATUS - NERR_Success or reason for failure.
  221. --*/
  222. {
  223. NET_API_STATUS status;
  224. NTSTATUS ntstatus;
  225. DWORD OutputBufferLength;
  226. DWORD TotalBytesNeeded = 1;
  227. ULONG OriginalResumeKey;
  228. IO_STATUS_BLOCK IoStatusBlock;
  229. PLMDR_REQUEST_PACKET Drrp = (PLMDR_REQUEST_PACKET) RequestPacket;
  230. HANDLE CompletionEvent;
  231. #define INITIAL_ALLOCATION_SIZE 48*1024 // First attempt size (48K)
  232. #define FUDGE_FACTOR_SIZE 1024 // Second try TotalBytesNeeded
  233. // plus this amount
  234. OriginalResumeKey = Drrp->Parameters.EnumerateNames.ResumeHandle;
  235. //
  236. // If PreferedMaximumLength is MAXULONG, then we are supposed to get all
  237. // the information, regardless of size. Allocate the output buffer of a
  238. // reasonable size and try to use it. If this fails, the Redirector FSD
  239. // will say how much we need to allocate.
  240. //
  241. if (PreferedMaximumLength == MAXULONG) {
  242. OutputBufferLength = (BufferHintSize) ?
  243. BufferHintSize :
  244. INITIAL_ALLOCATION_SIZE;
  245. }
  246. else {
  247. OutputBufferLength = PreferedMaximumLength;
  248. }
  249. OutputBufferLength = ROUND_UP_COUNT(OutputBufferLength, ALIGN_WCHAR);
  250. if ((*OutputBuffer = LocalAlloc( LMEM_ZEROINIT, OutputBufferLength)) == NULL) {
  251. return ERROR_NOT_ENOUGH_MEMORY;
  252. }
  253. CompletionEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  254. if (CompletionEvent == (HANDLE)-1) {
  255. LocalFree(*OutputBuffer);
  256. *OutputBuffer = NULL;
  257. return(GetLastError());
  258. }
  259. Drrp->Parameters.EnumerateServers.EntriesRead = 0;
  260. //
  261. // Make the request of the Datagram Receiver
  262. //
  263. ntstatus = NtDeviceIoControlFile(
  264. FileHandle,
  265. CompletionEvent,
  266. NULL, // APC routine
  267. NULL, // APC context
  268. &IoStatusBlock,
  269. DeviceControlCode,
  270. Drrp,
  271. RequestPacketLength,
  272. *OutputBuffer,
  273. OutputBufferLength
  274. );
  275. if (NT_SUCCESS(ntstatus)) {
  276. //
  277. // If pending was returned, then wait until the request completes.
  278. //
  279. if (ntstatus == STATUS_PENDING) {
  280. do {
  281. ntstatus = WaitForSingleObjectEx(CompletionEvent, 0xffffffff, TRUE);
  282. } while ( ntstatus == WAIT_IO_COMPLETION );
  283. }
  284. if (NT_SUCCESS(ntstatus)) {
  285. ntstatus = IoStatusBlock.Status;
  286. }
  287. }
  288. //
  289. // Map NT status to Win error
  290. //
  291. status = NetpNtStatusToApiStatus(ntstatus);
  292. if (status == ERROR_MORE_DATA) {
  293. ASSERT(
  294. FIELD_OFFSET(
  295. LMDR_REQUEST_PACKET,
  296. Parameters.EnumerateNames.TotalBytesNeeded
  297. ) ==
  298. FIELD_OFFSET(
  299. LMDR_REQUEST_PACKET,
  300. Parameters.EnumerateServers.TotalBytesNeeded
  301. )
  302. );
  303. ASSERT(
  304. FIELD_OFFSET(
  305. LMDR_REQUEST_PACKET,
  306. Parameters.GetBrowserServerList.TotalBytesNeeded
  307. ) ==
  308. FIELD_OFFSET(
  309. LMDR_REQUEST_PACKET,
  310. Parameters.EnumerateServers.TotalBytesNeeded
  311. )
  312. );
  313. TotalBytesNeeded = Drrp->Parameters.EnumerateNames.TotalBytesNeeded;
  314. }
  315. if ((TotalBytesNeeded > OutputBufferLength) &&
  316. (PreferedMaximumLength == MAXULONG)) {
  317. PLMDR_REQUEST_PACKET Drrp = (PLMDR_REQUEST_PACKET) RequestPacket;
  318. //
  319. // Initial output buffer allocated was too small and we need to return
  320. // all data. First free the output buffer before allocating the
  321. // required size plus a fudge factor just in case the amount of data
  322. // grew.
  323. //
  324. LocalFree(*OutputBuffer);
  325. OutputBufferLength =
  326. ROUND_UP_COUNT((TotalBytesNeeded + FUDGE_FACTOR_SIZE),
  327. ALIGN_WCHAR);
  328. if ((*OutputBuffer = LocalAlloc(LMEM_ZEROINIT, OutputBufferLength)) == NULL) {
  329. return ERROR_NOT_ENOUGH_MEMORY;
  330. }
  331. ASSERT(
  332. FIELD_OFFSET(
  333. LMDR_REQUEST_PACKET,
  334. Parameters.EnumerateNames.ResumeHandle
  335. ) ==
  336. FIELD_OFFSET(
  337. LMDR_REQUEST_PACKET,
  338. Parameters.EnumerateServers.ResumeHandle
  339. )
  340. );
  341. ASSERT(
  342. FIELD_OFFSET(
  343. LMDR_REQUEST_PACKET,
  344. Parameters.EnumerateNames.ResumeHandle
  345. ) ==
  346. FIELD_OFFSET(
  347. LMDR_REQUEST_PACKET,
  348. Parameters.GetBrowserServerList.ResumeHandle
  349. )
  350. );
  351. Drrp->Parameters.EnumerateNames.ResumeHandle = OriginalResumeKey;
  352. Drrp->Parameters.EnumerateServers.EntriesRead = 0;
  353. //
  354. // Make the request of the Datagram Receiver
  355. //
  356. ntstatus = NtDeviceIoControlFile(
  357. FileHandle,
  358. CompletionEvent,
  359. NULL, // APC routine
  360. NULL, // APC context
  361. &IoStatusBlock,
  362. DeviceControlCode,
  363. Drrp,
  364. RequestPacketLength,
  365. *OutputBuffer,
  366. OutputBufferLength
  367. );
  368. if (NT_SUCCESS(ntstatus)) {
  369. //
  370. // If pending was returned, then wait until the request completes.
  371. //
  372. if (ntstatus == STATUS_PENDING) {
  373. do {
  374. ntstatus = WaitForSingleObjectEx(CompletionEvent, 0xffffffff, TRUE);
  375. } while ( ntstatus == WAIT_IO_COMPLETION );
  376. }
  377. if (NT_SUCCESS(ntstatus)) {
  378. ntstatus = IoStatusBlock.Status;
  379. }
  380. }
  381. status = NetpNtStatusToApiStatus(ntstatus);
  382. }
  383. //
  384. // If not successful in getting any data, or if the caller asked for
  385. // all available data with PreferedMaximumLength == MAXULONG and
  386. // our buffer overflowed, free the output buffer and set its pointer
  387. // to NULL.
  388. //
  389. if ((status != NERR_Success && status != ERROR_MORE_DATA) ||
  390. (TotalBytesNeeded == 0) ||
  391. (PreferedMaximumLength == MAXULONG && status == ERROR_MORE_DATA) ||
  392. (Drrp->Parameters.EnumerateServers.EntriesRead == 0)) {
  393. LocalFree(*OutputBuffer);
  394. *OutputBuffer = NULL;
  395. //
  396. // PreferedMaximumLength == MAXULONG and buffer overflowed means
  397. // we do not have enough memory to satisfy the request.
  398. //
  399. if (status == ERROR_MORE_DATA) {
  400. status = ERROR_NOT_ENOUGH_MEMORY;
  401. }
  402. }
  403. CloseHandle(CompletionEvent);
  404. return status;
  405. UNREFERENCED_PARAMETER(Information);
  406. }
  407. NET_API_STATUS
  408. OpenBrowser(
  409. OUT PHANDLE BrowserHandle
  410. )
  411. /*++
  412. Routine Description:
  413. This function opens a handle to the bowser device driver.
  414. Arguments:
  415. OUT PHANDLE BrowserHandle - Returns the handle to the browser.
  416. Return Value:
  417. NET_API_STATUS - NERR_Success or reason for failure.
  418. --*/
  419. {
  420. NTSTATUS Status;
  421. UNICODE_STRING DeviceName;
  422. IO_STATUS_BLOCK IoStatusBlock;
  423. OBJECT_ATTRIBUTES ObjectAttributes;
  424. //
  425. // Open the redirector device.
  426. //
  427. RtlInitUnicodeString(&DeviceName, DD_BROWSER_DEVICE_NAME_U);
  428. InitializeObjectAttributes(
  429. &ObjectAttributes,
  430. &DeviceName,
  431. OBJ_CASE_INSENSITIVE,
  432. NULL,
  433. NULL
  434. );
  435. Status = NtOpenFile(
  436. BrowserHandle,
  437. SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE,
  438. &ObjectAttributes,
  439. &IoStatusBlock,
  440. FILE_SHARE_READ | FILE_SHARE_WRITE,
  441. FILE_SYNCHRONOUS_IO_NONALERT
  442. );
  443. if (NT_SUCCESS(Status)) {
  444. Status = IoStatusBlock.Status;
  445. }
  446. return NetpNtStatusToApiStatus(Status);
  447. }
  448. // ========================================================================
  449. // * matches one or more chars, eg. match( "a*b", "a..b" ).
  450. // ? matches exactly one char, eg. match( "a?b", "a.b" ).
  451. int match( const char * p, const char * s )
  452. /*++
  453. Routine Description:
  454. This routine is used to compare addresses.
  455. Author:
  456. 07/01/98 Rajkumar
  457. --*/
  458. {
  459. switch( *p ){
  460. case '\0' : return ! *s ;
  461. case '*' : return match( p+1, s ) || *s && match( p, s+1 );
  462. case '?' : return *s && match( p+1, s+1 );
  463. default : return *p == *s && match( p+1, s+1 );
  464. }
  465. }