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.

1605 lines
44 KiB

  1. /*++
  2. Copyright (c) 1991-1992 Microsoft Corporation
  3. Module Name:
  4. wksstub.c
  5. Abstract:
  6. Client stubs of the Browser service APIs.
  7. Author:
  8. Rita Wong (ritaw) 10-May-1991
  9. Larry Osterman (LarryO) 23-Mar-1992
  10. Environment:
  11. User Mode - Win32
  12. Revision History:
  13. 18-Jun-1991 JohnRo
  14. Remote NetUse APIs to downlevel servers.
  15. 24-Jul-1991 JohnRo
  16. Use NET_REMOTE_TRY_RPC etc macros for NetUse APIs.
  17. Moved NetpIsServiceStarted() into NetLib.
  18. 25-Jul-1991 JohnRo
  19. Quiet DLL stub debug output.
  20. 19-Aug-1991 JohnRo
  21. Implement downlevel NetWksta APIs. Use NetRpc.h for NetWksta APIs.
  22. 07-Nov-1991 JohnRo
  23. RAID 4186: assert in RxNetShareAdd and other DLL stub problems.
  24. 19-Nov-1991 JohnRo
  25. Make sure status is correct for APIs not supported on downlevel.
  26. Implement remote NetWkstaUserEnum().
  27. 09-Nov-1992 JohnRo
  28. Fix NET_API_FUNCTION references.
  29. Avoid compiler warnings.
  30. --*/
  31. #include "brclient.h"
  32. #undef IF_DEBUG // avoid wsclient.h vs. debuglib.h conflicts.
  33. #include <debuglib.h> // IF_DEBUG() (needed by netrpc.h).
  34. #include <lmserver.h>
  35. #include <lmsvc.h>
  36. #include <rxuse.h> // RxNetUse APIs.
  37. #include <rxwksta.h> // RxNetWksta and RxNetWkstaUser APIs.
  38. #include <rap.h> // Needed by rxserver.h
  39. #include <rxserver.h> // RxNetServerEnum API.
  40. #include <netlib.h> // NetpServiceIsStarted() (needed by netrpc.h).
  41. #include <ntddbrow.h> // Browser definitions
  42. #include <netrpc.h> // NET_REMOTE macros.
  43. #include <align.h>
  44. #include <tstr.h>
  45. #include <tstring.h> // NetpInitOemString().
  46. #include <brcommon.h> // Routines common between client & server
  47. #include <lmapibuf.h> // NetApiBufferFree().
  48. #include <lmbrowsr.h> // Definition of I_BrowserServerEnum
  49. #include <icanon.h>
  50. #include <lmapibuf.h>
  51. #include "cscp.h"
  52. //-------------------------------------------------------------------//
  53. // //
  54. // Global variables //
  55. // //
  56. //-------------------------------------------------------------------//
  57. #define API_SUCCESS(x) ((x) == NERR_Success || (x) == ERROR_MORE_DATA)
  58. //-------------------------------------------------------------------//
  59. // //
  60. // Global types //
  61. // //
  62. //-------------------------------------------------------------------//
  63. //-------------------------------------------------------------------//
  64. // //
  65. // Private routines //
  66. // //
  67. //-------------------------------------------------------------------//
  68. NET_API_STATUS
  69. GetBrowserTransportList(
  70. OUT PLMDR_TRANSPORT_LIST *TransportList
  71. );
  72. NET_API_STATUS
  73. EnumServersForTransport(
  74. IN PUNICODE_STRING TransportName,
  75. IN LPCWSTR DomainName OPTIONAL,
  76. IN ULONG level,
  77. IN ULONG prefmaxlen,
  78. IN ULONG servertype,
  79. IN LPTSTR CurrentComputerName,
  80. OUT PINTERIM_SERVER_LIST InterimServerList,
  81. OUT PULONG TotalEntriesOnThisTransport,
  82. IN LPCWSTR FirstNameToReturn,
  83. IN BOOLEAN WannishTransport,
  84. IN BOOLEAN RasTransport,
  85. IN BOOLEAN IPXTransport
  86. );
  87. #if DBG
  88. void
  89. ValidateServerList(
  90. IN PVOID ServerList,
  91. IN ULONG ulLevel,
  92. IN ULONG ulEntries
  93. );
  94. #else
  95. #define ValidateServerList(x,y,z)
  96. #endif
  97. NET_API_STATUS NET_API_FUNCTION
  98. NetServerEnum(
  99. IN LPCWSTR servername OPTIONAL,
  100. IN DWORD level,
  101. OUT LPBYTE *bufptr,
  102. IN DWORD prefmaxlen,
  103. OUT LPDWORD entriesread,
  104. OUT LPDWORD totalentries,
  105. IN DWORD servertype,
  106. IN LPCWSTR domain OPTIONAL,
  107. IN OUT LPDWORD resume_handle OPTIONAL
  108. )
  109. /*++
  110. Routine Description:
  111. This is the DLL entrypoint for NetServerEnum.
  112. Arguments:
  113. servername - Supplies the name of server to execute this function
  114. level - Supplies the requested level of information.
  115. bufptr - Returns a pointer to a buffer which contains the
  116. requested transport information.
  117. prefmaxlen - Supplies the number of bytes of information
  118. to return in the buffer. If this value is MAXULONG, we will try
  119. to return all available information if there is enough memory
  120. resource.
  121. entriesread - Returns the number of entries read into the buffer. This
  122. value is returned only if the return code is NERR_Success or
  123. ERROR_MORE_DATA.
  124. totalentries - Returns the total number of entries available. This value
  125. is returned only if the return code is NERR_Success or ERROR_MORE_DATA.
  126. servertype - Supplies the type of server to enumerate.
  127. domain - Supplies the name of one of the active domains to enumerate the
  128. servers from. If NULL, servers from the primary domain, logon domain
  129. and other domains are enumerated.
  130. resume_handle - Supplies and returns the point to continue with enumeration.
  131. Return Value:
  132. NET_API_STATUS - NERR_Success or reason for failure.
  133. --*/
  134. {
  135. NET_API_STATUS NetStatus;
  136. //
  137. // NetServerEnum is simply a wrapper to NetServerEnumEx
  138. //
  139. NetStatus = NetServerEnumEx(
  140. servername,
  141. level,
  142. bufptr,
  143. prefmaxlen,
  144. entriesread,
  145. totalentries,
  146. servertype,
  147. domain,
  148. NULL ); // NULL FirstNameToReturn
  149. if (ARGUMENT_PRESENT(resume_handle)) {
  150. *resume_handle = 0;
  151. }
  152. return NetStatus;
  153. }
  154. NET_API_STATUS NET_API_FUNCTION
  155. NetServerEnumEx(
  156. IN LPCWSTR servername OPTIONAL,
  157. IN DWORD level,
  158. OUT LPBYTE *bufptr,
  159. IN DWORD prefmaxlen,
  160. OUT LPDWORD entriesread,
  161. OUT LPDWORD totalentries,
  162. IN DWORD servertype,
  163. IN LPCWSTR domain OPTIONAL,
  164. IN LPCWSTR FirstNameToReturnArg OPTIONAL
  165. )
  166. /*++
  167. Routine Description:
  168. This is the DLL entrypoint for NetServerEnum.
  169. Arguments:
  170. servername - Supplies the name of server to execute this function
  171. level - Supplies the requested level of information.
  172. bufptr - Returns a pointer to a buffer which contains the
  173. requested transport information.
  174. prefmaxlen - Supplies the number of bytes of information
  175. to return in the buffer. If this value is MAXULONG, we will try
  176. to return all available information if there is enough memory
  177. resource.
  178. entriesread - Returns the number of entries read into the buffer. This
  179. value is returned only if the return code is NERR_Success or
  180. ERROR_MORE_DATA.
  181. totalentries - Returns the total number of entries available. This value
  182. is returned only if the return code is NERR_Success or ERROR_MORE_DATA.
  183. servertype - Supplies the type of server to enumerate.
  184. domain - Supplies the name of one of the active domains to enumerate the
  185. servers from. If NULL, servers from the primary domain, logon domain
  186. and other domains are enumerated.
  187. FirstNameToReturnArg - Supplies the name of the first domain or server entry to return.
  188. The caller can use this parameter to implement a resume handle of sorts by passing
  189. the name of the last entry returned on a previous call. (Notice that the specified
  190. entry will, also, be returned on this call unless it has since been deleted.)
  191. Pass NULL (or a zero length string) to start with the first entry available.
  192. Return Value:
  193. NET_API_STATUS - NERR_Success or reason for failure.
  194. ERROR_MORE_DATA - More servers are available to be enumerated.
  195. It is possible to return ERROR_MORE_DATA and zero entries in the case
  196. where the browser server used doesn't support enumerating all the entries
  197. it has. (e.g., an NT 3.5x Domain Master Browser that downloaded a domain
  198. list from WINS and the WINS list is more than 64Kb long.) The caller
  199. should simply ignore the additional data.
  200. It is possible to fail to return ERROR_MORE_DATA and return a truncated
  201. list. (e.g., an NT 3.5x Backup browser or WIN 95 backup browser in the
  202. above mentioned domain. Such a backup browser replicates only 64kb
  203. of data from the DMB (PDC) then represents that list as the entire list.)
  204. The caller should ignore this problem. The site should upgrade its
  205. browser servers.
  206. --*/
  207. {
  208. PLMDR_TRANSPORT_LIST TransportList = NULL;
  209. PLMDR_TRANSPORT_LIST TransportEntry = NULL;
  210. INTERIM_SERVER_LIST InterimServerList;
  211. NET_API_STATUS Status;
  212. DWORD DomainNameSize = 0;
  213. TCHAR DomainName[DNLEN + 1];
  214. WCHAR FirstNameToReturn[DNLEN+1];
  215. DWORD LocalTotalEntries;
  216. BOOLEAN AnyTransportHasMoreData = FALSE;
  217. //
  218. //
  219. // The workstation has to be started for the NetServerEnum API to work.
  220. //
  221. //
  222. if ((Status = CheckForService(SERVICE_WORKSTATION, NULL)) != NERR_Success) {
  223. return Status;
  224. }
  225. #ifdef ENABLE_PSEUDO_BROWSER
  226. //
  227. // Disabled NetServerEnum check
  228. //
  229. if ( !IsEnumServerEnabled() ||
  230. GetBrowserPseudoServerLevel() == BROWSER_PSEUDO ) {
  231. // NetServerEnum is disabled or pseudo server is
  232. // enabled on box ==> return no entries.
  233. *entriesread = 0;
  234. *totalentries = 0;
  235. *bufptr = NULL;
  236. return NERR_Success;
  237. }
  238. #endif
  239. //
  240. // Canonicalize the input parameters to make later comparisons easier.
  241. //
  242. if (ARGUMENT_PRESENT(domain)) {
  243. if ( I_NetNameCanonicalize(
  244. NULL,
  245. (LPWSTR) domain,
  246. DomainName,
  247. (DNLEN + 1) * sizeof(TCHAR),
  248. NAMETYPE_WORKGROUP,
  249. LM2X_COMPATIBLE
  250. ) != NERR_Success) {
  251. return ERROR_INVALID_PARAMETER;
  252. }
  253. DomainNameSize = STRLEN(DomainName) * sizeof(WCHAR);
  254. domain = DomainName;
  255. }
  256. if (ARGUMENT_PRESENT(FirstNameToReturnArg) && *FirstNameToReturnArg != L'\0') {
  257. if ( I_NetNameCanonicalize(
  258. NULL,
  259. (LPWSTR) FirstNameToReturnArg,
  260. FirstNameToReturn,
  261. sizeof(FirstNameToReturn),
  262. NAMETYPE_WORKGROUP,
  263. LM2X_COMPATIBLE
  264. ) != NERR_Success) {
  265. return ERROR_INVALID_PARAMETER;
  266. }
  267. } else {
  268. FirstNameToReturn[0] = L'\0';
  269. }
  270. if ((servername != NULL) &&
  271. ( *servername != TCHAR_EOS)) {
  272. //
  273. // Call downlevel version of the API
  274. //
  275. Status = RxNetServerEnum(
  276. servername,
  277. NULL,
  278. level,
  279. bufptr,
  280. prefmaxlen,
  281. entriesread,
  282. totalentries,
  283. servertype,
  284. domain,
  285. FirstNameToReturn );
  286. return Status;
  287. }
  288. //
  289. // Only levels 100 and 101 are valid
  290. //
  291. if ((level != 100) && (level != 101)) {
  292. return ERROR_INVALID_LEVEL;
  293. }
  294. if (servertype != SV_TYPE_ALL) {
  295. if (servertype & SV_TYPE_DOMAIN_ENUM) {
  296. if (servertype != SV_TYPE_DOMAIN_ENUM) {
  297. return ERROR_INVALID_FUNCTION;
  298. }
  299. }
  300. }
  301. //
  302. // Initialize the buffer to a known value.
  303. //
  304. *bufptr = NULL;
  305. *entriesread = 0;
  306. *totalentries = 0;
  307. //
  308. // If we are off-line, give CSC a chance to do the enumeration
  309. //
  310. if( !ARGUMENT_PRESENT( servername ) &&
  311. (servertype & SV_TYPE_SERVER) &&
  312. CSCIsOffline() ) {
  313. Status = CSCNetServerEnumEx( level,
  314. bufptr,
  315. prefmaxlen,
  316. entriesread,
  317. totalentries
  318. );
  319. if( Status == NERR_Success ) {
  320. return Status;
  321. }
  322. }
  323. Status = InitializeInterimServerList(&InterimServerList, NULL, NULL, NULL, NULL);
  324. try {
  325. BOOL AnyEnumServersSucceeded = FALSE;
  326. LPTSTR MyComputerName = NULL;
  327. Status = NetpGetComputerName( &MyComputerName);
  328. if ( Status != NERR_Success ) {
  329. goto try_exit;
  330. }
  331. //
  332. // Retrieve the list of transports from the browser.
  333. //
  334. Status = GetBrowserTransportList(&TransportList);
  335. if (Status != NERR_Success) {
  336. goto try_exit;
  337. }
  338. TransportEntry = TransportList;
  339. while (TransportEntry != NULL) {
  340. UNICODE_STRING TransportName;
  341. TransportName.Buffer = TransportEntry->TransportName;
  342. TransportName.Length = (USHORT)TransportEntry->TransportNameLength;
  343. TransportName.MaximumLength = (USHORT)TransportEntry->TransportNameLength;
  344. Status = EnumServersForTransport(&TransportName,
  345. domain,
  346. level,
  347. prefmaxlen,
  348. servertype,
  349. MyComputerName,
  350. &InterimServerList,
  351. &LocalTotalEntries,
  352. FirstNameToReturn,
  353. (BOOLEAN)((TransportEntry->Flags & LMDR_TRANSPORT_WANNISH) != 0),
  354. (BOOLEAN)((TransportEntry->Flags & LMDR_TRANSPORT_RAS) != 0),
  355. (BOOLEAN)((TransportEntry->Flags & LMDR_TRANSPORT_IPX) != 0));
  356. if (API_SUCCESS(Status)) {
  357. if ( Status == ERROR_MORE_DATA ) {
  358. AnyTransportHasMoreData = TRUE;
  359. }
  360. AnyEnumServersSucceeded = TRUE;
  361. if ( LocalTotalEntries > *totalentries ) {
  362. *totalentries = LocalTotalEntries;
  363. }
  364. }
  365. if (TransportEntry->NextEntryOffset == 0) {
  366. TransportEntry = NULL;
  367. } else {
  368. TransportEntry = (PLMDR_TRANSPORT_LIST)((PCHAR)TransportEntry+TransportEntry->NextEntryOffset);
  369. }
  370. }
  371. if ( MyComputerName != NULL ) {
  372. (void) NetApiBufferFree( MyComputerName );
  373. }
  374. if (AnyEnumServersSucceeded) {
  375. //
  376. // Pack the interim server list into its final form.
  377. //
  378. Status = PackServerList(&InterimServerList,
  379. level,
  380. servertype,
  381. prefmaxlen,
  382. (PVOID *)bufptr,
  383. entriesread,
  384. &LocalTotalEntries, // Pack thinks it has ALL the entries
  385. NULL ); // The server has already returned us the right entries
  386. if ( API_SUCCESS( Status ) ) {
  387. if ( LocalTotalEntries > *totalentries ) {
  388. *totalentries = LocalTotalEntries;
  389. }
  390. }
  391. }
  392. try_exit:NOTHING;
  393. } finally {
  394. if (TransportList != NULL) {
  395. MIDL_user_free(TransportList);
  396. }
  397. UninitializeInterimServerList(&InterimServerList);
  398. }
  399. if ( API_SUCCESS( Status )) {
  400. //
  401. // At this point,
  402. // *totalentries is the largest of:
  403. // The TotalEntries returned from any transport.
  404. // The actual number of entries read.
  405. //
  406. // Adjust TotalEntries returned for reality.
  407. //
  408. if ( Status == NERR_Success ) {
  409. *totalentries = *entriesread;
  410. } else {
  411. if ( *totalentries <= *entriesread ) {
  412. *totalentries = *entriesread + 1;
  413. }
  414. }
  415. //
  416. // Ensure we return ERROR_MORE_DATA if any transport has more data.
  417. //
  418. if ( AnyTransportHasMoreData ) {
  419. Status = ERROR_MORE_DATA;
  420. }
  421. }
  422. return Status;
  423. }
  424. NET_API_STATUS
  425. EnumServersForTransport(
  426. IN PUNICODE_STRING TransportName,
  427. IN LPCWSTR DomainName OPTIONAL,
  428. IN ULONG level,
  429. IN ULONG prefmaxlen,
  430. IN ULONG servertype,
  431. IN LPTSTR CurrentComputerName,
  432. OUT PINTERIM_SERVER_LIST InterimServerList,
  433. OUT PULONG TotalEntriesOnThisTransport,
  434. IN LPCWSTR FirstNameToReturn,
  435. IN BOOLEAN WannishTransport,
  436. IN BOOLEAN RasTransport,
  437. IN BOOLEAN IpxTransport
  438. )
  439. {
  440. PWSTR *BrowserList = NULL;
  441. ULONG BrowserListLength = 0;
  442. NET_API_STATUS Status;
  443. PVOID ServerList = NULL;
  444. ULONG EntriesInList = 0;
  445. ULONG ServerIndex = 0;
  446. //
  447. // Skip over IPX transports - we can't contact machines over them anyway.
  448. //
  449. *TotalEntriesOnThisTransport = 0;
  450. if (IpxTransport) {
  451. return NERR_Success;
  452. }
  453. //
  454. // Retrieve a new browser list. Do not force a revalidation.
  455. //
  456. Status = GetBrowserServerList(TransportName,
  457. DomainName,
  458. &BrowserList,
  459. &BrowserListLength,
  460. FALSE);
  461. //
  462. // If a domain name was specified and we were unable to find the browse
  463. // master for the domain and we are running on a wannish transport,
  464. // invoke the "double hop" code and allow a local browser server
  465. // remote the API to the browse master for that domain (we assume that
  466. // this means that the workgroup is on a different subnet of a WAN).
  467. //
  468. if (!API_SUCCESS(Status) &&
  469. DomainName != NULL) {
  470. Status = GetBrowserServerList(TransportName,
  471. NULL,
  472. &BrowserList,
  473. &BrowserListLength,
  474. FALSE);
  475. }
  476. //
  477. // If we were able to retrieve the list, remote the API. Otherwise
  478. // return.
  479. //
  480. if (API_SUCCESS(Status) && BrowserList) {
  481. do {
  482. LPTSTR Transport;
  483. LPTSTR ServerName;
  484. BOOL AlreadyInTree;
  485. //
  486. // Remote the API to that server.
  487. //
  488. Transport = TransportName->Buffer;
  489. ServerName = BrowserList[0];
  490. *TotalEntriesOnThisTransport = 0;
  491. // add 2 to skip double backslash at start of ServerName
  492. if ( STRICMP(ServerName + 2, CurrentComputerName ) == 0 ) {
  493. //
  494. // If we are going to remote the API to ourselves,
  495. // and we are running the browser service, simply
  496. // use RPC to get the information we need, don't
  497. // bother using the redirector. This allows us to
  498. // avoid tying up RPCXLATE thread.
  499. //
  500. Status = I_BrowserServerEnumEx (
  501. NULL,
  502. Transport,
  503. CurrentComputerName,
  504. level,
  505. (LPBYTE *)&ServerList,
  506. prefmaxlen,
  507. &EntriesInList,
  508. TotalEntriesOnThisTransport,
  509. servertype,
  510. DomainName,
  511. FirstNameToReturn );
  512. } else {
  513. Status = RxNetServerEnum(
  514. ServerName,
  515. Transport,
  516. level,
  517. (LPBYTE *)&ServerList,
  518. prefmaxlen,
  519. &EntriesInList,
  520. TotalEntriesOnThisTransport,
  521. servertype,
  522. DomainName,
  523. FirstNameToReturn );
  524. }
  525. if ( !API_SUCCESS(Status)) {
  526. NET_API_STATUS GetBListStatus;
  527. //
  528. // If we failed to remote the API for some reason,
  529. // we want to regenerate the bowsers list of browser
  530. // servers.
  531. //
  532. if (BrowserList != NULL) {
  533. MIDL_user_free(BrowserList);
  534. BrowserList = NULL;
  535. }
  536. GetBListStatus = GetBrowserServerList(TransportName,
  537. DomainName,
  538. &BrowserList,
  539. &BrowserListLength,
  540. TRUE);
  541. if (GetBListStatus != NERR_Success) {
  542. //
  543. // If we were unable to reload the list,
  544. // try the next transport.
  545. //
  546. break;
  547. }
  548. ServerIndex += 1;
  549. //
  550. // If we've looped more times than we got servers
  551. // in the list, we're done.
  552. //
  553. if ( ServerIndex > BrowserListLength ) {
  554. break;
  555. }
  556. } else {
  557. NET_API_STATUS TempStatus;
  558. TempStatus = MergeServerList(
  559. InterimServerList,
  560. level,
  561. ServerList,
  562. EntriesInList,
  563. *TotalEntriesOnThisTransport );
  564. if ( TempStatus != NERR_Success ) {
  565. Status = TempStatus;
  566. }
  567. //
  568. // The remote API succeeded.
  569. //
  570. // Now free up the remaining parts of the list.
  571. //
  572. if (ServerList != NULL) {
  573. NetApiBufferFree(ServerList);
  574. ServerList = NULL;
  575. }
  576. // We're done regardless of the success or failure of MergeServerList.
  577. break;
  578. }
  579. } while ( !API_SUCCESS(Status) );
  580. }
  581. //
  582. // Free up the browser list.
  583. //
  584. if (BrowserList != NULL) {
  585. MIDL_user_free(BrowserList);
  586. BrowserList = NULL;
  587. }
  588. return Status;
  589. }
  590. NET_API_STATUS
  591. GetBrowserTransportList(
  592. OUT PLMDR_TRANSPORT_LIST *TransportList
  593. )
  594. /*++
  595. Routine Description:
  596. This routine returns the list of transports bound into the browser.
  597. Arguments:
  598. OUT PLMDR_TRANSPORT_LIST *TransportList - Transport list to return.
  599. Return Value:
  600. NET_API_STATUS - NERR_Success or reason for failure.
  601. --*/
  602. {
  603. NET_API_STATUS Status;
  604. HANDLE BrowserHandle;
  605. LMDR_REQUEST_PACKET RequestPacket;
  606. Status = OpenBrowser(&BrowserHandle);
  607. if (Status != NERR_Success) {
  608. return Status;
  609. }
  610. ZeroMemory(&RequestPacket, sizeof(RequestPacket));
  611. RequestPacket.Version = LMDR_REQUEST_PACKET_VERSION_DOM;
  612. RequestPacket.Type = EnumerateXports;
  613. RtlInitUnicodeString(&RequestPacket.TransportName, NULL);
  614. RtlInitUnicodeString(&RequestPacket.EmulatedDomainName, NULL);
  615. Status = DeviceControlGetInfo(
  616. BrowserHandle,
  617. IOCTL_LMDR_ENUMERATE_TRANSPORTS,
  618. &RequestPacket,
  619. sizeof(RequestPacket),
  620. (PVOID *)TransportList,
  621. 0xffffffff,
  622. 4096,
  623. NULL);
  624. NtClose(BrowserHandle);
  625. return Status;
  626. }
  627. NET_API_STATUS
  628. I_BrowserServerEnum (
  629. IN LPCWSTR servername OPTIONAL,
  630. IN LPCWSTR transport OPTIONAL,
  631. IN LPCWSTR clientname OPTIONAL,
  632. IN DWORD level,
  633. OUT LPBYTE *bufptr,
  634. IN DWORD prefmaxlen,
  635. OUT LPDWORD entriesread,
  636. OUT LPDWORD totalentries,
  637. IN DWORD servertype,
  638. IN LPCWSTR domain OPTIONAL,
  639. IN OUT LPDWORD resume_handle OPTIONAL
  640. )
  641. /*++
  642. Routine Description:
  643. This is the DLL entrypoint for NetWkstaSetInfo.
  644. Arguments:
  645. servername - Supplies the name of server to execute this function
  646. level - Supplies the level of information.
  647. buf - Supplies a buffer which contains the information structure of fields
  648. to set. The level denotes the structure in this buffer.
  649. parm_err - Returns the identifier to the invalid parameter in buf if this
  650. function returns ERROR_INVALID_PARAMETER.
  651. Return Value:
  652. NET_API_STATUS - NERR_Success or reason for failure.
  653. --*/
  654. {
  655. NET_API_STATUS status;
  656. GENERIC_INFO_CONTAINER GenericInfoContainer;
  657. GENERIC_ENUM_STRUCT InfoStruct;
  658. GenericInfoContainer.Buffer = NULL;
  659. GenericInfoContainer.EntriesRead = 0;
  660. InfoStruct.Container = &GenericInfoContainer;
  661. InfoStruct.Level = level;
  662. NET_REMOTE_TRY_RPC
  663. //
  664. // Try RPC (local or remote) version of API.
  665. //
  666. status = I_BrowserrServerEnum(
  667. (LPWSTR) servername,
  668. (LPWSTR) transport,
  669. (LPWSTR) clientname,
  670. (LPSERVER_ENUM_STRUCT)&InfoStruct,
  671. prefmaxlen,
  672. totalentries,
  673. servertype,
  674. (LPWSTR) domain,
  675. resume_handle
  676. );
  677. if (status == NERR_Success || status == ERROR_MORE_DATA) {
  678. *bufptr = (LPBYTE) GenericInfoContainer.Buffer;
  679. *entriesread = GenericInfoContainer.EntriesRead;
  680. #if 0
  681. if (((servertype == SV_TYPE_ALL || servertype == SV_TYPE_DOMAIN_ENUM)) &&
  682. (STRICMP(transport, L"\\Device\\Streams\\NBT"))) {
  683. if (*entriesread <= 20) {
  684. KdPrint(("RPC API Returned EntriesRead == %ld on transport %ws\n", *entriesread, transport));
  685. }
  686. if (*totalentries <= 20) {
  687. KdPrint(("RPC API Returned TotalEntries == %ld on transport %ws\n", *totalentries, transport));
  688. }
  689. }
  690. #endif
  691. }
  692. NET_REMOTE_RPC_FAILED("I_BrServerEnum",
  693. servername,
  694. status,
  695. NET_REMOTE_FLAG_NORMAL,
  696. SERVICE_BROWSER )
  697. //
  698. // There is no downlevel version of api.
  699. //
  700. status = ERROR_NOT_SUPPORTED;
  701. NET_REMOTE_END
  702. #if 0
  703. if ((servertype == SV_TYPE_ALL || servertype == SV_TYPE_DOMAIN_ENUM) &&
  704. (STRICMP(transport, L"\\Device\\Streams\\NBT"))) {
  705. if (*entriesread <= 20) {
  706. KdPrint(("Client API Returned EntriesRead == %ld on transport %ws\n", *entriesread, transport));
  707. }
  708. if (*totalentries <= 20) {
  709. KdPrint(("Client API Returned TotalEntries == %ld on transport %ws\n", *totalentries, transport));
  710. }
  711. }
  712. #endif
  713. return status;
  714. }
  715. NET_API_STATUS
  716. I_BrowserServerEnumEx (
  717. IN LPCWSTR servername OPTIONAL,
  718. IN LPCWSTR transport OPTIONAL,
  719. IN LPCWSTR clientname OPTIONAL,
  720. IN DWORD level,
  721. OUT LPBYTE *bufptr,
  722. IN DWORD prefmaxlen,
  723. OUT LPDWORD entriesread,
  724. OUT LPDWORD totalentries,
  725. IN DWORD servertype,
  726. IN LPCWSTR domain OPTIONAL,
  727. IN LPCWSTR FirstNameToReturn OPTIONAL
  728. )
  729. /*++
  730. Routine Description:
  731. This is the DLL entrypoint for NetWkstaSetInfo.
  732. Arguments:
  733. servername - Supplies the name of server to execute this function
  734. level - Supplies the level of information.
  735. buf - Supplies a buffer which contains the information structure of fields
  736. to set. The level denotes the structure in this buffer.
  737. parm_err - Returns the identifier to the invalid parameter in buf if this
  738. function returns ERROR_INVALID_PARAMETER.
  739. FirstNameToReturn - Supplies the name of the first domain or server entry to return.
  740. The caller can use this parameter to implement a resume handle of sorts by passing
  741. the name of the last entry returned on a previous call. (Notice that the specified
  742. entry will, also, be returned on this call unless it has since been deleted.)
  743. Pass NULL to start with the first entry available.
  744. Return Value:
  745. NET_API_STATUS - NERR_Success or reason for failure.
  746. --*/
  747. {
  748. NET_API_STATUS status;
  749. GENERIC_INFO_CONTAINER GenericInfoContainer;
  750. GENERIC_ENUM_STRUCT InfoStruct;
  751. GenericInfoContainer.Buffer = NULL;
  752. GenericInfoContainer.EntriesRead = 0;
  753. InfoStruct.Container = &GenericInfoContainer;
  754. InfoStruct.Level = level;
  755. NET_REMOTE_TRY_RPC
  756. //
  757. // Try RPC (local or remote) version of API.
  758. //
  759. status = I_BrowserrServerEnumEx(
  760. (LPWSTR) servername,
  761. (LPWSTR) transport,
  762. (LPWSTR) clientname,
  763. (LPSERVER_ENUM_STRUCT)&InfoStruct,
  764. prefmaxlen,
  765. totalentries,
  766. servertype,
  767. (LPWSTR) domain,
  768. (LPWSTR) FirstNameToReturn );
  769. if (status == NERR_Success || status == ERROR_MORE_DATA) {
  770. *bufptr = (LPBYTE) GenericInfoContainer.Buffer;
  771. *entriesread = GenericInfoContainer.EntriesRead;
  772. #if 0
  773. if (((servertype == SV_TYPE_ALL || servertype == SV_TYPE_DOMAIN_ENUM)) &&
  774. (STRICMP(transport, L"\\Device\\Streams\\NBT"))) {
  775. if (*entriesread <= 20) {
  776. KdPrint(("RPC API Returned EntriesRead == %ld on transport %ws\n", *entriesread, transport));
  777. }
  778. if (*totalentries <= 20) {
  779. KdPrint(("RPC API Returned TotalEntries == %ld on transport %ws\n", *totalentries, transport));
  780. }
  781. }
  782. #endif
  783. }
  784. NET_REMOTE_RPC_FAILED("I_BrServerEnum",
  785. servername,
  786. status,
  787. NET_REMOTE_FLAG_NORMAL,
  788. SERVICE_BROWSER )
  789. //
  790. // There is no downlevel version of api.
  791. //
  792. status = ERROR_NOT_SUPPORTED;
  793. NET_REMOTE_END
  794. #if 0
  795. if ((servertype == SV_TYPE_ALL || servertype == SV_TYPE_DOMAIN_ENUM) &&
  796. (STRICMP(transport, L"\\Device\\Streams\\NBT"))) {
  797. if (*entriesread <= 20) {
  798. KdPrint(("Client API Returned EntriesRead == %ld on transport %ws\n", *entriesread, transport));
  799. }
  800. if (*totalentries <= 20) {
  801. KdPrint(("Client API Returned TotalEntries == %ld on transport %ws\n", *totalentries, transport));
  802. }
  803. }
  804. #endif
  805. return status;
  806. }
  807. NET_API_STATUS NET_API_FUNCTION
  808. I_BrowserQueryOtherDomains (
  809. IN LPCWSTR servername OPTIONAL,
  810. OUT LPBYTE *bufptr,
  811. OUT LPDWORD entriesread,
  812. OUT LPDWORD totalentries
  813. )
  814. /*++
  815. Routine Description:
  816. This is the DLL entrypoint for NetWkstaSetInfo.
  817. Arguments:
  818. servername - Supplies the name of server to execute this function
  819. buf - Supplies a buffer which contains the information structure of fields
  820. to set. The level denotes the structure in this buffer.
  821. Return Value:
  822. NET_API_STATUS - NERR_Success or reason for failure.
  823. --*/
  824. {
  825. NET_API_STATUS status;
  826. GENERIC_INFO_CONTAINER GenericInfoContainer;
  827. GENERIC_ENUM_STRUCT InfoStruct;
  828. GenericInfoContainer.Buffer = NULL;
  829. GenericInfoContainer.EntriesRead = 0;
  830. InfoStruct.Container = &GenericInfoContainer;
  831. InfoStruct.Level = 100;
  832. NET_REMOTE_TRY_RPC
  833. //
  834. // Try RPC (local or remote) version of API.
  835. //
  836. status = I_BrowserrQueryOtherDomains (
  837. (LPWSTR) servername,
  838. (LPSERVER_ENUM_STRUCT)&InfoStruct,
  839. totalentries
  840. );
  841. if (status == NERR_Success || status == ERROR_MORE_DATA) {
  842. *bufptr = (LPBYTE) GenericInfoContainer.Buffer;
  843. *entriesread = GenericInfoContainer.EntriesRead;
  844. }
  845. NET_REMOTE_RPC_FAILED("I_BrowserQueryOtherDomains",
  846. servername,
  847. status,
  848. NET_REMOTE_FLAG_NORMAL,
  849. SERVICE_BROWSER )
  850. //
  851. // There is no downlevel version of api.
  852. //
  853. status = ERROR_NOT_SUPPORTED;
  854. NET_REMOTE_END
  855. return status;
  856. }
  857. NET_API_STATUS
  858. I_BrowserResetNetlogonState (
  859. IN LPCWSTR servername OPTIONAL
  860. )
  861. /*++
  862. Routine Description:
  863. This is the DLL entrypoint for NetWkstaSetInfo.
  864. Arguments:
  865. servername - Supplies the name of server to execute this function
  866. buf - Supplies a buffer which contains the information structure of fields
  867. to set. The level denotes the structure in this buffer.
  868. Return Value:
  869. NET_API_STATUS - NERR_Success or reason for failure.
  870. --*/
  871. {
  872. NET_API_STATUS status;
  873. NET_REMOTE_TRY_RPC
  874. //
  875. // Try RPC (local or remote) version of API.
  876. //
  877. status = I_BrowserrResetNetlogonState (
  878. (LPWSTR) servername );
  879. NET_REMOTE_RPC_FAILED("I_BrowserResetNetlogonState",
  880. servername,
  881. status,
  882. NET_REMOTE_FLAG_NORMAL,
  883. SERVICE_BROWSER )
  884. //
  885. // There is no downlevel version of api.
  886. //
  887. status = ERROR_NOT_SUPPORTED;
  888. NET_REMOTE_END
  889. return status;
  890. }
  891. NET_API_STATUS
  892. I_BrowserDebugCall (
  893. IN LPTSTR servername OPTIONAL,
  894. IN DWORD DebugCode,
  895. IN DWORD Options
  896. )
  897. {
  898. NET_API_STATUS status;
  899. NET_REMOTE_TRY_RPC
  900. //
  901. // Try RPC (local or remote) version of API.
  902. //
  903. status = I_BrowserrDebugCall(
  904. servername,
  905. DebugCode,
  906. Options
  907. );
  908. NET_REMOTE_RPC_FAILED("I_BrowserDebugCall",
  909. servername,
  910. status,
  911. NET_REMOTE_FLAG_NORMAL,
  912. SERVICE_BROWSER )
  913. //
  914. // There is no downlevel version of api.
  915. //
  916. status = ERROR_NOT_SUPPORTED;
  917. NET_REMOTE_END
  918. return status;
  919. }
  920. NET_API_STATUS
  921. I_BrowserDebugTrace (
  922. IN LPTSTR servername OPTIONAL,
  923. IN PCHAR DebugString
  924. )
  925. {
  926. NET_API_STATUS status;
  927. NET_REMOTE_TRY_RPC
  928. //
  929. // Try RPC (local or remote) version of API.
  930. //
  931. status = I_BrowserrDebugTrace(
  932. servername,
  933. DebugString
  934. );
  935. NET_REMOTE_RPC_FAILED("I_BrowserDebugTrace",
  936. servername,
  937. status,
  938. NET_REMOTE_FLAG_NORMAL,
  939. SERVICE_BROWSER )
  940. //
  941. // There is no downlevel version of api.
  942. //
  943. status = ERROR_NOT_SUPPORTED;
  944. NET_REMOTE_END
  945. return status;
  946. }
  947. NET_API_STATUS
  948. I_BrowserQueryStatistics (
  949. IN LPCWSTR servername OPTIONAL,
  950. IN OUT LPBROWSER_STATISTICS *Statistics
  951. )
  952. {
  953. NET_API_STATUS status;
  954. NET_REMOTE_TRY_RPC
  955. //
  956. // Try RPC (local or remote) version of API.
  957. //
  958. status = I_BrowserrQueryStatistics(
  959. (LPWSTR) servername,
  960. Statistics
  961. );
  962. NET_REMOTE_RPC_FAILED("I_BrowserQueryStatistics",
  963. servername,
  964. status,
  965. NET_REMOTE_FLAG_NORMAL,
  966. SERVICE_BROWSER )
  967. //
  968. // There is no downlevel version of api.
  969. //
  970. status = ERROR_NOT_SUPPORTED;
  971. NET_REMOTE_END
  972. return status;
  973. }
  974. NET_API_STATUS
  975. I_BrowserResetStatistics (
  976. IN LPCWSTR servername OPTIONAL
  977. )
  978. {
  979. NET_API_STATUS status;
  980. NET_REMOTE_TRY_RPC
  981. //
  982. // Try RPC (local or remote) version of API.
  983. //
  984. status = I_BrowserrResetStatistics(
  985. (LPWSTR) servername );
  986. NET_REMOTE_RPC_FAILED("I_BrowserResetStatistics",
  987. servername,
  988. status,
  989. NET_REMOTE_FLAG_NORMAL,
  990. SERVICE_BROWSER )
  991. //
  992. // There is no downlevel version of api.
  993. //
  994. status = ERROR_NOT_SUPPORTED;
  995. NET_REMOTE_END
  996. return status;
  997. }
  998. NET_API_STATUS
  999. NetBrowserStatisticsGet(
  1000. IN LPTSTR ServerName,
  1001. IN DWORD Level,
  1002. OUT LPBYTE* Buffer
  1003. )
  1004. /*++
  1005. Routine Description:
  1006. Wrapper for workstation statistics retrieval routine - either calls the
  1007. client-side RPC function or calls RxNetStatisticsGet to retrieve the
  1008. statistics from a down-level workstation service
  1009. Arguments:
  1010. ServerName - where to remote this function
  1011. Level - of information required (100, or 101)
  1012. Buffer - pointer to pointer to returned buffer
  1013. Return Value:
  1014. NET_API_STATUS
  1015. Success - NERR_Success
  1016. Failure - ERROR_INVALID_LEVEL
  1017. Level not 0
  1018. ERROR_INVALID_PARAMETER
  1019. Unsupported options requested
  1020. ERROR_NOT_SUPPORTED
  1021. Service is not SERVER or WORKSTATION
  1022. ERROR_ACCESS_DENIED
  1023. Caller doesn't have necessary access rights for request
  1024. --*/
  1025. {
  1026. NET_API_STATUS status;
  1027. GENERIC_INFO_CONTAINER GenericInfoContainer;
  1028. GENERIC_ENUM_STRUCT InfoStruct;
  1029. //
  1030. // set the caller's buffer pointer to known value. This will kill the
  1031. // calling app if it gave us a bad pointer and didn't use try...except
  1032. //
  1033. *Buffer = NULL;
  1034. //
  1035. // validate parms
  1036. //
  1037. if (Level != 100 && Level != 101) {
  1038. return ERROR_INVALID_LEVEL;
  1039. }
  1040. GenericInfoContainer.Buffer = NULL;
  1041. GenericInfoContainer.EntriesRead = 0;
  1042. InfoStruct.Container = &GenericInfoContainer;
  1043. InfoStruct.Level = Level;
  1044. NET_REMOTE_TRY_RPC
  1045. status = NetrBrowserStatisticsGet(ServerName,
  1046. Level,
  1047. (PBROWSER_STATISTICS_STRUCT)&InfoStruct
  1048. );
  1049. if (status == NERR_Success || status == ERROR_MORE_DATA) {
  1050. *Buffer = (LPBYTE) GenericInfoContainer.Buffer;
  1051. }
  1052. NET_REMOTE_RPC_FAILED("NetBrowserStatisticsGet",
  1053. ServerName,
  1054. status,
  1055. NET_REMOTE_FLAG_NORMAL,
  1056. SERVICE_BROWSER
  1057. )
  1058. status = ERROR_NOT_SUPPORTED;
  1059. NET_REMOTE_END
  1060. return status;
  1061. }
  1062. NET_API_STATUS
  1063. I_BrowserSetNetlogonState(
  1064. IN LPWSTR ServerName,
  1065. IN LPWSTR DomainName,
  1066. IN LPWSTR EmulatedComputerName,
  1067. IN DWORD Role
  1068. )
  1069. /*++
  1070. Routine Description:
  1071. This is the DLL entrypoint for I_BrowserSetNetlogonState.
  1072. Arguments:
  1073. servername - Supplies the name of server to execute this function
  1074. DomainName - name of the domain who's role is to be updated.
  1075. EmulatedComputerName - Name of the computer within DomainName
  1076. Role - Role of the specified domain.
  1077. Return Value:
  1078. NET_API_STATUS - NERR_Success or reason for failure.
  1079. --*/
  1080. {
  1081. NET_API_STATUS status;
  1082. NET_REMOTE_TRY_RPC
  1083. //
  1084. // Try RPC (local or remote) version of API.
  1085. //
  1086. status = I_BrowserrSetNetlogonState (
  1087. ServerName,
  1088. DomainName,
  1089. EmulatedComputerName,
  1090. Role );
  1091. NET_REMOTE_RPC_FAILED("I_BrowserSetNetlogonState",
  1092. ServerName,
  1093. status,
  1094. NET_REMOTE_FLAG_NORMAL,
  1095. SERVICE_BROWSER )
  1096. //
  1097. // There is no downlevel version of api.
  1098. //
  1099. status = ERROR_NOT_SUPPORTED;
  1100. NET_REMOTE_END
  1101. return status;
  1102. }
  1103. NET_API_STATUS NET_API_FUNCTION
  1104. I_BrowserQueryEmulatedDomains (
  1105. IN LPTSTR ServerName OPTIONAL,
  1106. OUT PBROWSER_EMULATED_DOMAIN *EmulatedDomains,
  1107. OUT LPDWORD EntriesRead
  1108. )
  1109. /*++
  1110. Routine Description:
  1111. This is the DLL entrypoint for I_BrowserQueryEmulatedDomains.
  1112. Arguments:
  1113. ServerName - Supplies the name of server to execute this function
  1114. EmulatedDomains - Returns a pointer to a an allocated array of emulated domain
  1115. information.
  1116. EntriesRead - Returns the number of entries in 'EmulatedDomains'
  1117. Return Value:
  1118. NET_API_STATUS - NERR_Success or reason for failure.
  1119. --*/
  1120. {
  1121. NET_API_STATUS NetStatus;
  1122. BROWSER_EMULATED_DOMAIN_CONTAINER Container;
  1123. // Force RPC to allocate the buffer
  1124. Container.Buffer = NULL;
  1125. Container.EntriesRead = 0;
  1126. *EmulatedDomains = NULL;
  1127. *EntriesRead = 0;
  1128. NET_REMOTE_TRY_RPC
  1129. //
  1130. // Try RPC (local or remote) version of API.
  1131. //
  1132. NetStatus = I_BrowserrQueryEmulatedDomains (
  1133. ServerName,
  1134. &Container );
  1135. if ( NetStatus == NERR_Success ) {
  1136. *EmulatedDomains = (PBROWSER_EMULATED_DOMAIN) Container.Buffer;
  1137. *EntriesRead = Container.EntriesRead;
  1138. }
  1139. NET_REMOTE_RPC_FAILED("I_BrowserQueryEmulatedDomains",
  1140. ServerName,
  1141. NetStatus,
  1142. NET_REMOTE_FLAG_NORMAL,
  1143. SERVICE_BROWSER )
  1144. //
  1145. // There is no downlevel version of api.
  1146. //
  1147. NetStatus = ERROR_NOT_SUPPORTED;
  1148. NET_REMOTE_END
  1149. return NetStatus;
  1150. }
  1151. #if DBG
  1152. void
  1153. ValidateServerList(
  1154. IN PVOID ServerList,
  1155. IN ULONG ulLevel,
  1156. IN ULONG ulEntries
  1157. )
  1158. /*++
  1159. Routine Description (ValidateServerList):
  1160. Cycle through servers. Validate the content in the list of server
  1161. Arguments:
  1162. Return Value:
  1163. Remarks:
  1164. None.
  1165. --*/
  1166. {
  1167. LONG i;
  1168. ULONG ServerElementSize;
  1169. PSERVER_INFO_101 ServerInfo = (PSERVER_INFO_101)ServerList;
  1170. static BOOL bDisplayEntries = FALSE;
  1171. ASSERT (ulLevel == 100 || ulLevel == 101);
  1172. //
  1173. // Figure out the size of each element.
  1174. //
  1175. if (ulLevel == 100) {
  1176. ServerElementSize = sizeof(SERVER_INFO_100);
  1177. } else {
  1178. ASSERT( ulLevel == 101 );
  1179. ServerElementSize = sizeof(SERVER_INFO_101);
  1180. }
  1181. //
  1182. // Next check to see if the input list is sorted.
  1183. //
  1184. if ( bDisplayEntries ) {
  1185. DbgPrint("Server List:\n");
  1186. }
  1187. for (i = 0 ; i < (LONG)ulEntries ; i++ ) {
  1188. if ( bDisplayEntries ) {
  1189. DbgPrint("<%d>: [0x%x] %S\n",
  1190. i,
  1191. ServerInfo->sv101_platform_id,
  1192. ServerInfo->sv101_name);
  1193. }
  1194. ASSERT (ServerInfo->sv101_name &&
  1195. wcslen(ServerInfo->sv101_name) > 0);
  1196. ServerInfo = (PSERVER_INFO_101)((PCHAR)ServerInfo + ServerElementSize);
  1197. }
  1198. }
  1199. #endif