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.

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