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.

1187 lines
34 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. address.c
  5. Abstract:
  6. This module contains the code to support NPGetAddressByName.
  7. Author:
  8. Yi-Hsin Sung (yihsins) 18-Apr-94
  9. Revision History:
  10. yihsins Created
  11. --*/
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #include <windows.h>
  16. #include <winsock2.h>
  17. #include "ncp.h"
  18. #include <wsipx.h>
  19. #include <ws2spi.h>
  20. #include <nwxchg.h>
  21. #include <ntddnwfs.h>
  22. #include <rpc.h>
  23. #include <rpcdce.h>
  24. #include "rnrdefs.h"
  25. #include "sapcmn.h"
  26. #include <time.h>
  27. #include <rnraddrs.h>
  28. //-------------------------------------------------------------------//
  29. // //
  30. // Special Externs
  31. // //
  32. //-------------------------------------------------------------------//
  33. NTSTATUS
  34. NwOpenAServer(
  35. PWCHAR pwszServName,
  36. PHANDLE ServerHandle,
  37. BOOL fVerify
  38. );
  39. //-------------------------------------------------------------------//
  40. // //
  41. // Local Function Prototypes //
  42. // //
  43. //-------------------------------------------------------------------//
  44. #define IPX_ADDRESS_LENGTH 12
  45. #define MAX_PROPERTY_BUFFER_LENGTH 128
  46. DWORD
  47. NwrpGetAddressByNameInner(
  48. IN HANDLE hServer,
  49. IN WORD nServiceType,
  50. IN LPWSTR lpServiceName,
  51. IN BOOL fAnsi,
  52. IN OUT LPSOCKADDR_IPX lpSockAddr,
  53. OUT PDWORD pdwVersion
  54. );
  55. BOOL
  56. NwConvertToUnicode(
  57. OUT LPWSTR *UnicodeOut,
  58. IN LPSTR OemIn
  59. );
  60. DWORD
  61. NwMapBinderyCompletionCode(
  62. IN NTSTATUS ntstatus
  63. );
  64. #if 0
  65. DWORD
  66. NwpFetchClassType(
  67. HANDLE hServer,
  68. PUNICODE_STRING pUString,
  69. PBYTE pbBuffer
  70. );
  71. #endif
  72. DWORD
  73. NwppGetClassInfo(
  74. IN PWCHAR pwszServerName,
  75. IN LPWSTR lpszServiceClassName,
  76. IN LPGUID lpServiceClassType,
  77. OUT PLONG plSpare,
  78. OUT PDWORD pdwClassInfos,
  79. OUT LPGUID lpFoundType,
  80. OUT PWCHAR *ppwszFoundName,
  81. IN LONG lSpace,
  82. OUT PBYTE pbBuffer
  83. );
  84. BOOL
  85. NwpEnumClassInfoServers(
  86. IN OUT PHANDLE phServ,
  87. IN OUT PLONG plIndex,
  88. IN PWCHAR pwszServerName,
  89. IN BOOL fVerify
  90. );
  91. #if 0
  92. DWORD
  93. NwppSetClassInfo(
  94. IN LPWSTR pwszClassInfoName,
  95. IN LPGUID lpClassType,
  96. IN PCHAR pbProperty,
  97. IN LPWSTR pwszServerName
  98. );
  99. #endif
  100. DWORD
  101. NwpCreateAndWriteProperty(
  102. IN HANDLE hServer,
  103. IN LPSTR lpszPropertyName,
  104. IN PUNICODE_STRING pusObjectName,
  105. IN WORD ObjectType,
  106. IN PCHAR pbPropertyBuffer
  107. );
  108. //-------------------------------------------------------------------//
  109. // //
  110. // Function Bodies //
  111. // //
  112. //-------------------------------------------------------------------//
  113. DWORD
  114. NwpGetHandleForServer(
  115. PWCHAR pwszServerName,
  116. PHANDLE phServer,
  117. BOOL fVerify
  118. )
  119. /*++
  120. Routine Description:
  121. Find a handle to use, or make one. This calls into device.c to do the
  122. real work.
  123. --*/
  124. {
  125. DWORD err = NO_ERROR;
  126. if(!*phServer)
  127. {
  128. if(!pwszServerName)
  129. {
  130. pwszServerName = NW_RDR_PREFERRED_SUFFIX;
  131. }
  132. err = NwOpenAServer(pwszServerName, phServer, fVerify);
  133. }
  134. return(err);
  135. }
  136. DWORD
  137. NwpGetRnRAddress(
  138. IN OUT PHANDLE phServer,
  139. IN LPWSTR lpszContext,
  140. IN OUT PLONG plIndex,
  141. IN LPWSTR lpServiceName,
  142. IN WORD nType,
  143. OUT PDWORD pdwVersion,
  144. DWORD dwInSize,
  145. OUT LPWSTR ServiceName,
  146. OUT LPSOCKADDR_IPX lpSockAddr
  147. )
  148. /*++
  149. Routine Description:
  150. Called to get the name and address of the next item of nType type.
  151. If a name is supplied as well, then there is no enumeration. This is
  152. called from NSPLookupServiceNext and the parameters are close analogs
  153. of the ones it receives.
  154. --*/
  155. {
  156. NTSTATUS ntstatus;
  157. CHAR szObjectName[48];
  158. DWORD err = NO_ERROR;
  159. PWCHAR pwszObjectName;
  160. PWCHAR pwszConv;
  161. BOOL fAll, fAnsi;
  162. //
  163. // Open a server for enumeration and querying
  164. //
  165. err = NwpGetHandleForServer(lpszContext, phServer, FALSE);
  166. if(err == NO_ERROR)
  167. {
  168. if(!lpServiceName)
  169. {
  170. lpServiceName = L"*";
  171. }
  172. if(wcschr(lpServiceName, L'*'))
  173. {
  174. WORD ObjectType;
  175. //
  176. // we've no name, or we have an enumeration
  177. //
  178. UNICODE_STRING U;
  179. RtlInitUnicodeString(&U, lpServiceName);
  180. ntstatus = NwlibMakeNcp(
  181. *phServer,
  182. FSCTL_NWR_NCP_E3H,
  183. 58,
  184. 59,
  185. "bdwU|dwc",
  186. 0x37,
  187. *plIndex,
  188. nType,
  189. &U,
  190. plIndex,
  191. &ObjectType,
  192. &szObjectName);
  193. if(NT_SUCCESS(ntstatus))
  194. {
  195. //
  196. // got another one.
  197. //
  198. //
  199. // got another one. Convert the name
  200. //
  201. if(!NwConvertToUnicode(&pwszConv, szObjectName))
  202. {
  203. //
  204. // out of space ...
  205. //
  206. err = WN_NO_MORE_ENTRIES;
  207. }
  208. fAll = TRUE;
  209. if(nType == OT_DIRSERVER)
  210. {
  211. //
  212. // looking for DIRSERVERs is tricky and requires
  213. // preserving the name intact. This includes some
  214. // binary cruft, so special case it.
  215. //
  216. fAnsi = TRUE;
  217. pwszObjectName = (PWCHAR)szObjectName;
  218. }
  219. else
  220. {
  221. fAnsi = FALSE;
  222. pwszObjectName = pwszConv;
  223. }
  224. }
  225. }
  226. else
  227. {
  228. //
  229. // a non-enumerattion name was given. Use it
  230. //
  231. fAnsi = FALSE;
  232. pwszConv = pwszObjectName = lpServiceName;
  233. fAll = FALSE;
  234. ntstatus = 0;
  235. }
  236. if((err == NO_ERROR)
  237. &&
  238. NT_SUCCESS(ntstatus))
  239. {
  240. //
  241. // we've a name and type to lookup. Call the old RnR
  242. // serice routine to do it. First, return the name.
  243. // But return the name first
  244. DWORD dwLen;
  245. if(fAnsi)
  246. {
  247. //
  248. // it's an NDS tree server. Have to munge the name
  249. // a bit
  250. //
  251. PWCHAR pwszTemp = &pwszConv[31];
  252. while(*pwszTemp == L'_')
  253. {
  254. pwszTemp--;
  255. }
  256. dwLen = (DWORD) ((PCHAR)pwszTemp - (PCHAR)pwszConv + sizeof(WCHAR));
  257. }
  258. else
  259. {
  260. dwLen = wcslen(pwszConv) * sizeof(WCHAR);
  261. }
  262. dwLen = min(dwInSize, dwLen);
  263. RtlCopyMemory(ServiceName, pwszConv, dwLen);
  264. memset(((PBYTE)ServiceName) + dwLen,
  265. 0,
  266. dwInSize - dwLen);
  267. err = NwrpGetAddressByNameInner(
  268. *phServer,
  269. nType,
  270. pwszObjectName,
  271. fAnsi,
  272. lpSockAddr,
  273. pdwVersion);
  274. if(fAll)
  275. {
  276. LocalFree(pwszConv);
  277. }
  278. }
  279. }
  280. if(err == NO_ERROR)
  281. {
  282. err = NwMapBinderyCompletionCode(ntstatus);
  283. }
  284. return(err);
  285. }
  286. DWORD
  287. NwpGetAddressByName(
  288. IN LPWSTR Reserved,
  289. IN WORD nServiceType,
  290. IN LPWSTR lpServiceName,
  291. IN OUT LPSOCKADDR_IPX lpSockAddr
  292. )
  293. /*++
  294. Routine Description:
  295. This routine returns address information about a specific service.
  296. Arguments:
  297. Reserved - unused
  298. nServiceType - netware service type
  299. lpServiceName - unique string representing the service name, in the
  300. Netware case, this is the server name
  301. lpSockAddr - on return, will be filled with SOCKADDR_IPX
  302. Return Value:
  303. Win32 error.
  304. --*/
  305. {
  306. NTSTATUS ntstatus;
  307. HANDLE hServer = 0;
  308. DWORD err;
  309. UNREFERENCED_PARAMETER( Reserved );
  310. err = NwpGetHandleForServer( 0, &hServer, FALSE );
  311. if ( err == ERROR_PATH_NOT_FOUND )
  312. err = ERROR_SERVICE_NOT_ACTIVE;
  313. if (err == NO_ERROR)
  314. {
  315. err = NwrpGetAddressByNameInner(
  316. hServer,
  317. nServiceType,
  318. lpServiceName,
  319. FALSE,
  320. lpSockAddr,
  321. 0);
  322. CloseHandle(hServer);
  323. }
  324. return(err);
  325. }
  326. DWORD
  327. NwrpGetAddressByNameInner(
  328. IN HANDLE hServer,
  329. IN WORD nServiceType,
  330. IN LPWSTR lpServiceName,
  331. IN BOOL fAnsi,
  332. IN OUT LPSOCKADDR_IPX lpSockAddr,
  333. OUT PDWORD pdwVersion
  334. )
  335. /*++
  336. Routine Description:
  337. This routine returns address information about a specific service.
  338. Arguments:
  339. Reserved - unused
  340. nServiceType - netware service type
  341. lpServiceName - unique string representing the service name, in the
  342. Netware case, this is the server name
  343. lpSockAddr - on return, will be filled with SOCKADDR_IPX
  344. fAnsi -- the input name is in ASCII. This happens only when looking
  345. for a DIRSERVER.
  346. Return Value:
  347. Win32 error.
  348. --*/
  349. {
  350. NTSTATUS ntstatus;
  351. UNICODE_STRING UServiceName;
  352. STRING PropertyName;
  353. BYTE PropertyValueBuffer[MAX_PROPERTY_BUFFER_LENGTH];
  354. BYTE fMoreSegments;
  355. PCHAR pszFormat;
  356. //
  357. // Send an ncp to find the address of the given service name
  358. //
  359. RtlInitString( &PropertyName, "NET_ADDRESS" );
  360. if(!fAnsi)
  361. {
  362. RtlInitUnicodeString( &UServiceName, lpServiceName );
  363. pszFormat = "bwUbp|rb";
  364. ntstatus = NwlibMakeNcp(
  365. hServer,
  366. FSCTL_NWR_NCP_E3H, // Bindery function
  367. 72, // Max request packet size
  368. 132, // Max response packet size
  369. pszFormat, // Format string
  370. 0x3D, // Read Property Value
  371. nServiceType, // Object Type
  372. &UServiceName, // Object Name
  373. 1, // Segment Number
  374. PropertyName.Buffer, // Property Name
  375. PropertyValueBuffer, // Ignore
  376. MAX_PROPERTY_BUFFER_LENGTH, // size of buffer
  377. &fMoreSegments // TRUE if there are more
  378. // 128-byte segments
  379. );
  380. if ( NT_SUCCESS( ntstatus))
  381. {
  382. //
  383. // IPX address should fit into the first 128 byte
  384. //
  385. ASSERT( !fMoreSegments );
  386. //
  387. // Fill in the return buffer
  388. //
  389. lpSockAddr->sa_family = AF_IPX;
  390. RtlCopyMemory( lpSockAddr->sa_netnum,
  391. PropertyValueBuffer,
  392. IPX_ADDRESS_LENGTH );
  393. if(pdwVersion)
  394. {
  395. //
  396. // the caller wants the version as well. Get it
  397. //
  398. RtlInitString( &PropertyName, "VERSION" );
  399. ntstatus = NwlibMakeNcp(
  400. hServer,
  401. FSCTL_NWR_NCP_E3H, // Bindery function
  402. 72, // Max request packet size
  403. 132, // Max response packet size
  404. pszFormat, // Format string
  405. 0x3D, // Read Property Value
  406. nServiceType, // Object Type
  407. &UServiceName, // Object Name
  408. 1, // Segment Number
  409. PropertyName.Buffer, // Property Name
  410. PropertyValueBuffer, // Ignore
  411. MAX_PROPERTY_BUFFER_LENGTH, // size of buffer
  412. &fMoreSegments // TRUE if there are more
  413. // 128-byte segments
  414. );
  415. if(NT_SUCCESS(ntstatus))
  416. {
  417. //
  418. // have a version
  419. //
  420. *pdwVersion = *(PDWORD)PropertyValueBuffer;
  421. }
  422. else
  423. {
  424. ntstatus = STATUS_SUCCESS;
  425. *pdwVersion = 0;
  426. }
  427. }
  428. }
  429. }
  430. else
  431. {
  432. //
  433. // exact match needed
  434. //
  435. pszFormat = "bwbrbp|rb";
  436. ntstatus = NwlibMakeNcp(
  437. hServer,
  438. FSCTL_NWR_NCP_E3H, // Bindery function
  439. 66, // Max request packet size
  440. 132, // Max response packet size
  441. pszFormat, // Format string
  442. 0x3D, // Read Property Value
  443. nServiceType, // Object Type
  444. 48,
  445. lpServiceName, // Object Name
  446. 48,
  447. 1, // Segment Number
  448. PropertyName.Buffer, // Property Name
  449. PropertyValueBuffer, // Ignore
  450. MAX_PROPERTY_BUFFER_LENGTH, // size of buffer
  451. &fMoreSegments // TRUE if there are more
  452. // 128-byte segments
  453. );
  454. if ( NT_SUCCESS( ntstatus))
  455. {
  456. //
  457. // IPX address should fit into the first 128 byte
  458. //
  459. ASSERT( !fMoreSegments );
  460. //
  461. // Fill in the return buffer
  462. //
  463. lpSockAddr->sa_family = AF_IPX;
  464. RtlCopyMemory( lpSockAddr->sa_netnum,
  465. PropertyValueBuffer,
  466. IPX_ADDRESS_LENGTH );
  467. if(pdwVersion)
  468. {
  469. //
  470. // the caller wants the version as well. Get it
  471. //
  472. RtlInitString( &PropertyName, "VERSION" );
  473. ntstatus = NwlibMakeNcp(
  474. hServer,
  475. FSCTL_NWR_NCP_E3H, // Bindery function
  476. 66, // Max request packet size
  477. 132, // Max response packet size
  478. pszFormat, // Format string
  479. 0x3D, // Read Property Value
  480. nServiceType, // Object Type
  481. 48,
  482. lpServiceName, // Object Name
  483. 48,
  484. 1, // Segment Number
  485. PropertyName.Buffer, // Property Name
  486. PropertyValueBuffer, // Ignore
  487. MAX_PROPERTY_BUFFER_LENGTH, // size of buffer
  488. &fMoreSegments // TRUE if there are more
  489. // 128-byte segments
  490. );
  491. if(NT_SUCCESS(ntstatus))
  492. {
  493. //
  494. // have a version
  495. //
  496. *pdwVersion = *(PDWORD)PropertyValueBuffer;
  497. }
  498. else
  499. {
  500. ntstatus = STATUS_SUCCESS;
  501. *pdwVersion = 0;
  502. }
  503. }
  504. }
  505. }
  506. return NwMapBinderyCompletionCode(ntstatus);
  507. }
  508. #if 0
  509. DWORD
  510. NwpSetClassInfo(
  511. IN LPWSTR lpszServiceClassName,
  512. IN LPGUID lpServiceClassType,
  513. IN PCHAR lpbProperty
  514. )
  515. {
  516. WCHAR wszServerName[48];
  517. LONG lIndex = -1;
  518. BOOL fFoundOne = FALSE;
  519. HANDLE hServer = 0;
  520. while(NwpEnumClassInfoServers( &hServer, &lIndex, wszServerName, FALSE))
  521. {
  522. DWORD Status = NwppSetClassInfo(
  523. lpszServiceClassName,
  524. lpServiceClassType,
  525. lpbProperty,
  526. wszServerName);
  527. if(Status == NO_ERROR)
  528. {
  529. fFoundOne = TRUE;
  530. }
  531. }
  532. if(fFoundOne)
  533. {
  534. return(NO_ERROR);
  535. }
  536. return(NO_DATA);
  537. }
  538. DWORD
  539. NwppSetClassInfo(
  540. IN LPWSTR pwszClassInfoName,
  541. IN LPGUID lpClassType,
  542. IN PCHAR pbProperty,
  543. IN LPWSTR pwszServerName
  544. )
  545. {
  546. /*++
  547. Routine Description:
  548. Inner routine for SetClassInfo. This is called for each class info
  549. server and attempts to create and populate the object
  550. --*/
  551. HANDLE hServer = 0;
  552. DWORD err;
  553. UNICODE_STRING UString;
  554. WCHAR wszProp[48];
  555. DWORD dwLen = wcslen(pwszClassInfoName);
  556. PWCHAR pszProp;
  557. NTSTATUS Status;
  558. UuidToString(lpClassType, &pszProp);
  559. memset(wszProp, 0, sizeof(wszProp));
  560. dwLen = min(sizeof(wszProp) - sizeof(WCHAR), dwLen);
  561. RtlMoveMemory(wszProp, pwszClassInfoName, dwLen);
  562. RtlInitUnicodeString(&UString, pszProp);
  563. err = NwpGetHandleForServer(pwszServerName, &hServer, TRUE);
  564. if(err == NO_ERROR)
  565. {
  566. Status = NwlibMakeNcp(
  567. hServer,
  568. FSCTL_NWR_NCP_E3H,
  569. 56,
  570. 2,
  571. "bbbwU|",
  572. 0x32, // create
  573. 0, // static
  574. 0x20, // security
  575. RNRCLASSSAPTYPE, // type
  576. &UString);
  577. if(!NT_SUCCESS(Status)
  578. &&
  579. ((Status & 0xff) != 0xEE))
  580. {
  581. err = NO_DATA; // can't do it here
  582. }
  583. else
  584. {
  585. //
  586. // create and write each property
  587. //
  588. err = NwpCreateAndWriteProperty(
  589. hServer,
  590. RNRTYPE, // property name
  591. &UString, // object name
  592. RNRCLASSSAPTYPE, // object type
  593. (PCHAR)pwszClassInfoName);
  594. err = NwpCreateAndWriteProperty(
  595. hServer,
  596. RNRCLASSES,
  597. &UString,
  598. RNRCLASSSAPTYPE, // object type
  599. pbProperty); // and this one too
  600. }
  601. }
  602. if(hServer)
  603. {
  604. CloseHandle(hServer);
  605. }
  606. RpcStringFree(&pszProp);
  607. return(err);
  608. }
  609. DWORD
  610. NwpGetClassInfo(
  611. IN LPWSTR lpszServiceClassName,
  612. IN LPGUID lpServiceClassType,
  613. OUT PLONG plSpare,
  614. OUT PDWORD pdwClassInfos,
  615. OUT LPGUID lpFoundType,
  616. OUT PWCHAR *ppwszFoundName,
  617. IN LONG lSpace,
  618. OUT PBYTE pbBuffer
  619. )
  620. {
  621. /*++
  622. Routine Description:
  623. Wrapper for the routine below. This comes up with the server name
  624. and decides whether to enumerate servers
  625. --*/
  626. HANDLE hServer = 0;
  627. DWORD err;
  628. NTSTATUS ntstatus;
  629. LONG lIndex = -1;
  630. HANDLE hServ = 0;
  631. WCHAR wszObjectName[48];
  632. while(NwpEnumClassInfoServers(&hServer, &lIndex, wszObjectName, FALSE))
  633. {
  634. WORD ObjectType;
  635. PWCHAR pwszName;
  636. err = NwppGetClassInfo(
  637. wszObjectName,
  638. lpszServiceClassName,
  639. lpServiceClassType,
  640. plSpare,
  641. pdwClassInfos,
  642. lpFoundType,
  643. ppwszFoundName,
  644. lSpace,
  645. pbBuffer);
  646. if((err == NO_ERROR)
  647. ||
  648. (err == WSAEFAULT))
  649. {
  650. CloseHandle(hServer);
  651. break;
  652. }
  653. }
  654. return(err);
  655. }
  656. BOOL
  657. NwpEnumClassInfoServers(
  658. IN OUT PHANDLE phServer,
  659. IN OUT PLONG plIndex,
  660. OUT PWCHAR pwszServerName,
  661. IN BOOL fVerify)
  662. {
  663. /*++
  664. Routine Description:
  665. Common routine to enumerate Class Info servers. Nothing fancy just
  666. a way to issue the NCP
  667. --*/
  668. WORD ObjectType;
  669. PWCHAR pwszName;
  670. NTSTATUS Status;
  671. CHAR szObjectName[48];
  672. BOOL fRet;
  673. DWORD err;
  674. err = NwpGetHandleForServer(0, phServer, fVerify);
  675. if(err == NO_ERROR)
  676. {
  677. Status = NwlibMakeNcp(
  678. *phServer,
  679. FSCTL_NWR_NCP_E3H,
  680. 58,
  681. 59,
  682. "bdwp|dwc",
  683. 0x37,
  684. *plIndex,
  685. CLASSINFOSAPID,
  686. "*",
  687. plIndex,
  688. &ObjectType,
  689. &szObjectName);
  690. if(!NT_SUCCESS(Status))
  691. {
  692. err = NwMapBinderyCompletionCode(Status);
  693. }
  694. else if(!NwConvertToUnicode(&pwszName, szObjectName))
  695. {
  696. err = ERROR_NOT_ENOUGH_MEMORY;
  697. }
  698. else
  699. {
  700. wcscpy(pwszServerName, pwszName);
  701. LocalFree(pwszName);
  702. }
  703. }
  704. if(err != NO_ERROR)
  705. {
  706. fRet = FALSE;
  707. if(*phServer)
  708. {
  709. CloseHandle(*phServer);
  710. *phServer = 0;
  711. }
  712. }
  713. else
  714. {
  715. fRet = TRUE;
  716. }
  717. return(fRet);
  718. }
  719. DWORD
  720. NwppGetClassInfo(
  721. IN PWCHAR pwszServerName,
  722. IN LPWSTR lpszServiceClassName,
  723. IN LPGUID lpServiceClassType,
  724. OUT PLONG plSpare,
  725. OUT PDWORD pdwClassInfos,
  726. OUT LPGUID lpFoundType,
  727. OUT PWCHAR *ppwszFoundName,
  728. IN LONG lSpace,
  729. OUT PBYTE pbBuffer
  730. )
  731. {
  732. /*++
  733. Routine Description
  734. Find and return the class info information for the given Class.
  735. The general methodology is to look up the object
  736. in the registry, pull out the RnR property, pack what is read into
  737. Class Info structures, and voila!
  738. Arguments:
  739. lpServiceClassName the class name
  740. lpServiceClassType the class type
  741. plSpare Space needed if no class infos returned
  742. pdwClassInfos Number of class infos returned
  743. lSpace the space available on input
  744. pbBuffer the scratch are for building this
  745. This was originally an RPC method and the general structure has been preserved
  746. in case we want to revert to using RPC once again.
  747. --*/
  748. DWORD err = NO_ERROR;
  749. BYTE PropertyValueBuffer[MAX_PROPERTY_BUFFER_LENGTH]; // max segment size
  750. STRING PropertyName;
  751. UNICODE_STRING UString;
  752. OEM_STRING OString;
  753. LPWSANSCLASSINFOW pci = (LPWSANSCLASSINFO)pbBuffer;
  754. LONG lFreeSpace = lSpace;
  755. PBYTE pbFreeSpace = (PBYTE)((LONG)pbBuffer + lFreeSpace);
  756. BYTE fMoreSegments;
  757. HANDLE hServer = 0;
  758. NTSTATUS ntstatus;
  759. PWCHAR pwszName;
  760. UuidToString(lpServiceClassType, &pwszName);
  761. *pdwClassInfos = 0;
  762. *plSpare = 0; // no space needed yet.
  763. err = NwpGetHandleForServer(pwszServerName, &hServer, FALSE);
  764. if(err == NO_ERROR)
  765. {
  766. DWORD Segment;
  767. PBINDERYCLASSES pbc = (PBINDERYCLASSES)PropertyValueBuffer;
  768. DWORD dwTotalSize;
  769. DWORD dwSS;
  770. //
  771. // init the Class Info stuff
  772. //
  773. //
  774. // pwszName is the name of the object we want to use. We must
  775. // fetch all of the Class Info stuff to return.
  776. //
  777. //
  778. RtlInitUnicodeString(&UString, pwszName);
  779. RtlMoveMemory(lpFoundType,
  780. lpServiceClassType,
  781. sizeof(GUID));
  782. RtlInitString(&PropertyName, RNRCLASSES); // where the data is
  783. for(Segment = 1;; Segment++)
  784. {
  785. ntstatus = NwlibMakeNcp(
  786. hServer,
  787. FSCTL_NWR_NCP_E3H, // Bindery function
  788. 72, // Max request packet size
  789. 132, // Max response packet size
  790. "bwUbp|rb", // Format string
  791. 0x3D, // Read Property Value
  792. RNRCLASSSAPTYPE, // Object Type
  793. &UString, // Object Name
  794. (BYTE)Segment,
  795. PropertyName.Buffer, // Property Name
  796. PropertyValueBuffer, // Ignore
  797. MAX_PROPERTY_BUFFER_LENGTH, // size of buffer
  798. &fMoreSegments // TRUE if there are more
  799. // 128-byte segments
  800. );
  801. if(!NT_SUCCESS(ntstatus))
  802. {
  803. break;
  804. }
  805. //
  806. // got another value. Stuff it in if it fits. In all
  807. // cases, compute the space needed.
  808. //
  809. if((pbc->bType != BT_WORD)
  810. &&
  811. (pbc->bType != BT_DWORD))
  812. {
  813. //
  814. // Don't know what to do with these ...
  815. //
  816. err = WSAEPFNOSUPPORT;
  817. break;
  818. }
  819. dwSS = (DWORD)pbc->bSizeOfString;
  820. dwTotalSize = (DWORD)pbc->bSizeOfType +
  821. ((dwSS + 1) * sizeof(WCHAR)) +
  822. sizeof(DWORD) - 1;
  823. dwTotalSize &= ~(sizeof(DWORD) - 1);
  824. *plSpare += (LONG)dwTotalSize + sizeof(WSANSCLASSINFO); // running total
  825. lFreeSpace -= (LONG)dwTotalSize + sizeof(WSANSCLASSINFO);
  826. if(lFreeSpace >= 0)
  827. {
  828. PBYTE pbString;
  829. PCHAR pbData = (PCHAR)((PCHAR)pbc +
  830. (DWORD)pbc->bOffset);
  831. BYTE bRnRName[128];
  832. PWCHAR pwszRnR;
  833. //
  834. // it fits. Pack it in
  835. //
  836. pbFreeSpace = (PBYTE)((DWORD)pbFreeSpace - dwTotalSize);
  837. *pdwClassInfos += 1; // one more class info.
  838. pci->dwNameSpace = (DWORD)ntohs(pbc->wNameSpace);
  839. pci->dwValueType = REG_DWORD;
  840. pci->dwValueSize = (DWORD)pbc->bSizeOfType;
  841. pci->lpValue = (PVOID)(pbFreeSpace - pbBuffer);
  842. pci->lpszName = (PWCHAR)((PBYTE)pci->lpValue +
  843. pci->dwValueSize);
  844. pci->dwConnectionFlags = (DWORD)pbc->bFlags;
  845. pci++;
  846. //
  847. // now copy the values.
  848. //
  849. if(pbc->bType == BT_WORD)
  850. {
  851. *(PWORD)pbFreeSpace = ntohs(*(PWORD)pbData);
  852. pbString = (PBYTE)((DWORD)pbFreeSpace + sizeof(WORD));
  853. pbData = pbData + sizeof(WORD);
  854. }
  855. else
  856. {
  857. *(PDWORD)pbFreeSpace = ntohl(*(PDWORD)pbData);
  858. pbString = (PBYTE)((DWORD)pbFreeSpace + sizeof(DWORD));
  859. pbData = pbData + sizeof(DWORD);
  860. }
  861. //
  862. // the name is in ASCII, and not null terminated.
  863. //
  864. RtlMoveMemory(bRnRName, pbData, dwSS);
  865. bRnRName[dwSS] = 0;
  866. if(!NwConvertToUnicode(&pwszRnR, bRnRName))
  867. {
  868. //
  869. // bad news. Out of space.
  870. //
  871. err = GetLastError();
  872. break;
  873. }
  874. RtlMoveMemory(pbString,
  875. pwszRnR,
  876. (dwSS + 1) * sizeof(WCHAR));
  877. LocalFree(pwszRnR);
  878. }
  879. }
  880. if(err == NO_ERROR)
  881. {
  882. if(!*ppwszFoundName)
  883. {
  884. LONG lLen;
  885. //
  886. // need to return the name
  887. //
  888. err = NwpFetchClassType(hServer,
  889. &UString,
  890. PropertyValueBuffer);
  891. if(err == NO_ERROR)
  892. {
  893. lLen = (wcslen((PWCHAR)PropertyValueBuffer) + 1) *
  894. sizeof(WCHAR);
  895. lFreeSpace -= lLen;
  896. *plSpare += lLen;
  897. if(lFreeSpace >= 0)
  898. {
  899. //
  900. // it fits. Move it
  901. pbFreeSpace = (PBYTE)((DWORD)pbFreeSpace - lLen);
  902. RtlMoveMemory(pbFreeSpace, PropertyValueBuffer, lLen);
  903. *ppwszFoundName = (PWCHAR)(pbFreeSpace - pbBuffer);
  904. }
  905. if(lFreeSpace < 0)
  906. {
  907. err = WSAEFAULT;
  908. }
  909. }
  910. }
  911. }
  912. else if(*pdwClassInfos == 0)
  913. {
  914. err = NO_DATA;
  915. }
  916. }
  917. CloseHandle(hServer);
  918. RpcStringFree(&pwszName);
  919. return(err);
  920. }
  921. DWORD
  922. NwpFetchClassType(
  923. HANDLE hServer,
  924. PUNICODE_STRING pUString,
  925. PBYTE pbBuffer)
  926. {
  927. /*++
  928. Routine Description
  929. Common routine to read the class type buffer.
  930. --*/
  931. BYTE fMoreSegments;
  932. STRING PropertyName;
  933. NTSTATUS ntstatus;
  934. RtlInitString(&PropertyName, RNRTYPE); // where the GUID is
  935. ntstatus = NwlibMakeNcp(
  936. hServer,
  937. FSCTL_NWR_NCP_E3H, // Bindery function
  938. 72, // Max request packet size
  939. 132, // Max response packet size
  940. "bwUbp|rb", // Format string
  941. 0x3D, // Read Property Value
  942. RNRCLASSSAPTYPE, // Object Type
  943. pUString, // Object Name
  944. 1, // Segment Number
  945. PropertyName.Buffer, // Property Name
  946. pbBuffer,
  947. MAX_PROPERTY_BUFFER_LENGTH, // size of buffer
  948. &fMoreSegments // TRUE if there are more
  949. // 128-byte segments
  950. );
  951. if(!NT_SUCCESS(ntstatus))
  952. {
  953. return(WSASERVICE_NOT_FOUND);
  954. }
  955. return(NO_ERROR);
  956. }
  957. #endif
  958. DWORD
  959. NwpCreateAndWriteProperty(
  960. IN HANDLE hServer,
  961. IN LPSTR lpszPropertyName,
  962. IN PUNICODE_STRING pusObjectName,
  963. IN WORD wObjectType,
  964. IN PCHAR pbPropertyBuffer
  965. )
  966. {
  967. /*++
  968. Routine Description:
  969. Create the named property and write the data.
  970. Arguments:
  971. hServer: handle to the server
  972. lpszPropertyName Name of the property
  973. pusObjectName Name of the object
  974. wObjectType Type of the object
  975. pbPropertyBuffer The property data. Must be 128 bytes
  976. Note that the return is always NO_ERROR for now. This may change in the future.
  977. --*/
  978. NTSTATUS Status;
  979. Status = NwlibMakeNcp(
  980. hServer,
  981. FSCTL_NWR_NCP_E3H,
  982. 73,
  983. 2,
  984. "bwUbbp|",
  985. 0x39, // create property
  986. wObjectType,
  987. pusObjectName,
  988. 0, // static/item
  989. 0x20, // security
  990. lpszPropertyName
  991. );
  992. //
  993. // Now write the porperty data
  994. //
  995. Status = NwlibMakeNcp(
  996. hServer,
  997. FSCTL_NWR_NCP_E3H,
  998. 201,
  999. 2,
  1000. "bwUbbpr|",
  1001. 0x3E, // write property
  1002. wObjectType,
  1003. pusObjectName,
  1004. 1, // one segment
  1005. 0,
  1006. lpszPropertyName,
  1007. pbPropertyBuffer, 128);
  1008. return(NO_ERROR);
  1009. }