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.

3019 lines
73 KiB

  1. /*++
  2. Copyright (c) 1991-1993 Microsoft Corporation
  3. Module Name:
  4. wksstub.c
  5. Abstract:
  6. Client stubs of the Workstation service APIs.
  7. Author:
  8. Rita Wong (ritaw) 10-May-1991
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. 18-Jun-1991 JohnRo
  13. Remote NetUse APIs to downlevel servers.
  14. 24-Jul-1991 JohnRo
  15. Use NET_REMOTE_TRY_RPC etc macros for NetUse APIs.
  16. Moved NetpIsServiceStarted() into NetLib.
  17. 25-Jul-1991 JohnRo
  18. Quiet DLL stub debug output.
  19. 19-Aug-1991 JohnRo
  20. Implement downlevel NetWksta APIs. Use NetRpc.h for NetWksta APIs.
  21. 07-Nov-1991 JohnRo
  22. RAID 4186: assert in RxNetShareAdd and other DLL stub problems.
  23. 19-Nov-1991 JohnRo
  24. Make sure status is correct for APIs not supported on downlevel.
  25. Implement remote NetWkstaUserEnum().
  26. 21-Jan-1991 rfirth
  27. Added NetWkstaStatisticsGet wrapper
  28. 19-Apr-1993 JohnRo
  29. Fix NET_API_FUNCTION references.
  30. --*/
  31. #include "wsclient.h"
  32. #undef IF_DEBUG // avoid wsclient.h vs. debuglib.h conflicts.
  33. #include <debuglib.h> // IF_DEBUG() (needed by netrpc.h).
  34. #include <lmapibuf.h>
  35. #include <lmserver.h>
  36. #include <lmsvc.h>
  37. #include <rxuse.h> // RxNetUse APIs.
  38. #include <rxwksta.h> // RxNetWksta and RxNetWkstaUser APIs.
  39. #include <rap.h> // Needed by rxserver.h
  40. #include <rxserver.h> // RxNetServerEnum API.
  41. #include <netlib.h> // NetpServiceIsStarted() (needed by netrpc.h).
  42. #include <netrpc.h> // NET_REMOTE macros.
  43. #include <lmstats.h>
  44. #include <netstats.h> // NetWkstaStatisticsGet prototype
  45. #include <rxstats.h>
  46. #include <netsetup.h>
  47. #include <crypt.h>
  48. #include <rc4.h>
  49. #include <md5.h>
  50. #include <rpcasync.h>
  51. #if(_WIN32_WINNT >= 0x0500)
  52. #include "cscp.h"
  53. #endif
  54. STATIC
  55. DWORD
  56. WsMapRpcError(
  57. IN DWORD RpcError
  58. );
  59. //-------------------------------------------------------------------//
  60. // //
  61. // Global variables //
  62. // //
  63. //-------------------------------------------------------------------//
  64. #if DBG
  65. DWORD WorkstationClientTrace = 0;
  66. #endif // DBG
  67. NET_API_STATUS NET_API_FUNCTION
  68. NetWkstaGetInfo(
  69. IN LPTSTR servername OPTIONAL,
  70. IN DWORD level,
  71. OUT LPBYTE *bufptr
  72. )
  73. {
  74. NET_API_STATUS status;
  75. if (bufptr == NULL) {
  76. return ERROR_INVALID_PARAMETER;
  77. }
  78. *bufptr = NULL; // Must be NULL so RPC knows to fill it in.
  79. NET_REMOTE_TRY_RPC
  80. //
  81. // Try RPC (local or remote) version of API.
  82. //
  83. status = NetrWkstaGetInfo(
  84. servername,
  85. level,
  86. (LPWKSTA_INFO) bufptr
  87. );
  88. NET_REMOTE_RPC_FAILED("NetWkstaGetInfo",
  89. servername,
  90. status,
  91. NET_REMOTE_FLAG_NORMAL,
  92. SERVICE_WORKSTATION )
  93. //
  94. // Call downlevel version of the API.
  95. //
  96. status = RxNetWkstaGetInfo(
  97. servername,
  98. level,
  99. bufptr
  100. );
  101. NET_REMOTE_END
  102. #if(_WIN32_WINNT >= 0x0500)
  103. if( *bufptr == NULL && servername != NULL &&
  104. CSCNetWkstaGetInfo( servername, level, bufptr ) == NO_ERROR ) {
  105. status = NO_ERROR;
  106. }
  107. #endif
  108. return status;
  109. }
  110. NET_API_STATUS NET_API_FUNCTION
  111. NetWkstaSetInfo(
  112. IN LPTSTR servername OPTIONAL,
  113. IN DWORD level,
  114. IN LPBYTE buf,
  115. OUT LPDWORD parm_err OPTIONAL
  116. )
  117. /*++
  118. Routine Description:
  119. This is the DLL entrypoint for NetWkstaSetInfo.
  120. Arguments:
  121. servername - Supplies the name of server to execute this function
  122. level - Supplies the level of information.
  123. buf - Supplies a buffer which contains the information structure of fields
  124. to set. The level denotes the structure in this buffer.
  125. parm_err - Returns the identifier to the invalid parameter in buf if this
  126. function returns ERROR_INVALID_PARAMETER.
  127. Return Value:
  128. NET_API_STATUS - NERR_Success or reason for failure.
  129. --*/
  130. {
  131. NET_API_STATUS status;
  132. NET_REMOTE_TRY_RPC
  133. //
  134. // Try RPC (local or remote) version of API.
  135. //
  136. status = NetrWkstaSetInfo(
  137. servername,
  138. level,
  139. (LPWKSTA_INFO) &buf,
  140. parm_err
  141. );
  142. NET_REMOTE_RPC_FAILED("NetWkstaSetInfo",
  143. servername,
  144. status,
  145. NET_REMOTE_FLAG_NORMAL,
  146. SERVICE_WORKSTATION )
  147. //
  148. // Call downlevel version of the API.
  149. //
  150. status = RxNetWkstaSetInfo(
  151. servername,
  152. level,
  153. buf,
  154. parm_err
  155. );
  156. NET_REMOTE_END
  157. return status;
  158. }
  159. NET_API_STATUS NET_API_FUNCTION
  160. NetWkstaUserEnum(
  161. IN LPTSTR servername OPTIONAL,
  162. IN DWORD level,
  163. OUT LPBYTE *bufptr,
  164. IN DWORD prefmaxlen,
  165. OUT LPDWORD entriesread,
  166. OUT LPDWORD totalentries,
  167. IN OUT LPDWORD resume_handle OPTIONAL
  168. )
  169. /*++
  170. Routine Description:
  171. This is the DLL entrypoint for NetWkstaUserEnum.
  172. Arguments:
  173. servername - Supplies the name of server to execute this function
  174. level - Supplies the requested level of information.
  175. bufptr - Returns a pointer to the buffer which contains a sequence of
  176. information structure of the specified information level. This
  177. pointer is set to NULL if return code is not NERR_Success or
  178. ERROR_MORE_DATA, or if EntriesRead returned is 0.
  179. prefmaxlen - Supplies the number of bytes of information to return in the
  180. buffer. If this value is MAXULONG, all available information will
  181. be returned.
  182. entriesread - Returns the number of entries read into the buffer. This
  183. value is only valid if the return code is NERR_Success or
  184. ERROR_MORE_DATA.
  185. totalentries - Returns the total number of entries available. This value
  186. is only valid if the return code is NERR_Success or ERROR_MORE_DATA.
  187. resume_handle - Supplies a handle to resume the enumeration from where it
  188. left off the last time through. Returns the resume handle if return
  189. code is ERROR_MORE_DATA.
  190. Return Value:
  191. NET_API_STATUS - NERR_Success or reason for failure.
  192. --*/
  193. {
  194. NET_API_STATUS status;
  195. GENERIC_INFO_CONTAINER GenericInfoContainer;
  196. GENERIC_ENUM_STRUCT InfoStruct;
  197. if (bufptr == NULL || entriesread == NULL) {
  198. return ERROR_INVALID_PARAMETER;
  199. }
  200. try {
  201. *entriesread = 0;
  202. } except( EXCEPTION_EXECUTE_HANDLER ) {
  203. return ERROR_INVALID_PARAMETER;
  204. }
  205. GenericInfoContainer.Buffer = NULL;
  206. GenericInfoContainer.EntriesRead = 0;
  207. InfoStruct.Container = &GenericInfoContainer;
  208. InfoStruct.Level = level;
  209. NET_REMOTE_TRY_RPC
  210. //
  211. // Try RPC (local or remote) version of API.
  212. //
  213. status = NetrWkstaUserEnum(
  214. servername,
  215. (LPWKSTA_USER_ENUM_STRUCT) &InfoStruct,
  216. prefmaxlen,
  217. totalentries,
  218. resume_handle
  219. );
  220. if (status == NERR_Success || status == ERROR_MORE_DATA) {
  221. *bufptr = (LPBYTE) GenericInfoContainer.Buffer;
  222. *entriesread = GenericInfoContainer.EntriesRead;
  223. }
  224. NET_REMOTE_RPC_FAILED("NetWkstaUserEnum",
  225. servername,
  226. status,
  227. NET_REMOTE_FLAG_NORMAL,
  228. SERVICE_WORKSTATION )
  229. //
  230. // Call downlevel version.
  231. //
  232. status = RxNetWkstaUserEnum(
  233. servername,
  234. level,
  235. bufptr,
  236. prefmaxlen,
  237. entriesread,
  238. totalentries,
  239. resume_handle);
  240. NET_REMOTE_END
  241. return status;
  242. }
  243. NET_API_STATUS NET_API_FUNCTION
  244. NetWkstaUserGetInfo(
  245. IN LPTSTR reserved,
  246. IN DWORD level,
  247. OUT LPBYTE *bufptr
  248. )
  249. /*++
  250. Routine Description:
  251. This is the DLL entrypoint for NetWkstaUserGetInfo.
  252. Arguments:
  253. reserved - Must be NULL.
  254. level - Supplies the requested level of information.
  255. bufptr - Returns a pointer to a buffer which contains the requested
  256. user information.
  257. Return Value:
  258. NET_API_STATUS - NERR_Success or reason for failure.
  259. --*/
  260. {
  261. NET_API_STATUS status;
  262. if (reserved != NULL || bufptr == NULL) {
  263. return ERROR_INVALID_PARAMETER;
  264. }
  265. *bufptr = NULL; // Must be NULL so RPC knows to fill it in.
  266. NET_REMOTE_TRY_RPC
  267. //
  268. // Try RPC (local only) version of API.
  269. //
  270. status = NetrWkstaUserGetInfo(
  271. NULL,
  272. level,
  273. (LPWKSTA_USER_INFO) bufptr
  274. );
  275. NET_REMOTE_RPC_FAILED("NetWkstaUserGetInfo",
  276. NULL,
  277. status,
  278. NET_REMOTE_FLAG_NORMAL,
  279. SERVICE_WORKSTATION )
  280. //
  281. // No downlevel version to call
  282. //
  283. status = ERROR_NOT_SUPPORTED;
  284. NET_REMOTE_END
  285. return status;
  286. }
  287. NET_API_STATUS NET_API_FUNCTION
  288. NetWkstaUserSetInfo(
  289. IN LPTSTR reserved,
  290. IN DWORD level,
  291. OUT LPBYTE buf,
  292. OUT LPDWORD parm_err OPTIONAL
  293. )
  294. /*++
  295. Routine Description:
  296. This is the DLL entrypoint for NetWkstaUserSetInfo.
  297. Arguments:
  298. reserved - Must be NULL.
  299. level - Supplies the level of information.
  300. buf - Supplies a buffer which contains the information structure of fields
  301. to set. The level denotes the structure in this buffer.
  302. parm_err - Returns the identifier to the invalid parameter in buf if this
  303. function returns ERROR_INVALID_PARAMETER.
  304. Return Value:
  305. NET_API_STATUS - NERR_Success or reason for failure.
  306. --*/
  307. {
  308. NET_API_STATUS status;
  309. if (reserved != NULL) {
  310. return ERROR_INVALID_PARAMETER;
  311. }
  312. NET_REMOTE_TRY_RPC
  313. //
  314. // Try RPC (local only) version of API.
  315. //
  316. status = NetrWkstaUserSetInfo(
  317. NULL,
  318. level,
  319. (LPWKSTA_USER_INFO) &buf,
  320. parm_err
  321. );
  322. NET_REMOTE_RPC_FAILED("NetWkstaUserSetInfo",
  323. NULL,
  324. status,
  325. NET_REMOTE_FLAG_NORMAL,
  326. SERVICE_WORKSTATION )
  327. //
  328. // No downlevel version to call
  329. //
  330. status = ERROR_NOT_SUPPORTED;
  331. NET_REMOTE_END
  332. return status;
  333. }
  334. NET_API_STATUS NET_API_FUNCTION
  335. NetWkstaTransportEnum(
  336. IN LPTSTR servername OPTIONAL,
  337. IN DWORD level,
  338. OUT LPBYTE *bufptr,
  339. IN DWORD prefmaxlen,
  340. OUT LPDWORD entriesread,
  341. OUT LPDWORD totalentries,
  342. IN OUT LPDWORD resume_handle OPTIONAL
  343. )
  344. /*++
  345. Routine Description:
  346. This is the DLL entrypoint for NetWkstaTransportEnum.
  347. Arguments:
  348. servername - Supplies the name of server to execute this function
  349. level - Supplies the requested level of information.
  350. bufptr - Returns a pointer to the buffer which contains a sequence of
  351. information structure of the specified information level. This
  352. pointer is set to NULL if return code is not NERR_Success or
  353. ERROR_MORE_DATA, or if EntriesRead returned is 0.
  354. prefmaxlen - Supplies the number of bytes of information to return in the
  355. buffer. If this value is MAXULONG, all available information will
  356. be returned.
  357. entriesread - Returns the number of entries read into the buffer. This
  358. value is only valid if the return code is NERR_Success or
  359. ERROR_MORE_DATA.
  360. totalentries - Returns the total number of entries available. This value
  361. is only valid if the return code is NERR_Success or ERROR_MORE_DATA.
  362. resume_handle - Supplies a handle to resume the enumeration from where it
  363. left off the last time through. Returns the resume handle if return
  364. code is ERROR_MORE_DATA.
  365. Return Value:
  366. NET_API_STATUS - NERR_Success or reason for failure.
  367. --*/
  368. {
  369. NET_API_STATUS status;
  370. GENERIC_INFO_CONTAINER GenericInfoContainer;
  371. GENERIC_ENUM_STRUCT InfoStruct;
  372. if (bufptr == NULL || entriesread == NULL) {
  373. return ERROR_INVALID_PARAMETER;
  374. }
  375. try {
  376. *entriesread = 0;
  377. } except( EXCEPTION_EXECUTE_HANDLER ) {
  378. return ERROR_INVALID_PARAMETER;
  379. }
  380. GenericInfoContainer.Buffer = NULL;
  381. GenericInfoContainer.EntriesRead = 0;
  382. InfoStruct.Container = &GenericInfoContainer;
  383. InfoStruct.Level = level;
  384. NET_REMOTE_TRY_RPC
  385. //
  386. // Try RPC (local or remote) version of API.
  387. //
  388. status = NetrWkstaTransportEnum(
  389. servername,
  390. (LPWKSTA_TRANSPORT_ENUM_STRUCT) &InfoStruct,
  391. prefmaxlen,
  392. totalentries,
  393. resume_handle
  394. );
  395. if (status == NERR_Success || status == ERROR_MORE_DATA) {
  396. *bufptr = (LPBYTE) GenericInfoContainer.Buffer;
  397. *entriesread = GenericInfoContainer.EntriesRead;
  398. }
  399. NET_REMOTE_RPC_FAILED("NetWkstaTransportEnum",
  400. servername,
  401. status,
  402. NET_REMOTE_FLAG_NORMAL,
  403. SERVICE_WORKSTATION )
  404. //
  405. // No downlevel version to call
  406. //
  407. status = ERROR_NOT_SUPPORTED;
  408. NET_REMOTE_END
  409. return status;
  410. }
  411. NET_API_STATUS NET_API_FUNCTION
  412. NetWkstaTransportAdd(
  413. IN LPTSTR servername OPTIONAL,
  414. IN DWORD level,
  415. IN LPBYTE buf,
  416. OUT LPDWORD parm_err OPTIONAL
  417. )
  418. /*++
  419. Routine Description:
  420. This is the DLL entrypoint for NetWkstaTransportAdd.
  421. Arguments:
  422. servername - Supplies the name of server to execute this function
  423. level - Supplies the level of information.
  424. buf - Supplies a buffer which contains the information of transport to add.
  425. parm_err - Returns the identifier to the invalid parameter in buf if this
  426. function returns ERROR_INVALID_PARAMETER.
  427. Return Value:
  428. NET_API_STATUS - NERR_Success or reason for failure.
  429. --*/
  430. {
  431. NET_API_STATUS status;
  432. NET_REMOTE_TRY_RPC
  433. //
  434. // Try RPC (local or remote) version of API.
  435. //
  436. status = NetrWkstaTransportAdd(
  437. servername,
  438. level,
  439. (LPWKSTA_TRANSPORT_INFO_0) buf,
  440. parm_err
  441. );
  442. NET_REMOTE_RPC_FAILED("NetWkstaTransportAdd",
  443. servername,
  444. status,
  445. NET_REMOTE_FLAG_NORMAL,
  446. SERVICE_WORKSTATION )
  447. //
  448. // No downlevel version to call
  449. //
  450. status = ERROR_NOT_SUPPORTED;
  451. NET_REMOTE_END
  452. return status;
  453. }
  454. NET_API_STATUS NET_API_FUNCTION
  455. NetWkstaTransportDel(
  456. IN LPTSTR servername OPTIONAL,
  457. IN LPTSTR transportname,
  458. IN DWORD ucond
  459. )
  460. /*++
  461. Routine Description:
  462. This is the DLL entrypoint for NetWkstaTransportDel.
  463. Arguments:
  464. servername - Supplies the name of server to execute this function
  465. transportname - Supplies the name of the transport to delete.
  466. ucond - Supplies a value which specifies the force level of disconnection
  467. for existing use on the transport.
  468. Return Value:
  469. NET_API_STATUS - NERR_Success or reason for failure.
  470. --*/
  471. {
  472. NET_API_STATUS status;
  473. NET_REMOTE_TRY_RPC
  474. //
  475. // Try RPC (local or remote) version of API.
  476. //
  477. status = NetrWkstaTransportDel(
  478. servername,
  479. transportname,
  480. ucond
  481. );
  482. NET_REMOTE_RPC_FAILED("NetWkstaTransportDel",
  483. servername,
  484. status,
  485. NET_REMOTE_FLAG_NORMAL,
  486. SERVICE_WORKSTATION )
  487. //
  488. // No downlevel version to try
  489. //
  490. status = ERROR_NOT_SUPPORTED;
  491. NET_REMOTE_END
  492. return status;
  493. }
  494. NET_API_STATUS NET_API_FUNCTION
  495. NetUseAdd(
  496. IN LPTSTR servername OPTIONAL,
  497. IN DWORD level,
  498. IN LPBYTE buf,
  499. OUT LPDWORD parm_err OPTIONAL
  500. )
  501. /*++
  502. Routine Description:
  503. This is the DLL entrypoint for NetUseAdd.
  504. Arguments:
  505. servername - Supplies the name of server to execute this function
  506. level - Supplies the requested level of information.
  507. buf - Supplies a buffer which contains the information of use to add.
  508. parm_err - Returns the identifier to the invalid parameter in buf if this
  509. function returns ERROR_INVALID_PARAMETER.
  510. Return Value:
  511. NET_API_STATUS - NERR_Success or reason for failure.
  512. --*/
  513. {
  514. NET_API_STATUS status;
  515. LPWSTR lpwTempPassword = NULL;
  516. UNICODE_STRING EncodedPassword;
  517. #define NETR_USE_ADD_PASSWORD_SEED 0x56 // Pick a non-zero seed.
  518. DWORD OptionsSupported;
  519. status = NetRemoteComputerSupports(
  520. servername,
  521. SUPPORTS_RPC | SUPPORTS_LOCAL, // options wanted
  522. &OptionsSupported
  523. );
  524. if (status != NERR_Success) {
  525. //
  526. // This is where machine not found gets handled.
  527. //
  528. return status;
  529. }
  530. if (OptionsSupported & SUPPORTS_LOCAL) {
  531. //
  532. // Local case
  533. //
  534. RtlInitUnicodeString( &EncodedPassword, NULL );
  535. RpcTryExcept {
  536. //
  537. // Obfuscate the password so it won't end up in the pagefile
  538. //
  539. if ( level >= 1 ) {
  540. if ( ((PUSE_INFO_1)buf)->ui1_password != NULL ) {
  541. UCHAR Seed = NETR_USE_ADD_PASSWORD_SEED;
  542. // create a local copy of the password
  543. lpwTempPassword = ((PUSE_INFO_1)buf)->ui1_password;
  544. ((PUSE_INFO_1)buf)->ui1_password = (LPWSTR)LocalAlloc(LMEM_FIXED,(wcslen(lpwTempPassword)+1) * sizeof(WCHAR));
  545. if (((PUSE_INFO_1)buf)->ui1_password == NULL) {
  546. ((PUSE_INFO_1)buf)->ui1_password = lpwTempPassword;
  547. return ERROR_NOT_ENOUGH_MEMORY;
  548. }
  549. wcscpy(((PUSE_INFO_1)buf)->ui1_password,lpwTempPassword);
  550. RtlInitUnicodeString( &EncodedPassword,
  551. ((PUSE_INFO_1)buf)->ui1_password );
  552. RtlRunEncodeUnicodeString( &Seed, &EncodedPassword );
  553. }
  554. }
  555. status = NetrUseAdd(
  556. NULL,
  557. level,
  558. (LPUSE_INFO) &buf,
  559. parm_err
  560. );
  561. }
  562. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  563. status = WsMapRpcError(RpcExceptionCode());
  564. }
  565. RpcEndExcept
  566. //
  567. // Put the password back the way we found it.
  568. //
  569. if(lpwTempPassword != NULL) {
  570. LocalFree(((PUSE_INFO_1)buf)->ui1_password);
  571. ((PUSE_INFO_1)buf)->ui1_password = lpwTempPassword;
  572. }
  573. }
  574. else {
  575. //
  576. // Remote servername specified. Only allow remoting to downlevel.
  577. //
  578. if (OptionsSupported & SUPPORTS_RPC) {
  579. status = ERROR_NOT_SUPPORTED;
  580. }
  581. else {
  582. //
  583. // Call downlevel version of the API.
  584. //
  585. status = RxNetUseAdd(
  586. servername,
  587. level,
  588. buf,
  589. parm_err
  590. );
  591. }
  592. }
  593. return status;
  594. }
  595. NET_API_STATUS NET_API_FUNCTION
  596. NetUseDel(
  597. IN LPTSTR servername OPTIONAL,
  598. IN LPTSTR usename,
  599. IN DWORD ucond
  600. )
  601. /*++
  602. Routine Description:
  603. This is the DLL entrypoint for NetUseDel.
  604. Arguments:
  605. servername - Supplies the name of server to execute this function
  606. transportname - Supplies the name of the transport to delete.
  607. ucond - Supplies a value which specifies the force level of disconnection
  608. for the use.
  609. Return Value:
  610. NET_API_STATUS - NERR_Success or reason for failure.
  611. --*/
  612. {
  613. NET_API_STATUS status;
  614. DWORD OptionsSupported;
  615. status = NetRemoteComputerSupports(
  616. servername,
  617. SUPPORTS_RPC | SUPPORTS_LOCAL, // options wanted
  618. &OptionsSupported
  619. );
  620. if (status != NERR_Success) {
  621. //
  622. // This is where machine not found gets handled.
  623. //
  624. return status;
  625. }
  626. if (OptionsSupported & SUPPORTS_LOCAL) {
  627. //
  628. // Local case
  629. //
  630. RpcTryExcept {
  631. status = NetrUseDel(
  632. NULL,
  633. usename,
  634. ucond
  635. );
  636. }
  637. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  638. status = WsMapRpcError(RpcExceptionCode());
  639. }
  640. RpcEndExcept
  641. }
  642. else {
  643. //
  644. // Remote servername specified. Only allow remoting to downlevel.
  645. //
  646. if (OptionsSupported & SUPPORTS_RPC) {
  647. status = ERROR_NOT_SUPPORTED;
  648. }
  649. else {
  650. //
  651. // Call downlevel version of the API.
  652. //
  653. status = RxNetUseDel(
  654. servername,
  655. usename,
  656. ucond
  657. );
  658. }
  659. }
  660. return status;
  661. }
  662. NET_API_STATUS NET_API_FUNCTION
  663. NetUseGetInfo(
  664. IN LPTSTR servername OPTIONAL,
  665. IN LPTSTR usename,
  666. IN DWORD level,
  667. OUT LPBYTE *bufptr
  668. )
  669. /*++
  670. Routine Description:
  671. This is the DLL entrypoint for NetUseGetInfo.
  672. Arguments:
  673. servername - Supplies the name of server to execute this function
  674. level - Supplies the requested level of information.
  675. bufptr - Returns a pointer to a buffer which contains the requested
  676. use information.
  677. Return Value:
  678. NET_API_STATUS - NERR_Success or reason for failure.
  679. --*/
  680. {
  681. NET_API_STATUS status;
  682. DWORD OptionsSupported;
  683. if (bufptr == NULL) {
  684. return ERROR_INVALID_PARAMETER;
  685. }
  686. *bufptr = NULL; // Must be NULL so RPC knows to fill it in.
  687. status = NetRemoteComputerSupports(
  688. servername,
  689. SUPPORTS_RPC | SUPPORTS_LOCAL, // options wanted
  690. &OptionsSupported
  691. );
  692. if (status != NERR_Success) {
  693. //
  694. // This is where machine not found gets handled.
  695. //
  696. return status;
  697. }
  698. if (OptionsSupported & SUPPORTS_LOCAL) {
  699. //
  700. // Local case
  701. //
  702. RpcTryExcept {
  703. status = NetrUseGetInfo(
  704. NULL,
  705. usename,
  706. level,
  707. (LPUSE_INFO) bufptr
  708. );
  709. }
  710. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  711. status = WsMapRpcError(RpcExceptionCode());
  712. }
  713. RpcEndExcept
  714. }
  715. else {
  716. //
  717. // Remote servername specified. Only allow remoting to downlevel.
  718. //
  719. if (OptionsSupported & SUPPORTS_RPC) {
  720. status = ERROR_NOT_SUPPORTED;
  721. }
  722. else {
  723. //
  724. // Call downlevel version of the API.
  725. //
  726. status = RxNetUseGetInfo(
  727. servername,
  728. usename,
  729. level,
  730. bufptr
  731. );
  732. }
  733. }
  734. return status;
  735. }
  736. NET_API_STATUS NET_API_FUNCTION
  737. NetUseEnum(
  738. IN LPTSTR servername OPTIONAL,
  739. IN DWORD level,
  740. OUT LPBYTE *bufptr,
  741. IN DWORD prefmaxlen,
  742. OUT LPDWORD entriesread,
  743. OUT LPDWORD totalentries,
  744. IN OUT LPDWORD resume_handle OPTIONAL
  745. )
  746. /*++
  747. Routine Description:
  748. This is the DLL entrypoint for NetUseEnum.
  749. Arguments:
  750. servername - Supplies the name of server to execute this function
  751. level - Supplies the requested level of information.
  752. bufptr - Returns a pointer to the buffer which contains a sequence of
  753. information structure of the specified information level. This
  754. pointer is set to NULL if return code is not NERR_Success or
  755. ERROR_MORE_DATA, or if EntriesRead returned is 0.
  756. prefmaxlen - Supplies the number of bytes of information to return in the
  757. buffer. If this value is MAXULONG, all available information will
  758. be returned.
  759. entriesread - Returns the number of entries read into the buffer. This
  760. value is only valid if the return code is NERR_Success or
  761. ERROR_MORE_DATA.
  762. totalentries - Returns the total number of entries available. This value
  763. is only valid if the return code is NERR_Success or ERROR_MORE_DATA.
  764. resume_handle - Supplies a handle to resume the enumeration from where it
  765. left off the last time through. Returns the resume handle if return
  766. code is ERROR_MORE_DATA.
  767. Return Value:
  768. NET_API_STATUS - NERR_Success or reason for failure.
  769. --*/
  770. {
  771. NET_API_STATUS status;
  772. GENERIC_INFO_CONTAINER GenericInfoContainer;
  773. GENERIC_ENUM_STRUCT InfoStruct;
  774. DWORD OptionsSupported;
  775. if (bufptr == NULL || entriesread == NULL) {
  776. return ERROR_INVALID_PARAMETER;
  777. }
  778. try {
  779. *entriesread = 0;
  780. } except( EXCEPTION_EXECUTE_HANDLER ) {
  781. return ERROR_INVALID_PARAMETER;
  782. }
  783. GenericInfoContainer.Buffer = NULL;
  784. GenericInfoContainer.EntriesRead = 0;
  785. InfoStruct.Container = &GenericInfoContainer;
  786. InfoStruct.Level = level;
  787. status = NetRemoteComputerSupports(
  788. servername,
  789. SUPPORTS_RPC | SUPPORTS_LOCAL, // options wanted
  790. &OptionsSupported
  791. );
  792. if (status != NERR_Success) {
  793. //
  794. // This is where machine not found gets handled.
  795. //
  796. return status;
  797. }
  798. if (OptionsSupported & SUPPORTS_LOCAL) {
  799. //
  800. // Local case
  801. //
  802. RpcTryExcept {
  803. status = NetrUseEnum(
  804. NULL,
  805. (LPUSE_ENUM_STRUCT) &InfoStruct,
  806. prefmaxlen,
  807. totalentries,
  808. resume_handle
  809. );
  810. if (status == NERR_Success || status == ERROR_MORE_DATA) {
  811. *bufptr = (LPBYTE) GenericInfoContainer.Buffer;
  812. *entriesread = GenericInfoContainer.EntriesRead;
  813. }
  814. }
  815. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  816. status = WsMapRpcError(RpcExceptionCode());
  817. }
  818. RpcEndExcept
  819. }
  820. else {
  821. //
  822. // Remote servername specified. Only allow remoting to downlevel.
  823. //
  824. if (OptionsSupported & SUPPORTS_RPC) {
  825. status = ERROR_NOT_SUPPORTED;
  826. }
  827. else {
  828. //
  829. // Call downlevel version of the API.
  830. //
  831. status = RxNetUseEnum(
  832. servername,
  833. level,
  834. bufptr,
  835. prefmaxlen,
  836. entriesread,
  837. totalentries,
  838. resume_handle
  839. );
  840. }
  841. }
  842. return status;
  843. }
  844. NET_API_STATUS NET_API_FUNCTION
  845. NetMessageBufferSend (
  846. IN LPCWSTR servername OPTIONAL,
  847. IN LPCWSTR msgname,
  848. IN LPCWSTR fromname,
  849. IN LPBYTE buf,
  850. IN DWORD buflen
  851. )
  852. /*++
  853. Routine Description:
  854. This is the DLL entrypoint for NetMessageBufferSend.
  855. Arguments:
  856. servername - Supplies the name of server to execute this function
  857. Return Value:
  858. NET_API_STATUS - NERR_Success or reason for failure.
  859. --*/
  860. {
  861. #define MAX_MESSAGE_SIZE 1792
  862. NET_API_STATUS status;
  863. //
  864. // Truncate messages greater than (2K - 1/8th) = 1792 due to the 2K LPC
  865. // port data size max. The messenger server receiving this message uses
  866. // the MessageBox() api with the MB_SERVICE_NOTIFICATION flag to display
  867. // this message. The MB_SERVICE_NOTIFICATION flag instructs MessageBox()
  868. // to piggyback the hard error mechanism to get the UI on the console;
  869. // otherwise the UI would never be seen. This is where the LPC port data
  870. // size limitation comes into play.
  871. //
  872. // Why subtract an 1/8th from 2K? The messenger server prepends a string
  873. // to the message (e.g., "Message from Joe to Linda on 3/7/96 12:04PM").
  874. // In English, this string is 67 characters max (max user/computer name
  875. // is 15 chars).
  876. // 67 * 1.5 (other languages) * 2 (sizeof(WCHAR)) = 201 bytes.
  877. // An 1/8th of 2K is 256.
  878. //
  879. if (buflen > MAX_MESSAGE_SIZE) {
  880. buf[MAX_MESSAGE_SIZE - 2] = '\0';
  881. buf[MAX_MESSAGE_SIZE - 1] = '\0';
  882. buflen = MAX_MESSAGE_SIZE;
  883. }
  884. NET_REMOTE_TRY_RPC
  885. //
  886. // Try RPC (local or remote) version of API.
  887. //
  888. status = NetrMessageBufferSend(
  889. (LPWSTR)servername,
  890. (LPWSTR)msgname,
  891. (LPWSTR)fromname,
  892. buf,
  893. buflen
  894. );
  895. NET_REMOTE_RPC_FAILED("NetMessageBufferSend",
  896. (LPWSTR)servername,
  897. status,
  898. NET_REMOTE_FLAG_NORMAL,
  899. SERVICE_WORKSTATION )
  900. //
  901. // Call downlevel version of the API.
  902. //
  903. status = ERROR_NOT_SUPPORTED;
  904. NET_REMOTE_END
  905. return status;
  906. }
  907. NET_API_STATUS NET_API_FUNCTION
  908. I_NetLogonDomainNameAdd(
  909. IN LPTSTR logondomain
  910. )
  911. /*++
  912. Routine Description:
  913. This is the DLL entrypoint for the internal API I_NetLogonDomainNameAdd.
  914. Arguments:
  915. logondomain - Supplies the name of the logon domain to add to the Browser.
  916. Return Value:
  917. NET_API_STATUS - NERR_Success or reason for failure.
  918. --*/
  919. {
  920. NET_API_STATUS status;
  921. NET_REMOTE_TRY_RPC
  922. //
  923. // Try RPC (local only) version of API.
  924. //
  925. status = I_NetrLogonDomainNameAdd(
  926. logondomain
  927. );
  928. NET_REMOTE_RPC_FAILED(
  929. "I_NetLogonDomainNameAdd",
  930. NULL,
  931. status,
  932. NET_REMOTE_FLAG_NORMAL,
  933. SERVICE_WORKSTATION
  934. )
  935. //
  936. // No downlevel version to try
  937. //
  938. status = ERROR_NOT_SUPPORTED;
  939. NET_REMOTE_END
  940. return status;
  941. }
  942. NET_API_STATUS NET_API_FUNCTION
  943. I_NetLogonDomainNameDel(
  944. IN LPTSTR logondomain
  945. )
  946. /*++
  947. Routine Description:
  948. This is the DLL entrypoint for the internal API I_NetLogonDomainNameDel.
  949. Arguments:
  950. logondomain - Supplies the name of the logon domain to delete from the
  951. Browser.
  952. Return Value:
  953. NET_API_STATUS - NERR_Success or reason for failure.
  954. --*/
  955. {
  956. NET_API_STATUS status;
  957. NET_REMOTE_TRY_RPC
  958. //
  959. // Try RPC (local only) version of API.
  960. //
  961. status = I_NetrLogonDomainNameDel(
  962. logondomain
  963. );
  964. NET_REMOTE_RPC_FAILED(
  965. "I_NetLogonDomainNameDel",
  966. NULL,
  967. status,
  968. NET_REMOTE_FLAG_NORMAL,
  969. SERVICE_WORKSTATION
  970. )
  971. //
  972. // No downlevel version to try
  973. //
  974. status = ERROR_NOT_SUPPORTED;
  975. NET_REMOTE_END
  976. return status;
  977. }
  978. NET_API_STATUS
  979. NetWkstaStatisticsGet(
  980. IN LPTSTR ServerName,
  981. IN DWORD Level,
  982. IN DWORD Options,
  983. OUT LPBYTE* Buffer
  984. )
  985. /*++
  986. Routine Description:
  987. Wrapper for workstation statistics retrieval routine - either calls the
  988. client-side RPC function or calls RxNetStatisticsGet to retrieve the
  989. statistics from a down-level workstation service
  990. Arguments:
  991. ServerName - where to remote this function
  992. Level - of information required (MBZ)
  993. Options - flags. Currently MBZ
  994. Buffer - pointer to pointer to returned buffer
  995. Return Value:
  996. NET_API_STATUS
  997. Success - NERR_Success
  998. Failure - ERROR_INVALID_LEVEL
  999. Level not 0
  1000. ERROR_INVALID_PARAMETER
  1001. Unsupported options requested
  1002. ERROR_NOT_SUPPORTED
  1003. Service is not SERVER or WORKSTATION
  1004. ERROR_ACCESS_DENIED
  1005. Caller doesn't have necessary access rights for request
  1006. --*/
  1007. {
  1008. NET_API_STATUS status;
  1009. if (Buffer == NULL) {
  1010. return ERROR_INVALID_PARAMETER;
  1011. }
  1012. //
  1013. // set the caller's buffer pointer to known value. This will kill the
  1014. // calling app if it gave us a bad pointer and didn't use try...except
  1015. //
  1016. *Buffer = NULL;
  1017. //
  1018. // validate parms
  1019. //
  1020. if (Level) {
  1021. return ERROR_INVALID_LEVEL;
  1022. }
  1023. //
  1024. // we don't even allow clearing of stats any more
  1025. //
  1026. if (Options) {
  1027. return ERROR_INVALID_PARAMETER;
  1028. }
  1029. //
  1030. // NTRAID-70679-2/6/2000 davey remove redundant service name parameter
  1031. //
  1032. NET_REMOTE_TRY_RPC
  1033. status = NetrWorkstationStatisticsGet(ServerName,
  1034. SERVICE_WORKSTATION,
  1035. Level,
  1036. Options,
  1037. (LPSTAT_WORKSTATION_0*)Buffer
  1038. );
  1039. NET_REMOTE_RPC_FAILED("NetrWorkstationStatisticsGet",
  1040. ServerName,
  1041. status,
  1042. NET_REMOTE_FLAG_NORMAL,
  1043. SERVICE_WORKSTATION
  1044. )
  1045. status = RxNetStatisticsGet(ServerName,
  1046. SERVICE_LM20_WORKSTATION,
  1047. Level,
  1048. Options,
  1049. Buffer
  1050. );
  1051. NET_REMOTE_END
  1052. return status;
  1053. }
  1054. STATIC
  1055. DWORD
  1056. WsMapRpcError(
  1057. IN DWORD RpcError
  1058. )
  1059. /*++
  1060. Routine Description:
  1061. This routine maps the RPC error into a more meaningful net
  1062. error for the caller.
  1063. Arguments:
  1064. RpcError - Supplies the exception error raised by RPC
  1065. Return Value:
  1066. Returns the mapped error.
  1067. --*/
  1068. {
  1069. switch (RpcError) {
  1070. case RPC_S_SERVER_UNAVAILABLE:
  1071. return NERR_WkstaNotStarted;
  1072. case RPC_X_NULL_REF_POINTER:
  1073. return ERROR_INVALID_PARAMETER;
  1074. case EXCEPTION_ACCESS_VIOLATION:
  1075. return ERROR_INVALID_ADDRESS;
  1076. default:
  1077. return RpcError;
  1078. }
  1079. }
  1080. NET_API_STATUS
  1081. NetpEncodeJoinPassword(
  1082. IN LPWSTR lpPassword,
  1083. OUT LPWSTR *EncodedPassword
  1084. )
  1085. {
  1086. NET_API_STATUS status = NERR_Success;
  1087. UNICODE_STRING EncodedPasswordU;
  1088. PWSTR PasswordPart;
  1089. ULONG PwdLen;
  1090. UCHAR Seed;
  1091. *EncodedPassword = NULL;
  1092. if ( lpPassword ) {
  1093. PwdLen = wcslen( ( LPWSTR )lpPassword ) * sizeof( WCHAR );
  1094. PwdLen += sizeof( WCHAR ) + sizeof( WCHAR );
  1095. status = NetApiBufferAllocate( PwdLen,
  1096. ( PVOID * )EncodedPassword );
  1097. if ( status == NERR_Success ) {
  1098. //
  1099. // We'll put the encode byte as the first character in the string
  1100. //
  1101. PasswordPart = ( *EncodedPassword ) + 1;
  1102. wcscpy( PasswordPart, ( LPWSTR )lpPassword );
  1103. RtlInitUnicodeString( &EncodedPasswordU, PasswordPart );
  1104. Seed = 0;
  1105. RtlRunEncodeUnicodeString( &Seed, &EncodedPasswordU );
  1106. *( PWCHAR )( *EncodedPassword ) = ( WCHAR )Seed;
  1107. }
  1108. }
  1109. return( status );
  1110. }
  1111. NTSTATUS
  1112. JoinpRandomFill(
  1113. IN ULONG BufferSize,
  1114. IN OUT PUCHAR Buffer
  1115. )
  1116. /*++
  1117. Routine Description:
  1118. This routine fills a buffer with random data.
  1119. Parameters:
  1120. BufferSize - Length of the input buffer, in bytes.
  1121. Buffer - Input buffer to be filled with random data.
  1122. Return Values:
  1123. Errors from NtQuerySystemTime()
  1124. --*/
  1125. {
  1126. ULONG Index;
  1127. LARGE_INTEGER Time;
  1128. ULONG Seed;
  1129. NTSTATUS NtStatus;
  1130. NtStatus = NtQuerySystemTime(&Time);
  1131. if (!NT_SUCCESS(NtStatus)) {
  1132. return(NtStatus);
  1133. }
  1134. Seed = Time.LowPart ^ Time.HighPart;
  1135. for (Index = 0 ; Index < BufferSize ; Index++ )
  1136. {
  1137. *Buffer++ = (UCHAR) (RtlRandom(&Seed) % 256);
  1138. }
  1139. return(STATUS_SUCCESS);
  1140. }
  1141. NET_API_STATUS
  1142. NetpEncryptJoinPasswordStart(
  1143. IN LPCWSTR ServerName OPTIONAL,
  1144. IN LPCWSTR lpPassword OPTIONAL,
  1145. OUT RPC_BINDING_HANDLE *RpcBindingHandle,
  1146. OUT HANDLE *RedirHandle,
  1147. OUT PJOINPR_ENCRYPTED_USER_PASSWORD *EncryptedUserPassword,
  1148. OUT LPWSTR *EncodedPassword
  1149. )
  1150. /*++
  1151. Routine Description:
  1152. This routine takes a cleartext unicode NT password from the user,
  1153. and encrypts it with the session key.
  1154. Parameters:
  1155. ServerName - UNC server name of the server to remote the API to
  1156. lpPassword - the cleartext unicode NT password.
  1157. RpcBindingHandle - RPC handle used for acquiring a session key.
  1158. RedirHandle - Returns a handle to the redir. Since RpcBindingHandles don't represent
  1159. and open connection to the server, we have to ensure the connection stays open
  1160. until the server side has a chance to get this same UserSessionKey. The only
  1161. way to do that is to keep the connect open.
  1162. Returns NULL if no handle is needed.
  1163. EncryptedUserPassword - receives the encrypted cleartext password.
  1164. If lpPassword is NULL, a NULL is returned.
  1165. EncodedPassword - receives an encode form of lpPassowrd.
  1166. This form can be passed around locally with impunity.
  1167. Return Values:
  1168. If this routine returns NO_ERROR, the returned data must be freed using
  1169. NetpEncryptJoinPasswordEnd.
  1170. --*/
  1171. {
  1172. NET_API_STATUS NetStatus;
  1173. NTSTATUS NtStatus;
  1174. USER_SESSION_KEY UserSessionKey;
  1175. RC4_KEYSTRUCT Rc4Key;
  1176. MD5_CTX Md5Context;
  1177. PJOINPR_USER_PASSWORD UserPassword = NULL;
  1178. ULONG PasswordSize;
  1179. //
  1180. // Initialization
  1181. //
  1182. *RpcBindingHandle = NULL;
  1183. *EncryptedUserPassword = NULL;
  1184. *RedirHandle = NULL;
  1185. *EncodedPassword = NULL;
  1186. //
  1187. // Get an RPC handle to the server.
  1188. //
  1189. NetStatus = NetpBindRpc (
  1190. (LPWSTR) ServerName,
  1191. WORKSTATION_INTERFACE_NAME,
  1192. TEXT("Security=Impersonation Dynamic False"),
  1193. RpcBindingHandle );
  1194. if ( NetStatus != NO_ERROR ) {
  1195. goto Cleanup;
  1196. }
  1197. //
  1198. // If no password was specified,
  1199. // just return.
  1200. //
  1201. if ( lpPassword == NULL ) {
  1202. NetStatus = NO_ERROR;
  1203. goto Cleanup;
  1204. }
  1205. //
  1206. // Sanity check the password length
  1207. //
  1208. try {
  1209. PasswordSize = wcslen( lpPassword ) * sizeof(WCHAR);
  1210. } except( EXCEPTION_EXECUTE_HANDLER ) {
  1211. NetStatus = ERROR_INVALID_PARAMETER;
  1212. goto Cleanup;
  1213. }
  1214. if ( PasswordSize > JOIN_MAX_PASSWORD_LENGTH * sizeof(WCHAR)) {
  1215. NetStatus = ERROR_PASSWORD_RESTRICTION;
  1216. goto Cleanup;
  1217. }
  1218. //
  1219. // Encode the password
  1220. //
  1221. NetStatus = NetpEncodeJoinPassword( (LPWSTR) lpPassword, EncodedPassword );
  1222. if ( NetStatus != NO_ERROR ) {
  1223. goto Cleanup;
  1224. }
  1225. //
  1226. // Allocate a buffer to encrypt and fill it in.
  1227. //
  1228. UserPassword = LocalAlloc( 0, sizeof(*UserPassword) );
  1229. if ( UserPassword == NULL ) {
  1230. NetStatus = ERROR_NOT_ENOUGH_MEMORY;
  1231. goto Cleanup;
  1232. }
  1233. //
  1234. // Copy the password into the tail end of the buffer.
  1235. //
  1236. RtlCopyMemory(
  1237. ((PCHAR) UserPassword->Buffer) +
  1238. (JOIN_MAX_PASSWORD_LENGTH * sizeof(WCHAR)) -
  1239. PasswordSize,
  1240. lpPassword,
  1241. PasswordSize );
  1242. UserPassword->Length = PasswordSize;
  1243. //
  1244. // Fill the front of the buffer with random data
  1245. //
  1246. NtStatus = JoinpRandomFill(
  1247. (JOIN_MAX_PASSWORD_LENGTH * sizeof(WCHAR)) -
  1248. PasswordSize,
  1249. (PUCHAR) UserPassword->Buffer );
  1250. if ( !NT_SUCCESS(NtStatus) ) {
  1251. NetStatus = NetpNtStatusToApiStatus( NtStatus );
  1252. goto Cleanup;
  1253. }
  1254. NtStatus = JoinpRandomFill(
  1255. JOIN_OBFUSCATOR_LENGTH,
  1256. (PUCHAR) UserPassword->Obfuscator );
  1257. if ( !NT_SUCCESS(NtStatus) ) {
  1258. NetStatus = NetpNtStatusToApiStatus( NtStatus );
  1259. goto Cleanup;
  1260. }
  1261. //
  1262. // Get the session key.
  1263. //
  1264. NtStatus = RtlGetUserSessionKeyClientBinding(
  1265. *RpcBindingHandle,
  1266. RedirHandle,
  1267. &UserSessionKey );
  1268. if ( !NT_SUCCESS(NtStatus) ) {
  1269. NetStatus = NetpNtStatusToApiStatus( NtStatus );
  1270. goto Cleanup;
  1271. }
  1272. //
  1273. // The UserSessionKey is the same for the life of the session. RC4'ing multiple
  1274. // strings with a single key is weak (if you crack one you've cracked them all).
  1275. // So compute a key that's unique for this particular encryption.
  1276. //
  1277. //
  1278. MD5Init(&Md5Context);
  1279. MD5Update( &Md5Context, (LPBYTE)&UserSessionKey, sizeof(UserSessionKey) );
  1280. MD5Update( &Md5Context, UserPassword->Obfuscator, sizeof(UserPassword->Obfuscator) );
  1281. MD5Final( &Md5Context );
  1282. rc4_key( &Rc4Key, MD5DIGESTLEN, Md5Context.digest );
  1283. //
  1284. // Encrypt it.
  1285. // Don't encrypt the obfuscator. The server needs that to compute the key.
  1286. //
  1287. rc4( &Rc4Key, sizeof(UserPassword->Buffer)+sizeof(UserPassword->Length), (LPBYTE) UserPassword->Buffer );
  1288. NetStatus = NO_ERROR;
  1289. Cleanup:
  1290. if ( NetStatus == NO_ERROR ) {
  1291. *EncryptedUserPassword = (PJOINPR_ENCRYPTED_USER_PASSWORD) UserPassword;
  1292. } else {
  1293. if ( UserPassword != NULL ) {
  1294. LocalFree( UserPassword );
  1295. }
  1296. if ( *RpcBindingHandle != NULL ) {
  1297. NetpUnbindRpc( *RpcBindingHandle );
  1298. *RpcBindingHandle = NULL;
  1299. }
  1300. if ( *RedirHandle != NULL ) {
  1301. NtClose( *RedirHandle );
  1302. *RedirHandle = NULL;
  1303. }
  1304. if ( *EncodedPassword != NULL ) {
  1305. NetApiBufferFree( *EncodedPassword );
  1306. *EncodedPassword = NULL;
  1307. }
  1308. }
  1309. return NetStatus;
  1310. }
  1311. VOID
  1312. NetpEncryptJoinPasswordEnd(
  1313. IN RPC_BINDING_HANDLE RpcBindingHandle,
  1314. IN HANDLE RedirHandle OPTIONAL,
  1315. IN PJOINPR_ENCRYPTED_USER_PASSWORD EncryptedUserPassword OPTIONAL,
  1316. IN LPWSTR EncodedPassword OPTIONAL
  1317. )
  1318. /*++
  1319. Routine Description:
  1320. This routine takes the variables returned by NetpEncryptJoinPasswordStart and
  1321. frees them.
  1322. Parameters:
  1323. RpcBindingHandle - RPC handle used for acquiring a session key.
  1324. RedirHandle - Handle to the redirector
  1325. EncryptedUserPassword - the encrypted cleartext password.
  1326. EncodedPassword - the encoded form of lpPassowrd.
  1327. Return Values:
  1328. --*/
  1329. {
  1330. NET_API_STATUS NetStatus;
  1331. NTSTATUS NtStatus;
  1332. USER_SESSION_KEY UserSessionKey;
  1333. RC4_KEYSTRUCT Rc4Key;
  1334. PJOINPR_USER_PASSWORD UserPassword = NULL;
  1335. ULONG PasswordSize;
  1336. //
  1337. // Free the RPC binding handle.
  1338. //
  1339. if ( RpcBindingHandle != NULL ) {
  1340. (VOID) NetpUnbindRpc ( RpcBindingHandle );
  1341. }
  1342. //
  1343. // Close the redir handle.
  1344. //
  1345. if ( RedirHandle != NULL ) {
  1346. NtClose( RedirHandle );
  1347. }
  1348. //
  1349. // Free the encrypted password.
  1350. //
  1351. if ( EncryptedUserPassword != NULL ) {
  1352. LocalFree( EncryptedUserPassword );
  1353. }
  1354. //
  1355. // Free the encoded password
  1356. //
  1357. if ( EncodedPassword != NULL ) {
  1358. NetApiBufferFree( EncodedPassword );
  1359. }
  1360. }
  1361. NET_API_STATUS
  1362. NET_API_FUNCTION
  1363. NetJoinDomain(
  1364. IN LPCWSTR lpServer OPTIONAL,
  1365. IN LPCWSTR lpDomain,
  1366. IN LPCWSTR lpMachineAccountOU OPTIONAL,
  1367. IN LPCWSTR lpAccount OPTIONAL,
  1368. IN LPCWSTR lpPassword OPTIONAL,
  1369. IN DWORD fJoinOptions
  1370. )
  1371. /*++
  1372. Routine Description:
  1373. Joins the machine to the domain.
  1374. Arguments:
  1375. lpServer -- Name of server on which to execute this function
  1376. lpDomain -- Domain to join
  1377. lpMachineAccountOU -- Optional name of the OU under which to create the machine account
  1378. lpAccount -- Account to use for join
  1379. lpPassword -- Password matching the account
  1380. fOptions -- Options to use when joining the domain
  1381. Returns:
  1382. NERR_Success -- Success
  1383. ERROR_NOT_SUPPORTED -- The specified server does not support this interface
  1384. --*/
  1385. {
  1386. NET_API_STATUS NetStatus, OldStatus;
  1387. PWSTR ComputerName = NULL;
  1388. BOOLEAN CallLocal = FALSE;
  1389. RPC_BINDING_HANDLE RpcBindingHandle;
  1390. HANDLE RedirHandle;
  1391. PJOINPR_ENCRYPTED_USER_PASSWORD EncryptedUserPassword;
  1392. LPWSTR EncodedPassword;
  1393. //
  1394. // Encrypt the password.
  1395. //
  1396. NetStatus = NetpEncryptJoinPasswordStart( lpServer,
  1397. lpPassword,
  1398. &RpcBindingHandle,
  1399. &RedirHandle,
  1400. &EncryptedUserPassword,
  1401. &EncodedPassword );
  1402. if ( NetStatus == NERR_Success ) {
  1403. NET_REMOTE_TRY_RPC
  1404. //
  1405. // Try RPC version of API.
  1406. //
  1407. NetStatus = NetrJoinDomain2( RpcBindingHandle,
  1408. ( LPWSTR )lpServer,
  1409. ( LPWSTR )lpDomain,
  1410. ( LPWSTR )lpMachineAccountOU,
  1411. ( LPWSTR )lpAccount,
  1412. EncryptedUserPassword,
  1413. fJoinOptions );
  1414. NET_REMOTE_RPC_FAILED(
  1415. "NetJoinDomain",
  1416. NULL,
  1417. NetStatus,
  1418. NET_REMOTE_FLAG_NORMAL,
  1419. SERVICE_WORKSTATION
  1420. )
  1421. //
  1422. // No downlevel version to try
  1423. //
  1424. NetStatus = ERROR_NOT_SUPPORTED;
  1425. NET_REMOTE_END
  1426. if ( NetStatus == NERR_WkstaNotStarted || NetStatus == ERROR_ACCESS_DENIED ) {
  1427. OldStatus = NetStatus;
  1428. if ( lpServer ) {
  1429. NetStatus = NetpGetComputerName( &ComputerName );
  1430. if ( NetStatus == NERR_Success ) {
  1431. if ( !_wcsicmp( lpServer, ComputerName ) ) {
  1432. CallLocal = TRUE;
  1433. }
  1434. NetApiBufferFree( ComputerName );
  1435. }
  1436. } else {
  1437. CallLocal = TRUE;
  1438. }
  1439. //
  1440. // Only call locally if we are joining a workgroup
  1441. //
  1442. if ( CallLocal && !FLAG_ON( fJoinOptions, NETSETUP_JOIN_DOMAIN ) ) {
  1443. NetStatus = NetpDoDomainJoin( ( LPWSTR )lpServer,
  1444. ( LPWSTR )lpDomain,
  1445. NULL,
  1446. ( LPWSTR )lpAccount,
  1447. ( LPWSTR )EncodedPassword,
  1448. fJoinOptions );
  1449. } else {
  1450. NetStatus = OldStatus;
  1451. }
  1452. }
  1453. NetpEncryptJoinPasswordEnd( RpcBindingHandle,
  1454. RedirHandle,
  1455. EncryptedUserPassword,
  1456. EncodedPassword );
  1457. }
  1458. return NetStatus;
  1459. }
  1460. NET_API_STATUS
  1461. NET_API_FUNCTION
  1462. NetUnjoinDomain(
  1463. IN LPCWSTR lpServer OPTIONAL,
  1464. IN LPCWSTR lpAccount OPTIONAL,
  1465. IN LPCWSTR lpPassword OPTIONAL,
  1466. IN DWORD fUnjoinOptions
  1467. )
  1468. /*++
  1469. Routine Description:
  1470. Unjoins from the joined domain
  1471. Arguments:
  1472. lpServer -- Name of server on which to execute this function
  1473. lpAccount -- Account to use for unjoining
  1474. lpPassword -- Password matching the account
  1475. fOptions -- Options to use when unjoining the domain
  1476. Returns:
  1477. NERR_Success -- Success
  1478. ERROR_NOT_SUPPORTED -- The specified server does not support this interface
  1479. --*/
  1480. {
  1481. NET_API_STATUS NetStatus;
  1482. RPC_BINDING_HANDLE RpcBindingHandle;
  1483. HANDLE RedirHandle;
  1484. PJOINPR_ENCRYPTED_USER_PASSWORD EncryptedUserPassword;
  1485. LPWSTR EncodedPassword;
  1486. //
  1487. // Encrypt the password.
  1488. //
  1489. NetStatus = NetpEncryptJoinPasswordStart( lpServer,
  1490. lpPassword,
  1491. &RpcBindingHandle,
  1492. &RedirHandle,
  1493. &EncryptedUserPassword,
  1494. &EncodedPassword );
  1495. if ( NetStatus == NERR_Success ) {
  1496. NET_REMOTE_TRY_RPC
  1497. //
  1498. // Try RPC version of API.
  1499. //
  1500. NetStatus = NetrUnjoinDomain2(
  1501. RpcBindingHandle,
  1502. ( LPWSTR )lpServer,
  1503. ( LPWSTR )lpAccount,
  1504. EncryptedUserPassword,
  1505. fUnjoinOptions );
  1506. NET_REMOTE_RPC_FAILED(
  1507. "NetUnjoinDomain",
  1508. NULL,
  1509. NetStatus,
  1510. NET_REMOTE_FLAG_NORMAL,
  1511. SERVICE_WORKSTATION
  1512. )
  1513. //
  1514. // No downlevel version to try
  1515. //
  1516. NetStatus = ERROR_NOT_SUPPORTED;
  1517. NET_REMOTE_END
  1518. NetpEncryptJoinPasswordEnd( RpcBindingHandle,
  1519. RedirHandle,
  1520. EncryptedUserPassword,
  1521. EncodedPassword );
  1522. }
  1523. return NetStatus;
  1524. }
  1525. NET_API_STATUS
  1526. NET_API_FUNCTION
  1527. NetRenameMachineInDomain(
  1528. IN LPCWSTR lpServer OPTIONAL,
  1529. IN LPCWSTR lpNewMachineName OPTIONAL,
  1530. IN LPCWSTR lpAccount OPTIONAL,
  1531. IN LPCWSTR lpPassword OPTIONAL,
  1532. IN DWORD fRenameOptions
  1533. )
  1534. /*++
  1535. Routine Description:
  1536. Renames a machine currently joined to a domain.
  1537. Arguments:
  1538. lpServer -- Name of server on which to execute this function
  1539. lpNewMachineName -- New name for this machine. If the name is specified, it is used
  1540. for the new machine name. If it is not specified, it is assumed that SetComputerName
  1541. has already been invoked, and that name will be used.
  1542. lpAccount -- Account to use for the rename
  1543. lpPassword -- Password matching the account
  1544. fOptions -- Options to use for the rename
  1545. Returns:
  1546. NERR_Success -- Success
  1547. ERROR_NOT_SUPPORTED -- The specified server does not support this interface
  1548. --*/
  1549. {
  1550. NET_API_STATUS NetStatus;
  1551. RPC_BINDING_HANDLE RpcBindingHandle;
  1552. HANDLE RedirHandle;
  1553. PJOINPR_ENCRYPTED_USER_PASSWORD EncryptedUserPassword;
  1554. LPWSTR EncodedPassword;
  1555. //
  1556. // Encrypt the password.
  1557. //
  1558. NetStatus = NetpEncryptJoinPasswordStart( lpServer,
  1559. lpPassword,
  1560. &RpcBindingHandle,
  1561. &RedirHandle,
  1562. &EncryptedUserPassword,
  1563. &EncodedPassword );
  1564. if ( NetStatus == NERR_Success ) {
  1565. NET_REMOTE_TRY_RPC
  1566. //
  1567. // Try RPC (local only) version of API.
  1568. //
  1569. NetStatus = NetrRenameMachineInDomain2(
  1570. RpcBindingHandle,
  1571. ( LPWSTR )lpServer,
  1572. ( LPWSTR )lpNewMachineName,
  1573. ( LPWSTR )lpAccount,
  1574. EncryptedUserPassword,
  1575. fRenameOptions );
  1576. NET_REMOTE_RPC_FAILED(
  1577. "NetRenameMachineInDomain",
  1578. NULL,
  1579. NetStatus,
  1580. NET_REMOTE_FLAG_NORMAL,
  1581. SERVICE_WORKSTATION
  1582. )
  1583. //
  1584. // No downlevel version to try
  1585. //
  1586. NetStatus = ERROR_NOT_SUPPORTED;
  1587. NET_REMOTE_END
  1588. NetpEncryptJoinPasswordEnd( RpcBindingHandle,
  1589. RedirHandle,
  1590. EncryptedUserPassword,
  1591. EncodedPassword );
  1592. }
  1593. return NetStatus;
  1594. }
  1595. NET_API_STATUS
  1596. NET_API_FUNCTION
  1597. NetValidateName(
  1598. IN LPCWSTR lpServer OPTIONAL,
  1599. IN LPCWSTR lpName,
  1600. IN LPCWSTR lpAccount OPTIONAL,
  1601. IN LPCWSTR lpPassword OPTIONAL,
  1602. IN NETSETUP_NAME_TYPE NameType
  1603. )
  1604. /*++
  1605. Routine Description:
  1606. Ensures that the given name is valid for a name of that type
  1607. Arguments:
  1608. lpServer -- Name of server on which to execute this function
  1609. lpName -- Name to validate
  1610. lpAccount -- Account to use for validation
  1611. lpPassword -- Password matching the account
  1612. NameType -- Type of the name to validate
  1613. Returns:
  1614. NERR_Success -- Success
  1615. ERROR_NOT_SUPPORTED -- The specified server does not support this interface
  1616. --*/
  1617. {
  1618. NET_API_STATUS NetStatus, OldStatus;
  1619. PWSTR ComputerName = NULL;
  1620. BOOLEAN CallLocal = FALSE;
  1621. RPC_BINDING_HANDLE RpcBindingHandle;
  1622. HANDLE RedirHandle;
  1623. PJOINPR_ENCRYPTED_USER_PASSWORD EncryptedUserPassword;
  1624. LPWSTR EncodedPassword;
  1625. //
  1626. // Encrypt the password.
  1627. //
  1628. NetStatus = NetpEncryptJoinPasswordStart( lpServer,
  1629. lpPassword,
  1630. &RpcBindingHandle,
  1631. &RedirHandle,
  1632. &EncryptedUserPassword,
  1633. &EncodedPassword );
  1634. if ( NetStatus == NERR_Success ) {
  1635. NET_REMOTE_TRY_RPC
  1636. //
  1637. // Try RPC (local only) version of API.
  1638. //
  1639. NetStatus = NetrValidateName2( RpcBindingHandle,
  1640. ( LPWSTR )lpServer,
  1641. ( LPWSTR )lpName,
  1642. ( LPWSTR )lpAccount,
  1643. EncryptedUserPassword,
  1644. NameType );
  1645. NET_REMOTE_RPC_FAILED(
  1646. "NetValidateName",
  1647. NULL,
  1648. NetStatus,
  1649. NET_REMOTE_FLAG_NORMAL,
  1650. SERVICE_WORKSTATION
  1651. )
  1652. //
  1653. // No downlevel version to try
  1654. //
  1655. NetStatus = ERROR_NOT_SUPPORTED;
  1656. NET_REMOTE_END
  1657. if ( NetStatus == NERR_WkstaNotStarted ) {
  1658. OldStatus = NetStatus;
  1659. if ( lpServer ) {
  1660. NetStatus = NetpGetComputerName( &ComputerName );
  1661. if ( NetStatus == NERR_Success ) {
  1662. if ( !_wcsicmp( lpServer, ComputerName ) ) {
  1663. CallLocal = TRUE;
  1664. }
  1665. NetApiBufferFree( ComputerName );
  1666. }
  1667. } else {
  1668. CallLocal = TRUE;
  1669. }
  1670. if ( CallLocal ) {
  1671. NetStatus = NetpValidateName( ( LPWSTR )lpServer,
  1672. ( LPWSTR )lpName,
  1673. ( LPWSTR )lpAccount,
  1674. EncodedPassword,
  1675. NameType );
  1676. } else {
  1677. NetStatus = OldStatus;
  1678. }
  1679. }
  1680. NetpEncryptJoinPasswordEnd( RpcBindingHandle,
  1681. RedirHandle,
  1682. EncryptedUserPassword,
  1683. EncodedPassword );
  1684. }
  1685. return NetStatus;
  1686. }
  1687. NET_API_STATUS
  1688. NET_API_FUNCTION
  1689. NetGetJoinInformation(
  1690. IN LPCWSTR lpServer OPTIONAL,
  1691. OUT LPWSTR *lpNameBuffer,
  1692. OUT PNETSETUP_JOIN_STATUS BufferType
  1693. )
  1694. /*++
  1695. Routine Description:
  1696. Gets information on the state of the workstation. The information
  1697. obtainable is whether the machine is joined to a workgroup or a domain,
  1698. and optionally, the name of that workgroup/domain.
  1699. Arguments:
  1700. lpServer -- Name of server on which to execute this function
  1701. lpNameBuffer -- Where the domain/workgroup name is returned.
  1702. BufferType -- Whether the machine is joined to a workgroup or a domain
  1703. Returns:
  1704. NERR_Success -- Success
  1705. ERROR_NOT_SUPPORTED -- The specified server does not support this interface
  1706. ERROR_INVALID_PARAMETER -- An invalid buffer pointer was given
  1707. --*/
  1708. {
  1709. NET_API_STATUS status, OldStatus;
  1710. LPWSTR Name = NULL, ComputerName = NULL;
  1711. BOOLEAN CallLocal = FALSE;
  1712. if ( lpNameBuffer == NULL ) {
  1713. return( ERROR_INVALID_PARAMETER );
  1714. }
  1715. NET_REMOTE_TRY_RPC
  1716. //
  1717. // Try RPC (local only) version of API.
  1718. //
  1719. status = NetrGetJoinInformation( ( LPWSTR )lpServer,
  1720. &Name,
  1721. BufferType );
  1722. NET_REMOTE_RPC_FAILED(
  1723. "NetGetJoinInformation",
  1724. NULL,
  1725. status,
  1726. NET_REMOTE_FLAG_NORMAL,
  1727. SERVICE_WORKSTATION
  1728. )
  1729. //
  1730. // No downlevel version to try
  1731. //
  1732. status = ERROR_NOT_SUPPORTED;
  1733. NET_REMOTE_END
  1734. if ( status != NERR_Success ) {
  1735. OldStatus = status;
  1736. if ( lpServer ) {
  1737. if ( status == NERR_Success ) {
  1738. if ( !_wcsicmp( lpServer, ComputerName ) ) {
  1739. CallLocal = TRUE;
  1740. }
  1741. NetApiBufferFree( ComputerName );
  1742. }
  1743. } else {
  1744. CallLocal = TRUE;
  1745. }
  1746. if ( CallLocal ) {
  1747. status = NetpGetJoinInformation( ( LPWSTR )lpServer,
  1748. &Name,
  1749. BufferType );
  1750. } else {
  1751. status = OldStatus;
  1752. }
  1753. }
  1754. if ( status == NERR_Success ) {
  1755. *lpNameBuffer = Name;
  1756. }
  1757. return status;
  1758. }
  1759. NET_API_STATUS
  1760. NET_API_FUNCTION
  1761. NetGetJoinableOUs(
  1762. IN LPCWSTR lpServer OPTIONAL,
  1763. IN LPCWSTR lpDomain,
  1764. IN LPCWSTR lpAccount OPTIONAL,
  1765. IN LPCWSTR lpPassword OPTIONAL,
  1766. OUT DWORD *OUCount,
  1767. OUT LPWSTR **OUs
  1768. )
  1769. /*++
  1770. Routine Description:
  1771. This API is used to determine the list of OUs in which a machine account
  1772. can be created. This function is only valid against an NT5 or greater Dc.
  1773. Arguments:
  1774. lpServer -- Name of server on which to execute this function
  1775. lpDomain -- Domain to join
  1776. lpAccount -- Account to use for join
  1777. lpPassword -- Password matching the account
  1778. OUCount -- Where the number of joinable OU strings is returned
  1779. OUs -- Where the list of OU under which machine accounts can be created is returned
  1780. Returns:
  1781. NERR_Success -- Success
  1782. ERROR_NOT_SUPPORTED -- The specified server does not support this interface
  1783. ERROR_INVALID_PARAMETER -- An invalid buffer pointer was given
  1784. --*/
  1785. {
  1786. NET_API_STATUS NetStatus = NERR_Success;
  1787. ULONG Count = 0;
  1788. LPWSTR *OUList = NULL;
  1789. RPC_BINDING_HANDLE RpcBindingHandle;
  1790. HANDLE RedirHandle;
  1791. PJOINPR_ENCRYPTED_USER_PASSWORD EncryptedUserPassword;
  1792. LPWSTR EncodedPassword;
  1793. if ( OUCount == NULL || OUs == NULL ) {
  1794. return( ERROR_INVALID_PARAMETER );
  1795. }
  1796. //
  1797. // Encrypt the password.
  1798. //
  1799. NetStatus = NetpEncryptJoinPasswordStart( lpServer,
  1800. lpPassword,
  1801. &RpcBindingHandle,
  1802. &RedirHandle,
  1803. &EncryptedUserPassword,
  1804. &EncodedPassword );
  1805. if ( NetStatus == NERR_Success ) {
  1806. NET_REMOTE_TRY_RPC
  1807. //
  1808. // Try RPC (local only) version of API.
  1809. //
  1810. NetStatus = NetrGetJoinableOUs2(
  1811. RpcBindingHandle,
  1812. ( LPWSTR )lpServer,
  1813. ( LPWSTR )lpDomain,
  1814. ( LPWSTR )lpAccount,
  1815. EncryptedUserPassword,
  1816. &Count,
  1817. &OUList );
  1818. NET_REMOTE_RPC_FAILED(
  1819. "NetrGetJoinableOUs",
  1820. NULL,
  1821. NetStatus,
  1822. NET_REMOTE_FLAG_NORMAL,
  1823. SERVICE_WORKSTATION
  1824. )
  1825. //
  1826. // No downlevel version to try
  1827. //
  1828. NetStatus = ERROR_NOT_SUPPORTED;
  1829. NET_REMOTE_END
  1830. NetpEncryptJoinPasswordEnd( RpcBindingHandle,
  1831. RedirHandle,
  1832. EncryptedUserPassword,
  1833. EncodedPassword );
  1834. }
  1835. if ( NetStatus == NERR_Success ) {
  1836. *OUCount = Count;
  1837. *OUs = OUList;
  1838. }
  1839. return NetStatus;
  1840. }
  1841. NET_API_STATUS
  1842. NET_API_FUNCTION
  1843. NetAddAlternateComputerName(
  1844. IN LPCWSTR Server OPTIONAL,
  1845. IN LPCWSTR AlternateName,
  1846. IN LPCWSTR DomainAccount OPTIONAL,
  1847. IN LPCWSTR DomainAccountPassword OPTIONAL,
  1848. IN ULONG Reserved
  1849. )
  1850. /*++
  1851. Routine Description:
  1852. Adds an alternate name for the specified server.
  1853. Arguments:
  1854. Server -- Name of server on which to execute this function.
  1855. AlternateName -- The name to add.
  1856. DomainAccount -- Domain account to use for accessing the
  1857. machine account object for the specified server in the AD.
  1858. Not used if the server is not joined to a domain. May be
  1859. NULL in which case the credentials of the user executing
  1860. this routine are used.
  1861. DomainAccountPassword -- Password matching the domain account.
  1862. Not used if the server is not joined to a domain. May be
  1863. NULL in which case the credentials of the user executing
  1864. this routine are used.
  1865. Reserved -- Reserved for future use. If some flags are specified
  1866. that are not supported, they will be ignored if
  1867. NET_IGNORE_UNSUPPORTED_FLAGS is set, otherwise this routine
  1868. will fail with ERROR_INVALID_FLAGS.
  1869. Note:
  1870. The process that calls this routine must have administrator
  1871. privileges on the server computer.
  1872. Returns:
  1873. NO_ERROR -- Success
  1874. ERROR_NOT_SUPPORTED -- The specified server does not support this
  1875. functionality.
  1876. ERROR_INVALID_FLAGS - The Flags parameter is incorrect.
  1877. --*/
  1878. {
  1879. NET_API_STATUS NetStatus;
  1880. RPC_BINDING_HANDLE RpcBindingHandle;
  1881. HANDLE RedirHandle;
  1882. PJOINPR_ENCRYPTED_USER_PASSWORD EncryptedUserPassword;
  1883. LPWSTR EncodedPassword;
  1884. //
  1885. // Encrypt the password.
  1886. //
  1887. NetStatus = NetpEncryptJoinPasswordStart( Server,
  1888. DomainAccountPassword,
  1889. &RpcBindingHandle,
  1890. &RedirHandle,
  1891. &EncryptedUserPassword,
  1892. &EncodedPassword );
  1893. if ( NetStatus == NERR_Success ) {
  1894. NET_REMOTE_TRY_RPC
  1895. //
  1896. // Try RPC version of API.
  1897. //
  1898. NetStatus = NetrAddAlternateComputerName(
  1899. RpcBindingHandle,
  1900. (LPWSTR) Server,
  1901. (LPWSTR) AlternateName,
  1902. (LPWSTR) DomainAccount,
  1903. EncryptedUserPassword,
  1904. Reserved );
  1905. NET_REMOTE_RPC_FAILED(
  1906. "NetRenameMachineInDomain",
  1907. NULL,
  1908. NetStatus,
  1909. NET_REMOTE_FLAG_NORMAL,
  1910. SERVICE_WORKSTATION
  1911. )
  1912. //
  1913. // No downlevel version to try
  1914. //
  1915. NetStatus = ERROR_NOT_SUPPORTED;
  1916. NET_REMOTE_END
  1917. NetpEncryptJoinPasswordEnd( RpcBindingHandle,
  1918. RedirHandle,
  1919. EncryptedUserPassword,
  1920. EncodedPassword );
  1921. }
  1922. return NetStatus;
  1923. }
  1924. NET_API_STATUS
  1925. NET_API_FUNCTION
  1926. NetRemoveAlternateComputerName(
  1927. IN LPCWSTR Server OPTIONAL,
  1928. IN LPCWSTR AlternateName,
  1929. IN LPCWSTR DomainAccount OPTIONAL,
  1930. IN LPCWSTR DomainAccountPassword OPTIONAL,
  1931. IN ULONG Reserved
  1932. )
  1933. /*++
  1934. Routine Description:
  1935. Deletes an alternate name for the specified server.
  1936. Arguments:
  1937. Server -- Name of server on which to execute this function.
  1938. AlternateName -- The name to delete.
  1939. DomainAccount -- Domain account to use for accessing the
  1940. machine account object for the specified server in the AD.
  1941. Not used if the server is not joined to a domain. May be
  1942. NULL in which case the credentials of the user executing
  1943. this routine are used.
  1944. DomainAccountPassword -- Password matching the domain account.
  1945. Not used if the server is not joined to a domain. May be
  1946. NULL in which case the credentials of the user executing
  1947. this routine are used.
  1948. Reserved -- Reserved for future use. If some flags are specified
  1949. that are not supported, they will be ignored if
  1950. NET_IGNORE_UNSUPPORTED_FLAGS is set, otherwise this routine
  1951. will fail with ERROR_INVALID_FLAGS.
  1952. Note:
  1953. The process that calls this routine must have administrator
  1954. privileges on the server computer.
  1955. Returns:
  1956. NO_ERROR -- Success
  1957. ERROR_NOT_SUPPORTED -- The specified server does not support this
  1958. functionality.
  1959. ERROR_INVALID_FLAGS - The Flags parameter is incorrect.
  1960. --*/
  1961. {
  1962. NET_API_STATUS NetStatus;
  1963. RPC_BINDING_HANDLE RpcBindingHandle;
  1964. HANDLE RedirHandle;
  1965. PJOINPR_ENCRYPTED_USER_PASSWORD EncryptedUserPassword;
  1966. LPWSTR EncodedPassword;
  1967. //
  1968. // Encrypt the password.
  1969. //
  1970. NetStatus = NetpEncryptJoinPasswordStart( Server,
  1971. DomainAccountPassword,
  1972. &RpcBindingHandle,
  1973. &RedirHandle,
  1974. &EncryptedUserPassword,
  1975. &EncodedPassword );
  1976. if ( NetStatus == NERR_Success ) {
  1977. NET_REMOTE_TRY_RPC
  1978. //
  1979. // Try RPC version of API.
  1980. //
  1981. NetStatus = NetrRemoveAlternateComputerName(
  1982. RpcBindingHandle,
  1983. (LPWSTR) Server,
  1984. (LPWSTR) AlternateName,
  1985. (LPWSTR) DomainAccount,
  1986. EncryptedUserPassword,
  1987. Reserved );
  1988. NET_REMOTE_RPC_FAILED(
  1989. "NetRenameMachineInDomain",
  1990. NULL,
  1991. NetStatus,
  1992. NET_REMOTE_FLAG_NORMAL,
  1993. SERVICE_WORKSTATION
  1994. )
  1995. //
  1996. // No downlevel version to try
  1997. //
  1998. NetStatus = ERROR_NOT_SUPPORTED;
  1999. NET_REMOTE_END
  2000. NetpEncryptJoinPasswordEnd( RpcBindingHandle,
  2001. RedirHandle,
  2002. EncryptedUserPassword,
  2003. EncodedPassword );
  2004. }
  2005. return NetStatus;
  2006. }
  2007. NET_API_STATUS
  2008. NET_API_FUNCTION
  2009. NetSetPrimaryComputerName(
  2010. IN LPCWSTR Server OPTIONAL,
  2011. IN LPCWSTR PrimaryName,
  2012. IN LPCWSTR DomainAccount OPTIONAL,
  2013. IN LPCWSTR DomainAccountPassword OPTIONAL,
  2014. IN ULONG Reserved
  2015. )
  2016. /*++
  2017. Routine Description:
  2018. Sets the primary computer name for the specified server.
  2019. Arguments:
  2020. Server -- Name of server on which to execute this function.
  2021. PrimaryName -- The primary computer name to set.
  2022. DomainAccount -- Domain account to use for accessing the
  2023. machine account object for the specified server in the AD.
  2024. Not used if the server is not joined to a domain. May be
  2025. NULL in which case the credentials of the user executing
  2026. this routine are used.
  2027. DomainAccountPassword -- Password matching the domain account.
  2028. Not used if the server is not joined to a domain. May be
  2029. NULL in which case the credentials of the user executing
  2030. this routine are used.
  2031. Reserved -- Reserved for future use. If some flags are specified
  2032. that are not supported, they will be ignored if
  2033. NET_IGNORE_UNSUPPORTED_FLAGS is set, otherwise this routine
  2034. will fail with ERROR_INVALID_FLAGS.
  2035. Note:
  2036. The process that calls this routine must have administrator
  2037. privileges on the server computer.
  2038. Returns:
  2039. NO_ERROR -- Success
  2040. ERROR_NOT_SUPPORTED -- The specified server does not support this
  2041. functionality.
  2042. ERROR_INVALID_FLAGS - The Flags parameter is incorrect.
  2043. --*/
  2044. {
  2045. NET_API_STATUS NetStatus;
  2046. RPC_BINDING_HANDLE RpcBindingHandle;
  2047. HANDLE RedirHandle;
  2048. PJOINPR_ENCRYPTED_USER_PASSWORD EncryptedUserPassword;
  2049. LPWSTR EncodedPassword;
  2050. //
  2051. // Encrypt the password.
  2052. //
  2053. NetStatus = NetpEncryptJoinPasswordStart( Server,
  2054. DomainAccountPassword,
  2055. &RpcBindingHandle,
  2056. &RedirHandle,
  2057. &EncryptedUserPassword,
  2058. &EncodedPassword );
  2059. if ( NetStatus == NERR_Success ) {
  2060. NET_REMOTE_TRY_RPC
  2061. //
  2062. // Try RPC version of API.
  2063. //
  2064. NetStatus = NetrSetPrimaryComputerName(
  2065. RpcBindingHandle,
  2066. (LPWSTR) Server,
  2067. (LPWSTR) PrimaryName,
  2068. (LPWSTR) DomainAccount,
  2069. EncryptedUserPassword,
  2070. Reserved );
  2071. NET_REMOTE_RPC_FAILED(
  2072. "NetRenameMachineInDomain",
  2073. NULL,
  2074. NetStatus,
  2075. NET_REMOTE_FLAG_NORMAL,
  2076. SERVICE_WORKSTATION
  2077. )
  2078. //
  2079. // No downlevel version to try
  2080. //
  2081. NetStatus = ERROR_NOT_SUPPORTED;
  2082. NET_REMOTE_END
  2083. NetpEncryptJoinPasswordEnd( RpcBindingHandle,
  2084. RedirHandle,
  2085. EncryptedUserPassword,
  2086. EncodedPassword );
  2087. }
  2088. return NetStatus;
  2089. }
  2090. NET_API_STATUS
  2091. NET_API_FUNCTION
  2092. NetEnumerateComputerNames(
  2093. IN LPCWSTR Server OPTIONAL,
  2094. IN NET_COMPUTER_NAME_TYPE NameType,
  2095. IN ULONG Reserved,
  2096. OUT PDWORD EntryCount,
  2097. OUT LPWSTR **ComputerNames
  2098. )
  2099. /*++
  2100. Routine Description:
  2101. Enumerates computer names for the specified server.
  2102. Arguments:
  2103. Server -- Name of server on which to execute this function.
  2104. NameType -- The type of the name queried.
  2105. Reserved -- Reserved for future use. If some flags are specified
  2106. that are not supported, they will be ignored if
  2107. NET_IGNORE_UNSUPPORTED_FLAGS is set, otherwise this routine
  2108. will fail with ERROR_INVALID_FLAGS.
  2109. EntryCount -- Returns the number of names returned
  2110. ComputerNames -- An array of pointers to names. Must be freed by
  2111. calling NetApiBufferFree.
  2112. Returns:
  2113. NO_ERROR -- Success
  2114. ERROR_NOT_SUPPORTED -- The specified server does not support this
  2115. functionality.
  2116. ERROR_INVALID_FLAGS - The Flags parameter is incorrect.
  2117. --*/
  2118. {
  2119. NET_API_STATUS NetStatus = NO_ERROR;
  2120. PNET_COMPUTER_NAME_ARRAY ComputerNameArray = NULL;
  2121. NET_REMOTE_TRY_RPC
  2122. //
  2123. // Try RPC version of API.
  2124. //
  2125. NetStatus = NetrEnumerateComputerNames(
  2126. (LPWSTR) Server,
  2127. NameType,
  2128. Reserved,
  2129. &ComputerNameArray );
  2130. NET_REMOTE_RPC_FAILED(
  2131. "NetRenameMachineInDomain",
  2132. NULL,
  2133. NetStatus,
  2134. NET_REMOTE_FLAG_NORMAL,
  2135. SERVICE_WORKSTATION
  2136. )
  2137. //
  2138. // No downlevel version to try
  2139. //
  2140. NetStatus = ERROR_NOT_SUPPORTED;
  2141. NET_REMOTE_END
  2142. //
  2143. // Convert the computer names to what the caller expects
  2144. //
  2145. if ( NetStatus == NO_ERROR && ComputerNameArray != NULL ) {
  2146. //
  2147. // If there are no names returned,
  2148. // set the entry count to zero
  2149. //
  2150. if ( ComputerNameArray->EntryCount == 0 ) {
  2151. *ComputerNames = NULL;
  2152. *EntryCount = 0;
  2153. //
  2154. // Otherwise, allocate a buffer to return to the caller
  2155. //
  2156. } else {
  2157. ULONG Size;
  2158. ULONG i;
  2159. LPBYTE Where;
  2160. Size = sizeof(LPWSTR) * ComputerNameArray->EntryCount;
  2161. for ( i = 0; i < ComputerNameArray->EntryCount; i++ ) {
  2162. Size += ComputerNameArray->ComputerNames[i].Length + sizeof(WCHAR);
  2163. }
  2164. NetStatus = NetApiBufferAllocate( Size, (PVOID) ComputerNames );
  2165. if ( NetStatus == NO_ERROR ) {
  2166. //
  2167. // Set the size of the array
  2168. //
  2169. *EntryCount = ComputerNameArray->EntryCount;
  2170. //
  2171. // Loop copying names to the caller.
  2172. //
  2173. Where = ((LPBYTE)(*ComputerNames)) + sizeof(LPWSTR) * ComputerNameArray->EntryCount;
  2174. for ( i = 0; i < ComputerNameArray->EntryCount; i++ ) {
  2175. //
  2176. // Copy the site name into the return buffer.
  2177. //
  2178. (*ComputerNames)[i] = (LPWSTR) Where;
  2179. RtlCopyMemory( Where,
  2180. ComputerNameArray->ComputerNames[i].Buffer,
  2181. ComputerNameArray->ComputerNames[i].Length );
  2182. Where += ComputerNameArray->ComputerNames[i].Length;
  2183. *((LPWSTR)Where) = L'\0';
  2184. Where += sizeof(WCHAR);
  2185. }
  2186. }
  2187. }
  2188. NetApiBufferFree( ComputerNameArray );
  2189. }
  2190. return NetStatus;
  2191. }