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.

2371 lines
57 KiB

  1. /******************************************************************\
  2. * Microsoft Windows NT *
  3. * Copyright(c) Microsoft Corp., 1992 *
  4. \******************************************************************/
  5. /*++
  6. Module Name:
  7. USERAPI.C
  8. Description:
  9. This module contains code for all the RASADMIN APIs
  10. that require RAS information from the UAS.
  11. MprAdminUserSetInfo
  12. MprAdminUserGetInfo
  13. MprAdminGetUASServer
  14. Author:
  15. Janakiram Cherala (RamC) July 6,1992
  16. Revision History:
  17. June 8,1993 RamC Changes to RasAdminUserEnum to speed up user enumeration.
  18. May 13,1993 AndyHe Modified to coexist with other apps using user parms
  19. Mar 16,1993 RamC Change to speed up User enumeration. Now, when
  20. RasAdminUserEnum is invoked, only the user name
  21. information is returned. MprAdminUserGetInfo should
  22. be invoked to get the Ras permissions and Callback
  23. information.
  24. Aug 25,1992 RamC Code review changes:
  25. o changed all lpbBuffers to actual structure
  26. pointers.
  27. o changed all LPTSTR to LPWSTR
  28. o Added a new function RasPrivilegeAndCallBackNumber
  29. July 6,1992 RamC Begun porting from RAS 1.0 (Original version
  30. written by Narendra Gidwani - nareng)
  31. Oct 18,1995 NarenG Ported over to routing sources tree. Removed Enum
  32. since users can call NetQueryDisplayInformation
  33. to get this information.
  34. --*/
  35. #include <nt.h>
  36. #include <ntrtl.h>
  37. #include <nturtl.h>
  38. #include <ntlsa.h>
  39. #include <ntsam.h>
  40. #include <windows.h>
  41. #include <lm.h>
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #include <memory.h>
  45. #include <malloc.h>
  46. #include <raserror.h>
  47. #include <rasman.h>
  48. #include <rasppp.h>
  49. #include <mprapi.h>
  50. #include <mprapip.h>
  51. #include <usrparms.h> // for UP_CLIENT_DIAL
  52. #include <compress.h> // for Compress & Decompress fns.
  53. #include <dsrole.h> // To get the computer's role (NTW, NTS, etc)
  54. #include <oleauto.h>
  55. #include <samrpc.h>
  56. #include <dsgetdc.h>
  57. #include "sdolib.h" // To deal with SDO's
  58. extern DWORD dwFramed;
  59. extern DWORD dwFramedCallback;
  60. //
  61. // Local definitions
  62. //
  63. #define NT40_BUILD_NUMBER 1381
  64. extern const WCHAR c_szWinVersionPath[];
  65. extern const WCHAR c_szCurrentBuildNumber[];
  66. const WCHAR* pszBuildNumPath = c_szWinVersionPath;
  67. const WCHAR* pszBuildVal = c_szCurrentBuildNumber;
  68. // Names of user attributes that we set during upgrade
  69. //
  70. static const WCHAR pszAttrDialin[] = L"msNPAllowDialin";
  71. static const WCHAR pszAttrServiceType[] = L"msRADIUSServiceType";
  72. static const WCHAR pszAttrCbNumber[] = L"msRADIUSCallbackNumber";
  73. static const WCHAR pszAttrSavedCbNumber[] = L"msRASSavedCallbackNumber";
  74. // Defines a callback for enumerating users.
  75. // Returns TRUE to continue the enueration
  76. // FALSE to stop it. See EnumUsers
  77. //
  78. typedef
  79. BOOL (* pEnumUserCb)(
  80. IN NET_DISPLAY_USER* pUser,
  81. IN HANDLE hData);
  82. //
  83. // Structure of data to support user servers
  84. //
  85. typedef struct _MPR_USER_SERVER {
  86. BOOL bLocal; // Whether this is a local server
  87. HANDLE hSdo; // Sdolib handle
  88. HANDLE hServer; // Sdo server
  89. HANDLE hDefProf; // Default profile
  90. } MPR_USER_SERVER;
  91. //
  92. // Structure of data to support users
  93. //
  94. typedef struct _MPR_USER {
  95. HANDLE hUser; // Sdo handle to user
  96. MPR_USER_SERVER* pServer; // Server used to obtain this user
  97. } MPR_USER;
  98. //
  99. // Definitions used to directly manipulate ias parameters
  100. //
  101. typedef
  102. HRESULT (WINAPI *IASSetUserPropFuncPtr)(
  103. IN OPTIONAL PCWSTR pszUserParms,
  104. IN PCWSTR pszName,
  105. IN CONST VARIANT *pvarValue,
  106. OUT PWSTR *ppszNewUserParms
  107. );
  108. typedef
  109. HRESULT (WINAPI *IASQueryUserPropFuncPtr)(
  110. IN PCWSTR pszUserParms,
  111. IN PCWSTR pszName,
  112. OUT VARIANT *pvarValue
  113. );
  114. typedef
  115. VOID (WINAPI *IASFreeUserParmsFuncPtr)(
  116. IN PWSTR pszNewUserParms
  117. );
  118. const WCHAR pszIasLibrary[] = L"iassam.dll";
  119. const CHAR pszIasSetUserPropFunc[] = "IASParmsSetUserProperty";
  120. const CHAR pszIasQueryUserPropFunc[] = "IASParmsQueryUserProperty";
  121. const CHAR pszIasFreeUserParmsFunc[] = "IASParmsFreeUserParms";
  122. //
  123. // Control block for information needed to set ias
  124. // parameters directly.
  125. //
  126. typedef struct _IAS_PARAM_CB
  127. {
  128. HINSTANCE hLib;
  129. IASSetUserPropFuncPtr pSetUserProp;
  130. IASQueryUserPropFuncPtr pQueryUserProp;
  131. IASFreeUserParmsFuncPtr pFreeUserParms;
  132. } IAS_PARAM_CB;
  133. //
  134. // Structure defines data passed to MigrateNt4UserInfo
  135. //
  136. typedef struct _MIGRATE_NT4_USER_CB
  137. {
  138. IAS_PARAM_CB* pIasParams;
  139. PWCHAR pszServer;
  140. } MIGRATE_NT4_USER_CB;
  141. //
  142. // Determines the role of the given computer
  143. // (NTW, NTS, NTS DC, etc.)
  144. //
  145. DWORD GetMachineRole(
  146. IN PWCHAR pszMachine,
  147. OUT DSROLE_MACHINE_ROLE * peRole);
  148. //
  149. // Determines the build number of a given machine
  150. //
  151. DWORD GetNtosBuildNumber(
  152. IN PWCHAR pszMachine,
  153. OUT LPDWORD lpdwBuild);
  154. //
  155. // Flags used by the following ias api's.
  156. //
  157. #define IAS_F_SetDenyAsPolicy 0x1
  158. DWORD
  159. IasLoadParamInfo(
  160. OUT IAS_PARAM_CB * pIasInfo
  161. );
  162. DWORD
  163. IasUnloadParamInfo(
  164. IN IAS_PARAM_CB * pIasInfo
  165. );
  166. DWORD
  167. IasSyncUserInfo(
  168. IN IAS_PARAM_CB * IasInfo,
  169. IN PWSTR pszUserParms,
  170. IN RAS_USER_0 * pRasUser0,
  171. IN DWORD dwFlags,
  172. OUT PWSTR* ppszNewUserParams);
  173. PWCHAR
  174. FormatServerNameForNetApis(
  175. IN PWCHAR pszServer,
  176. IN PWCHAR pszBuffer);
  177. DWORD
  178. EnumUsers(
  179. IN PWCHAR pszServer,
  180. IN pEnumUserCb pCbFunction,
  181. IN HANDLE hData);
  182. BOOL
  183. MigrateNt4UserInfo(
  184. IN NET_DISPLAY_USER* pUser,
  185. IN HANDLE hData);
  186. NTSTATUS
  187. UaspGetDomainId(
  188. IN LPCWSTR ServerName OPTIONAL,
  189. OUT PSAM_HANDLE SamServerHandle OPTIONAL,
  190. OUT PPOLICY_ACCOUNT_DOMAIN_INFO * AccountDomainInfo
  191. )
  192. /*++
  193. Routine Description (borrowed from \nt\private\net\access\uasp.c):
  194. Return a domain ID of the account domain of a server.
  195. Arguments:
  196. ServerName - A pointer to a string containing the name of the
  197. Domain Controller (DC) to query. A NULL pointer
  198. or string specifies the local machine.
  199. SamServerHandle - Returns the SAM connection handle if the caller wants it.
  200. DomainId - Receives a pointer to the domain ID.
  201. Caller must deallocate buffer using NetpMemoryFree.
  202. Return Value:
  203. Error code for the operation.
  204. --*/
  205. {
  206. NTSTATUS Status;
  207. SAM_HANDLE LocalSamHandle = NULL;
  208. ACCESS_MASK LSADesiredAccess;
  209. LSA_HANDLE LSAPolicyHandle = NULL;
  210. OBJECT_ATTRIBUTES LSAObjectAttributes;
  211. UNICODE_STRING ServerNameString;
  212. //
  213. // Connect to the SAM server
  214. //
  215. RtlInitUnicodeString( &ServerNameString, ServerName );
  216. Status = SamConnect(
  217. &ServerNameString,
  218. &LocalSamHandle,
  219. SAM_SERVER_LOOKUP_DOMAIN,
  220. NULL);
  221. if ( !NT_SUCCESS(Status)) {
  222. LocalSamHandle = NULL;
  223. goto Cleanup;
  224. }
  225. //
  226. // Open LSA to read account domain info.
  227. //
  228. if ( AccountDomainInfo != NULL) {
  229. //
  230. // set desired access mask.
  231. //
  232. LSADesiredAccess = POLICY_VIEW_LOCAL_INFORMATION;
  233. InitializeObjectAttributes( &LSAObjectAttributes,
  234. NULL, // Name
  235. 0, // Attributes
  236. NULL, // Root
  237. NULL ); // Security Descriptor
  238. Status = LsaOpenPolicy( &ServerNameString,
  239. &LSAObjectAttributes,
  240. LSADesiredAccess,
  241. &LSAPolicyHandle );
  242. if( !NT_SUCCESS(Status) ) {
  243. goto Cleanup;
  244. }
  245. //
  246. // now read account domain info from LSA.
  247. //
  248. Status = LsaQueryInformationPolicy(
  249. LSAPolicyHandle,
  250. PolicyAccountDomainInformation,
  251. (PVOID *) AccountDomainInfo );
  252. if( !NT_SUCCESS(Status) ) {
  253. goto Cleanup;
  254. }
  255. }
  256. //
  257. // Return the SAM connection handle to the caller if he wants it.
  258. // Otherwise, disconnect from SAM.
  259. //
  260. if ( SamServerHandle != NULL ) {
  261. *SamServerHandle = LocalSamHandle;
  262. LocalSamHandle = NULL;
  263. }
  264. //
  265. // Cleanup locally used resources
  266. //
  267. Cleanup:
  268. if ( LocalSamHandle != NULL ) {
  269. (VOID) SamCloseHandle( LocalSamHandle );
  270. }
  271. if( LSAPolicyHandle != NULL ) {
  272. LsaClose( LSAPolicyHandle );
  273. }
  274. return Status;
  275. }
  276. NTSTATUS
  277. RasParseUserSid(
  278. IN PSID pUserSid,
  279. IN OUT PSID pDomainSid,
  280. OUT ULONG *Rid
  281. )
  282. /*++
  283. Routine Description:
  284. This function splits a sid into its domain sid and rid. The caller
  285. must provide a memory buffer for the returned DomainSid
  286. Arguments:
  287. pUserSid - Specifies the Sid to be split. The Sid is assumed to be
  288. syntactically valid. Sids with zero subauthorities cannot be split.
  289. DomainSid - Pointer to buffer to receive the domain sid.
  290. Return Value:
  291. NTSTATUS - Standard Nt Result Code
  292. STATUS_SUCCESS - The call completed successfully.
  293. STATUS_INVALID_SID - The Sid is has a subauthority count of 0.
  294. --*/
  295. {
  296. NTSTATUS NtStatus;
  297. UCHAR AccountSubAuthorityCount;
  298. ULONG AccountSidLength;
  299. //
  300. // Validate parameters
  301. //
  302. if (pDomainSid == NULL)
  303. return STATUS_INVALID_PARAMETER;
  304. //
  305. // Calculate the size of the domain sid
  306. //
  307. AccountSubAuthorityCount = *RtlSubAuthorityCountSid(pUserSid);
  308. if (AccountSubAuthorityCount < 1)
  309. return STATUS_INVALID_SID;
  310. AccountSidLength = RtlLengthSid(pUserSid);
  311. //
  312. // Copy the Account sid into the Domain sid
  313. //
  314. RtlMoveMemory(pDomainSid, pUserSid, AccountSidLength);
  315. //
  316. // Decrement the domain sid sub-authority count
  317. //
  318. (*RtlSubAuthorityCountSid(pDomainSid))--;
  319. //
  320. // Copy the rid out of the account sid
  321. //
  322. *Rid = *RtlSubAuthoritySid(pUserSid, AccountSubAuthorityCount-1);
  323. NtStatus = STATUS_SUCCESS;
  324. return(NtStatus);
  325. }
  326. NTSTATUS
  327. RasOpenSamUser(
  328. IN WCHAR * lpszServer,
  329. IN WCHAR * lpszUser,
  330. IN ACCESS_MASK DesiredAccess,
  331. OUT PSAM_HANDLE phUser)
  332. /*++
  333. Routine Description:
  334. Obtains a reference to a user that can be used in subsequent
  335. SAM calls.
  336. --*/
  337. {
  338. NTSTATUS ntStatus = STATUS_SUCCESS;
  339. SAM_HANDLE hServer = NULL, hDomain = NULL;
  340. BOOL bOk;
  341. PSID pSidUser = NULL, pSidDomain = NULL;
  342. DWORD dwSizeUserSid, dwDomainLength;
  343. PWCHAR pszDomain = NULL;
  344. SID_NAME_USE SidNameUse;
  345. ULONG ulRidUser = 0;
  346. do {
  347. // Get a server handle so that we can
  348. // open the domain
  349. ntStatus = UaspGetDomainId(
  350. lpszServer,
  351. &hServer,
  352. NULL);
  353. if (ntStatus != STATUS_SUCCESS)
  354. break;
  355. // Find out how large we need the user sid and
  356. // domain name buffers to be allocated.
  357. dwSizeUserSid = 0;
  358. dwDomainLength = 0;
  359. bOk = LookupAccountNameW(
  360. lpszServer,
  361. lpszUser,
  362. NULL,
  363. &dwSizeUserSid,
  364. NULL,
  365. &dwDomainLength,
  366. &SidNameUse);
  367. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  368. {
  369. ntStatus = GetLastError();
  370. if (ntStatus == ERROR_NONE_MAPPED)
  371. {
  372. ntStatus = STATUS_NO_SUCH_USER;
  373. }
  374. break;
  375. }
  376. // Allocate the domain name and sid
  377. dwDomainLength++;
  378. dwDomainLength *= sizeof(WCHAR);
  379. pSidUser = LocalAlloc(LPTR, dwSizeUserSid);
  380. pSidDomain = LocalAlloc(LPTR, dwSizeUserSid);
  381. pszDomain = LocalAlloc(LPTR, dwDomainLength);
  382. if ((pSidUser == NULL) ||
  383. (pszDomain == NULL) ||
  384. (pSidDomain == NULL)
  385. )
  386. {
  387. ntStatus = STATUS_NO_MEMORY;
  388. break;
  389. }
  390. // Lookup the user sid and domain name.
  391. //
  392. bOk = LookupAccountNameW(
  393. lpszServer,
  394. lpszUser,
  395. pSidUser,
  396. &dwSizeUserSid,
  397. pszDomain,
  398. &dwDomainLength,
  399. &SidNameUse);
  400. if (! bOk)
  401. {
  402. ntStatus = GetLastError();
  403. if (ntStatus == ERROR_NONE_MAPPED)
  404. {
  405. ntStatus = STATUS_NO_SUCH_USER;
  406. }
  407. break;
  408. }
  409. // Derive the user id and domain sid from the
  410. // user sid.
  411. ntStatus = RasParseUserSid(
  412. pSidUser,
  413. pSidDomain,
  414. &ulRidUser);
  415. if (ntStatus != STATUS_SUCCESS)
  416. break;
  417. // Open up the domain
  418. ntStatus = SamOpenDomain(
  419. hServer,
  420. DOMAIN_LOOKUP,
  421. pSidDomain,
  422. &hDomain);
  423. if (ntStatus != STATUS_SUCCESS)
  424. break;
  425. // Get a reference to the user
  426. ntStatus = SamOpenUser(
  427. hDomain,
  428. DesiredAccess,
  429. ulRidUser,
  430. phUser);
  431. if (ntStatus != STATUS_SUCCESS)
  432. break;
  433. } while (FALSE);
  434. // Cleanup
  435. {
  436. if (hServer)
  437. SamCloseHandle(hServer);
  438. if (hDomain)
  439. SamCloseHandle(hDomain);
  440. if (pszDomain)
  441. LocalFree(pszDomain);
  442. if (pSidUser)
  443. LocalFree(pSidUser);
  444. if (pSidDomain)
  445. LocalFree(pSidDomain);
  446. }
  447. return ntStatus;
  448. }
  449. NTSTATUS
  450. RasCloseSamUser(
  451. SAM_HANDLE hUser)
  452. /*++
  453. Routine Description:
  454. Cleans up after the RasOpenSamUser call.
  455. --*/
  456. {
  457. return SamCloseHandle(hUser);
  458. }
  459. DWORD
  460. RasGetUserParms(
  461. IN WCHAR * lpszServer,
  462. IN WCHAR * lpszUser,
  463. OUT LPWSTR * ppUserParms)
  464. /*++
  465. Routine Description:
  466. Obtains the user parms of the given user on the
  467. given machine. This function bypasses using
  468. NetUserGetInfo since level 1013 is not supported
  469. for read access (only for NetUserSetInfo). On
  470. nt5, we do not have sufficient privilege to obtain
  471. anything other than userparms.
  472. Return Value:
  473. SUCCESS on successful return.
  474. --*/
  475. {
  476. PVOID pvData;
  477. SAM_HANDLE hUser = NULL;
  478. NTSTATUS ntStatus = STATUS_SUCCESS;
  479. SAMPR_USER_PARAMETERS_INFORMATION * pUserParms = NULL;
  480. DWORD dwSize;
  481. // Validate parameters
  482. if ((ppUserParms == NULL) || (lpszUser == NULL))
  483. {
  484. return ERROR_INVALID_PARAMETER;
  485. }
  486. do {
  487. // Attempt to open the user with read access.
  488. // This level of access is required in nt4
  489. // domains in order to retrieve user parms.
  490. //
  491. ntStatus = RasOpenSamUser(
  492. lpszServer,
  493. lpszUser,
  494. GENERIC_READ,
  495. &hUser);
  496. if (ntStatus == STATUS_ACCESS_DENIED)
  497. {
  498. // If the previous call failed because
  499. // access is denied, it's likely that we're
  500. // running in an nt5 domain. In this case,
  501. // if we open the user object with no
  502. // desired access, we will still be allowed
  503. // to query the user parms.
  504. ntStatus = RasOpenSamUser(
  505. lpszServer,
  506. lpszUser,
  507. 0,
  508. &hUser);
  509. }
  510. if (ntStatus != STATUS_SUCCESS)
  511. break;
  512. // Query the user parms
  513. //
  514. ntStatus = SamQueryInformationUser(
  515. hUser,
  516. UserParametersInformation,
  517. (PVOID*)&pUserParms);
  518. if (ntStatus != STATUS_SUCCESS)
  519. break;
  520. // If the value is zero length, return null
  521. if (pUserParms->Parameters.Length == 0)
  522. {
  523. *ppUserParms = NULL;
  524. break;
  525. }
  526. // Otherwise, allocate and return the parms
  527. dwSize = (pUserParms->Parameters.Length + sizeof(WCHAR));
  528. *ppUserParms =
  529. (LPWSTR) LocalAlloc(LPTR, dwSize);
  530. if (*ppUserParms == NULL)
  531. {
  532. ntStatus = STATUS_NO_MEMORY;
  533. break;
  534. }
  535. CopyMemory(
  536. *ppUserParms,
  537. pUserParms->Parameters.Buffer,
  538. pUserParms->Parameters.Length);
  539. } while (FALSE);
  540. // Cleanup
  541. {
  542. if (ntStatus != STATUS_SUCCESS)
  543. *ppUserParms = NULL;
  544. if (hUser != NULL)
  545. RasCloseSamUser(hUser);
  546. if (pUserParms)
  547. SamFreeMemory(pUserParms);
  548. }
  549. return RtlNtStatusToDosError(ntStatus);
  550. }
  551. DWORD RasFreeUserParms(
  552. IN PVOID pvUserParms)
  553. /*++
  554. Routine Description:
  555. Frees the buffer returned by RasGetUserParms
  556. Return Value:
  557. SUCCESS on successful return.
  558. --*/
  559. {
  560. LocalFree (pvUserParms);
  561. return NO_ERROR;
  562. }
  563. DWORD APIENTRY
  564. RasPrivilegeAndCallBackNumber(
  565. IN BOOL Compress,
  566. IN PRAS_USER_0 pRasUser0
  567. )
  568. /*++
  569. Routine Description:
  570. This routine either compresses or decompresses the users call
  571. back number depending on the boolean value Compress.
  572. Return Value:
  573. SUCCESS on successful return.
  574. one of the following non-zero error codes on failure:
  575. ERROR_BAD_FORMAT indicating that usr_parms is invalid
  576. --*/
  577. {
  578. DWORD dwRetCode;
  579. switch( pRasUser0->bfPrivilege & RASPRIV_CallbackType) {
  580. case RASPRIV_NoCallback:
  581. case RASPRIV_AdminSetCallback:
  582. case RASPRIV_CallerSetCallback:
  583. if (Compress == TRUE)
  584. {
  585. WCHAR compressed[ MAX_PHONE_NUMBER_LEN + 1];
  586. // compress the phone number to fit in the
  587. // user parms field
  588. if (dwRetCode = CompressPhoneNumber(pRasUser0->wszPhoneNumber,
  589. compressed))
  590. {
  591. return (dwRetCode);
  592. }
  593. else
  594. {
  595. lstrcpy((LPTSTR) pRasUser0->wszPhoneNumber,
  596. (LPCTSTR) compressed);
  597. }
  598. }
  599. else
  600. {
  601. WCHAR decompressed[ MAX_PHONE_NUMBER_LEN + 1];
  602. decompressed[ MAX_PHONE_NUMBER_LEN ] = 0;
  603. //
  604. // decompress the phone number
  605. //
  606. if (DecompressPhoneNumber(pRasUser0->wszPhoneNumber,
  607. decompressed))
  608. {
  609. pRasUser0->bfPrivilege = RASPRIV_NoCallback;
  610. pRasUser0->wszPhoneNumber[0] = UNICODE_NULL;
  611. }
  612. else
  613. {
  614. decompressed[ MAX_PHONE_NUMBER_LEN ] = 0;
  615. lstrcpy((LPTSTR) pRasUser0->wszPhoneNumber,
  616. (LPCTSTR) decompressed);
  617. }
  618. }
  619. break;
  620. default:
  621. if (Compress == TRUE)
  622. {
  623. return(ERROR_BAD_FORMAT);
  624. }
  625. else
  626. {
  627. pRasUser0->bfPrivilege = RASPRIV_NoCallback;
  628. pRasUser0->wszPhoneNumber[0] = UNICODE_NULL;
  629. }
  630. break;
  631. }
  632. return(SUCCESS);
  633. }
  634. DWORD APIENTRY
  635. RasAdminUserSetInfo(
  636. IN const WCHAR * lpszServer,
  637. IN const WCHAR * lpszUser,
  638. IN DWORD dwLevel,
  639. IN const LPBYTE pRasUser
  640. )
  641. /*++
  642. Routine Description:
  643. This routine allows the admin to change the RAS permission for a
  644. user. If the user parms field of a user is being used by another
  645. application, it will be destroyed.
  646. Arguments:
  647. lpszServer name of the server which has the user database,
  648. eg., "\\\\UASSRVR" (the server must be one on which
  649. the UAS can be changed i.e., the name returned by
  650. RasAdminGetUasServer).
  651. lpszUser user account name to retrieve information for,
  652. e.g. "USER".
  653. dwLevel Level of the structure being passed in.
  654. pRasUser pointer to a buffer in which user information is
  655. provided. The buffer should contain a filled
  656. RAS_USER_0 structure for level 0.
  657. Return Value:
  658. SUCCESS on successful return.
  659. One of the following non-zero error codes indicating failure:
  660. return codes from NetUserGetInfo or NetUserSetInfo
  661. ERROR_BAD_FORMAT indicates that the data in pRasUser0 is bad.
  662. NERR_BufTooSmall indicates buffer size is smaller than RAS_USER_0.
  663. --*/
  664. {
  665. NET_API_STATUS dwRetCode;
  666. USER_PARMS UserParms;
  667. USER_INFO_1013 UserInfo1013;
  668. LPWSTR lpszUserParms = NULL, lpszServerFmt = NULL;
  669. PRAS_USER_0 pRasUser0;
  670. RAS_USER_0 RasUser0Backup;
  671. WCHAR pszBuffer[1024];
  672. if ( dwLevel != 0 )
  673. {
  674. return( ERROR_NOT_SUPPORTED );
  675. }
  676. pRasUser0 = (PRAS_USER_0)pRasUser;
  677. CopyMemory(&RasUser0Backup, pRasUser0, sizeof(RasUser0Backup));
  678. //
  679. // This will initialize a USER_PARMS structure with a template
  680. // for default Macintosh and Ras data.
  681. //
  682. InitUsrParams(&UserParms);
  683. // Format the server name
  684. lpszServerFmt = FormatServerNameForNetApis (
  685. (PWCHAR)lpszServer,
  686. pszBuffer);
  687. //
  688. // We are sharing the user parms field with LM SFM, and want to
  689. // preserver it's portion. So we'll get the user parms and put
  690. // the Mac primary group into our template, which is what we'll
  691. // eventually store back to the user parms field.
  692. //
  693. dwRetCode = RasGetUserParms(
  694. (WCHAR *)lpszServerFmt,
  695. (WCHAR *)lpszUser,
  696. &lpszUserParms);
  697. if (dwRetCode)
  698. {
  699. return (dwRetCode);
  700. }
  701. if (lpszUserParms)
  702. {
  703. //
  704. // usr_parms comes back as a wide character string. The MAC Primary
  705. // Group is at offset 1. We'll convert this part to ASCII and store
  706. // it in our template.
  707. //
  708. if (lstrlenW(lpszUserParms+1) >= UP_LEN_MAC)
  709. {
  710. wcstombs(UserParms.up_PriGrp, lpszUserParms+1,
  711. UP_LEN_MAC);
  712. }
  713. }
  714. //
  715. // We're done with the user info, so free up the buffer we were given.
  716. //
  717. // AndyHe... we're not done with it yet...
  718. // NetApiBufferFree(pUserInfo1013);
  719. //
  720. // Compress Callback number (the compressed phone number is placed
  721. // back in the RAS_USER_0 structure. The permissions byte may also
  722. // be affected if the phone number is not compressable.
  723. //
  724. if (dwRetCode = RasPrivilegeAndCallBackNumber(TRUE, pRasUser0))
  725. {
  726. return(dwRetCode);
  727. }
  728. //
  729. // Now put the dialin privileges and compressed phone number into
  730. // the USER_PARMS template. Note that the privileges byte is the
  731. // first byte of the callback number field.
  732. //
  733. UserParms.up_CBNum[0] = pRasUser0->bfPrivilege;
  734. wcstombs(&UserParms.up_CBNum[1], pRasUser0->wszPhoneNumber,
  735. sizeof(UserParms.up_CBNum) - 1);
  736. //
  737. // Wow, that was tough. Now, we'll convert our template into
  738. // wide characters for storing back into user parms field.
  739. //
  740. // AndyHe... we'll preserve anything past the USER_PARMS field.
  741. if (lpszUserParms &&
  742. lstrlenW(lpszUserParms) > sizeof(USER_PARMS) )
  743. {
  744. // allocate enough storage for usri1013_parms and a NULL
  745. UserInfo1013.usri1013_parms =
  746. malloc(sizeof(WCHAR) * (lstrlenW(lpszUserParms)+1));
  747. }
  748. else
  749. {
  750. UserInfo1013.usri1013_parms = malloc(2 * sizeof(USER_PARMS));
  751. }
  752. //
  753. // Just for grins, let's check that we got our buffer.
  754. //
  755. if (UserInfo1013.usri1013_parms == NULL)
  756. {
  757. RasFreeUserParms(lpszUserParms);
  758. return(GetLastError());
  759. }
  760. //
  761. // Fill in the remaining data with ' ' up to the bounds of USER_PARMS.
  762. //
  763. UserParms.up_Null = '\0';
  764. {
  765. USHORT Count;
  766. for (Count = 0; Count < sizeof(UserParms.up_CBNum); Count++ )
  767. {
  768. if (UserParms.up_CBNum[Count] == '\0')
  769. {
  770. UserParms.up_CBNum[Count] = ' ';
  771. }
  772. }
  773. }
  774. mbstowcs(UserInfo1013.usri1013_parms, (PBYTE) &UserParms,
  775. sizeof(USER_PARMS));
  776. if (lpszUserParms && lstrlenW(lpszUserParms) > sizeof(USER_PARMS) )
  777. {
  778. //
  779. // Here's where we copy all data after our parms back into the buffer
  780. //
  781. // the -1 is to account for NULL being part of the USER_PARMS struct.
  782. lstrcatW( UserInfo1013.usri1013_parms,
  783. lpszUserParms+(sizeof(USER_PARMS) - 1 ));
  784. }
  785. // AndyHe... moved from above. Now we're done with the buffer.
  786. RasFreeUserParms(lpszUserParms);
  787. // pmay: 297080
  788. //
  789. // Sync nt4 and nt5 section of user parms
  790. //
  791. {
  792. IAS_PARAM_CB IasCb;
  793. ZeroMemory(&IasCb, sizeof(IasCb));
  794. dwRetCode = IasLoadParamInfo(&IasCb);
  795. if (dwRetCode != NO_ERROR)
  796. {
  797. free(UserInfo1013.usri1013_parms);
  798. return dwRetCode;
  799. }
  800. dwRetCode = IasSyncUserInfo(
  801. &IasCb,
  802. UserInfo1013.usri1013_parms,
  803. &RasUser0Backup,
  804. 0,
  805. &lpszUserParms);
  806. free(UserInfo1013.usri1013_parms);
  807. if (dwRetCode != NO_ERROR)
  808. {
  809. IasUnloadParamInfo(&IasCb);
  810. return dwRetCode;
  811. }
  812. UserInfo1013.usri1013_parms = _wcsdup(lpszUserParms);
  813. (*IasCb.pFreeUserParms)(lpszUserParms);
  814. IasUnloadParamInfo(&IasCb);
  815. if (UserInfo1013.usri1013_parms == NULL)
  816. {
  817. return ERROR_NOT_ENOUGH_MEMORY;
  818. }
  819. }
  820. //
  821. // info level for setting user parms is 1013
  822. //
  823. dwRetCode = NetUserSetInfo(
  824. lpszServerFmt,
  825. (WCHAR *) lpszUser,
  826. 1013,
  827. (LPBYTE)&UserInfo1013,
  828. NULL);
  829. free(UserInfo1013.usri1013_parms);
  830. if (dwRetCode)
  831. {
  832. return(dwRetCode);
  833. }
  834. else
  835. {
  836. return(SUCCESS);
  837. }
  838. }
  839. DWORD
  840. RasAdminUserGetInfoFromUserParms(
  841. IN WCHAR * lpszUserParms,
  842. IN DWORD dwLevel,
  843. OUT LPBYTE pRasUser)
  844. {
  845. RAS_USER_0 * pRasUser0 = (RAS_USER_0 *)pRasUser;
  846. //
  847. // if usr_parms not initialized, default to no RAS privilege
  848. //
  849. if (lpszUserParms == NULL)
  850. {
  851. pRasUser0->bfPrivilege = RASPRIV_NoCallback;
  852. pRasUser0->wszPhoneNumber[0] = UNICODE_NULL;
  853. }
  854. else
  855. {
  856. //
  857. // AndyHe... truncate user parms at sizeof USER_PARMS
  858. //
  859. if (lstrlenW(lpszUserParms) >= sizeof(USER_PARMS))
  860. {
  861. //
  862. // we slam in a null at sizeof(USER_PARMS)-1 which corresponds to
  863. // user_parms.up_Null
  864. //
  865. lpszUserParms[sizeof(USER_PARMS)-1] = L'\0';
  866. }
  867. //
  868. // get RAS info (and validate) from usr_parms
  869. //
  870. if (MprGetUsrParams(UP_CLIENT_DIAL,
  871. (LPWSTR) lpszUserParms,
  872. (LPWSTR) pRasUser0))
  873. {
  874. pRasUser0->bfPrivilege = RASPRIV_NoCallback;
  875. pRasUser0->wszPhoneNumber[0] = UNICODE_NULL;
  876. }
  877. else
  878. {
  879. //
  880. // get RAS Privilege and callback number
  881. //
  882. RasPrivilegeAndCallBackNumber(FALSE, pRasUser0);
  883. }
  884. }
  885. return (SUCCESS);
  886. }
  887. DWORD APIENTRY
  888. RasAdminUserGetInfo(
  889. IN const WCHAR * lpszServer,
  890. IN const WCHAR * lpszUser,
  891. IN DWORD dwLevel,
  892. OUT LPBYTE pRasUser
  893. )
  894. /*++
  895. Routine Description:
  896. This routine retrieves RAS and other UAS information for a user
  897. in the domain the specified server belongs to. It loads the caller's
  898. pRasUser0 with a RAS_USER_0 structure.
  899. Arguments:
  900. lpszServer name of the server which has the user database,
  901. eg., "\\\\UASSRVR" (the server must be one on which
  902. the UAS can be changed i.e., the name returned by
  903. RasAdminGetUasServer).
  904. lpszUser user account name to retrieve information for,
  905. e.g. "USER".
  906. dwLevel Level of the structure being passed in.
  907. pRasUser0 pointer to a buffer in which user information is
  908. returned. The returned info is a RAS_USER_0 structure for
  909. level 0.
  910. Return Value:
  911. SUCCESS on successful return.
  912. One of the following non-zero error codes indicating failure:
  913. return codes from NetUserGetInfo or NetUserSetInfo
  914. ERROR_BAD_FORMAT indicates that user parms is invalid.
  915. --*/
  916. {
  917. NET_API_STATUS rc;
  918. LPWSTR lpszUserParms = NULL;
  919. PRAS_USER_0 pRasUser0;
  920. PWCHAR lpszServerFmt = NULL;
  921. WCHAR pszBuffer[1024];
  922. if ( dwLevel != 0 )
  923. {
  924. return( ERROR_NOT_SUPPORTED );
  925. }
  926. // Format the server name
  927. lpszServerFmt = FormatServerNameForNetApis (
  928. (PWCHAR)lpszServer,
  929. pszBuffer);
  930. pRasUser0 = (PRAS_USER_0)pRasUser;
  931. memset(pRasUser0, '\0', sizeof(RAS_USER_0));
  932. rc = RasGetUserParms(
  933. (WCHAR *)lpszServerFmt,
  934. (WCHAR *)lpszUser,
  935. &lpszUserParms );
  936. if (rc)
  937. {
  938. pRasUser0->bfPrivilege = RASPRIV_NoCallback;
  939. pRasUser0->wszPhoneNumber[0] = UNICODE_NULL;
  940. return( rc );
  941. }
  942. rc = RasAdminUserGetInfoFromUserParms(
  943. lpszUserParms,
  944. dwLevel,
  945. pRasUser);
  946. if (lpszUserParms)
  947. {
  948. RasFreeUserParms(lpszUserParms);
  949. }
  950. return rc;
  951. }
  952. DWORD APIENTRY
  953. RasAdminGetPDCServer(
  954. IN const WCHAR * lpszDomain,
  955. IN const WCHAR * lpszServer,
  956. OUT LPWSTR lpszUasServer
  957. )
  958. /*++
  959. Routine Description:
  960. This routine finds the server with the master UAS (the PDC) from
  961. either a domain name or a server name. Either the domain or the
  962. server (but not both) may be NULL.
  963. Arguments:
  964. lpszDomain Domain name or NULL if none.
  965. lpszServer name of the server which has the user database.
  966. lpszUasServer Caller's buffer for the returned UAS server name.
  967. The buffer should be atleast UNCLEN + 1 characters
  968. long.
  969. Return Value:
  970. SUCCESS on successful return.
  971. one of the following non-zero error codes on failure:
  972. return codes from NetGetDCName
  973. --*/
  974. {
  975. PUSER_MODALS_INFO_1 pModalsInfo1 = NULL;
  976. PDOMAIN_CONTROLLER_INFO pControllerInfo = NULL;
  977. DWORD dwErr = NO_ERROR;
  978. WCHAR TempName[UNCLEN + 1];
  979. //
  980. // Check the caller's buffer. Must be UNCLEN+1 bytes
  981. //
  982. lpszUasServer[0] = 0;
  983. lpszUasServer[UNCLEN] = 0;
  984. if ((lpszDomain) && (*lpszDomain))
  985. {
  986. //
  987. // This code will get the name of a DC for this domain.
  988. //
  989. dwErr = DsGetDcName(
  990. NULL,
  991. lpszDomain,
  992. NULL,
  993. NULL,
  994. DS_DIRECTORY_SERVICE_PREFERRED | DS_WRITABLE_REQUIRED,
  995. &pControllerInfo);
  996. if (dwErr != NO_ERROR)
  997. {
  998. return dwErr;
  999. }
  1000. //
  1001. // Return the name of the DC
  1002. //
  1003. wcscpy(lpszUasServer, pControllerInfo->DomainControllerName);
  1004. // Cleanup
  1005. //
  1006. NetApiBufferFree(pControllerInfo);
  1007. }
  1008. else
  1009. {
  1010. if ((lpszServer) && (*lpszServer))
  1011. {
  1012. lstrcpyW(TempName, lpszServer);
  1013. }
  1014. else
  1015. {
  1016. //
  1017. // Should have specified a computer name
  1018. //
  1019. return (NERR_InvalidComputer);
  1020. }
  1021. //
  1022. // Ok, we have the name of a server to use - now find out it's
  1023. // server role.
  1024. //
  1025. if (dwErr = NetUserModalsGet(TempName, 1, (LPBYTE *) &pModalsInfo1))
  1026. {
  1027. DbgPrint("Admapi: %x from NetUserModalGet(%ws)\n", dwErr, TempName);
  1028. return dwErr;
  1029. }
  1030. //
  1031. // Examine the role played by this server
  1032. //
  1033. switch (pModalsInfo1->usrmod1_role)
  1034. {
  1035. case UAS_ROLE_STANDALONE:
  1036. case UAS_ROLE_PRIMARY:
  1037. //
  1038. // In this case our server is a primary or a standalone.
  1039. // in either case we use it.
  1040. //
  1041. break;
  1042. case UAS_ROLE_BACKUP:
  1043. case UAS_ROLE_MEMBER:
  1044. //
  1045. // Use the primary domain controller as the remote server
  1046. // in this case.
  1047. //
  1048. wsprintf(TempName, L"\\\\%s", pModalsInfo1->usrmod1_primary);
  1049. break;
  1050. }
  1051. if (*TempName == L'\\')
  1052. {
  1053. lstrcpyW(lpszUasServer, TempName);
  1054. }
  1055. else
  1056. {
  1057. lstrcpyW(lpszUasServer, L"\\\\");
  1058. lstrcpyW(lpszUasServer + 2, TempName);
  1059. }
  1060. if (pModalsInfo1)
  1061. {
  1062. NetApiBufferFree(pModalsInfo1);
  1063. }
  1064. }
  1065. return (NERR_Success);
  1066. }
  1067. //
  1068. // Connects to the "user server" exposed on the given
  1069. // machine.
  1070. //
  1071. DWORD WINAPI
  1072. MprAdminUserServerConnect (
  1073. IN PWCHAR pszMachine,
  1074. IN BOOL bLocal,
  1075. OUT PHANDLE phUserServer)
  1076. {
  1077. MPR_USER_SERVER * pServer = NULL;
  1078. DWORD dwErr = NO_ERROR;
  1079. HANDLE hSdo = NULL;
  1080. // Load the SDO library if needed
  1081. if ((dwErr = SdoInit(&hSdo)) != NO_ERROR)
  1082. {
  1083. return dwErr;
  1084. }
  1085. do
  1086. {
  1087. // Create and initialize the server data
  1088. pServer = (MPR_USER_SERVER*) malloc (sizeof(MPR_USER_SERVER));
  1089. if (!pServer)
  1090. {
  1091. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1092. break;
  1093. }
  1094. ZeroMemory(pServer, sizeof(MPR_USER_SERVER));
  1095. pServer->bLocal = bLocal;
  1096. // Connect
  1097. dwErr = SdoConnect(hSdo, pszMachine, bLocal, &(pServer->hServer));
  1098. if (dwErr != NO_ERROR)
  1099. {
  1100. free (pServer);
  1101. break;
  1102. }
  1103. // Return the result
  1104. pServer->hSdo = hSdo;
  1105. *phUserServer = (HANDLE)pServer;
  1106. } while (FALSE);
  1107. // Cleanup
  1108. {
  1109. if (dwErr != NO_ERROR)
  1110. {
  1111. if (hSdo)
  1112. {
  1113. SdoCleanup(hSdo);
  1114. }
  1115. }
  1116. }
  1117. return dwErr;
  1118. }
  1119. //
  1120. // Disconnects the given "user server".
  1121. //
  1122. DWORD WINAPI
  1123. MprAdminUserServerDisconnect (
  1124. IN HANDLE hUserServer)
  1125. {
  1126. MPR_USER_SERVER * pServer = (MPR_USER_SERVER*)hUserServer;
  1127. DWORD dwErr;
  1128. // Validate
  1129. if (!pServer || !pServer->hServer)
  1130. return ERROR_INVALID_PARAMETER;
  1131. // Close out the default profile if neccessary
  1132. if (pServer->hDefProf)
  1133. {
  1134. SdoCloseProfile(pServer->hSdo, pServer->hDefProf);
  1135. pServer->hDefProf = NULL;
  1136. }
  1137. // Disconnect from the server
  1138. SdoDisconnect(pServer->hSdo, pServer->hServer);
  1139. SdoCleanup(pServer->hSdo);
  1140. pServer->hSdo = NULL;
  1141. pServer->hServer = NULL;
  1142. free (pServer);
  1143. return NO_ERROR;
  1144. }
  1145. //
  1146. // This helper function is not exported
  1147. //
  1148. DWORD WINAPI
  1149. MprAdminUserReadWriteProfFlags(
  1150. IN HANDLE hUserServer,
  1151. IN BOOL bRead,
  1152. OUT LPDWORD lpdwFlags)
  1153. {
  1154. MPR_USER_SERVER * pServer = (MPR_USER_SERVER*)hUserServer;
  1155. DWORD dwErr;
  1156. // Validate
  1157. if (!pServer || !pServer->hServer)
  1158. return ERROR_INVALID_PARAMETER;
  1159. // For MprAdmin, we assume global data is stored
  1160. // in default profile. Open it if needed.
  1161. if (pServer->hDefProf == NULL) {
  1162. dwErr = SdoOpenDefaultProfile(
  1163. pServer->hSdo,
  1164. pServer->hServer,
  1165. &(pServer->hDefProf));
  1166. if (dwErr != NO_ERROR)
  1167. return dwErr;
  1168. }
  1169. // Read or write the data according to bRead
  1170. if (bRead) {
  1171. dwErr = SdoGetProfileData(
  1172. pServer->hSdo,
  1173. pServer->hDefProf,
  1174. lpdwFlags);
  1175. }
  1176. else {
  1177. dwErr = SdoSetProfileData(
  1178. pServer->hSdo,
  1179. pServer->hDefProf,
  1180. *lpdwFlags);
  1181. }
  1182. return dwErr;
  1183. }
  1184. //
  1185. // Reads global user information
  1186. //
  1187. DWORD WINAPI
  1188. MprAdminUserReadProfFlags(
  1189. IN HANDLE hUserServer,
  1190. OUT LPDWORD lpdwFlags)
  1191. {
  1192. return MprAdminUserReadWriteProfFlags(
  1193. hUserServer,
  1194. TRUE,
  1195. lpdwFlags);
  1196. }
  1197. //
  1198. // Writes global user information
  1199. //
  1200. DWORD WINAPI
  1201. MprAdminUserWriteProfFlags(
  1202. IN HANDLE hUserServer,
  1203. IN DWORD dwFlags)
  1204. {
  1205. return MprAdminUserReadWriteProfFlags(
  1206. hUserServer,
  1207. FALSE,
  1208. &dwFlags);
  1209. }
  1210. //
  1211. // Opens the user on the given server
  1212. //
  1213. DWORD WINAPI
  1214. MprAdminUserOpen (
  1215. IN HANDLE hUserServer,
  1216. IN PWCHAR pszUser,
  1217. OUT PHANDLE phUser)
  1218. {
  1219. MPR_USER_SERVER * pServer = (MPR_USER_SERVER*)hUserServer;
  1220. MPR_USER * pUser = NULL;
  1221. HANDLE hUser = NULL;
  1222. DWORD dwErr;
  1223. WCHAR pszAdsUser[1024];
  1224. // Make sure we have a server
  1225. if (pServer == NULL)
  1226. return ERROR_INVALID_PARAMETER;
  1227. // Open up the user object in the SDO
  1228. dwErr = SdoOpenUser(
  1229. pServer->hSdo,
  1230. pServer->hServer,
  1231. pszUser,
  1232. &hUser);
  1233. if (dwErr != NO_ERROR)
  1234. return dwErr;
  1235. // Initialize and return the return value
  1236. pUser = (MPR_USER*) malloc (sizeof(MPR_USER));
  1237. if (pUser == NULL) {
  1238. SdoCloseUser (pServer->hSdo, hUser);
  1239. return ERROR_NOT_ENOUGH_MEMORY;
  1240. }
  1241. ZeroMemory(pUser, sizeof(MPR_USER));
  1242. pUser->hUser = hUser;
  1243. pUser->pServer = pServer;
  1244. *phUser = (HANDLE)pUser;
  1245. return NO_ERROR;
  1246. }
  1247. //
  1248. // Closes the user on the given server
  1249. //
  1250. DWORD WINAPI
  1251. MprAdminUserClose (
  1252. IN HANDLE hUser)
  1253. {
  1254. MPR_USER * pUser = (MPR_USER*)hUser;
  1255. DWORD dwErr;
  1256. if (pUser) {
  1257. SdoCloseUser(pUser->pServer->hSdo, pUser->hUser);
  1258. free (pUser);
  1259. }
  1260. return NO_ERROR;
  1261. }
  1262. //
  1263. // Reads in user information
  1264. //
  1265. DWORD WINAPI
  1266. MprAdminUserRead (
  1267. IN HANDLE hUser,
  1268. IN DWORD dwLevel,
  1269. IN const LPBYTE pRasUser)
  1270. {
  1271. DWORD dwErr;
  1272. MPR_USER * pUser = (MPR_USER*)hUser;
  1273. if (!hUser || !pRasUser || (dwLevel != 0 && dwLevel != 1))
  1274. return ERROR_INVALID_PARAMETER;
  1275. // Read in the info
  1276. if ((dwErr = SdoUserGetInfo (
  1277. pUser->pServer->hSdo,
  1278. pUser->hUser,
  1279. dwLevel,
  1280. pRasUser)) != NO_ERROR)
  1281. return dwErr;
  1282. return NO_ERROR;
  1283. }
  1284. //
  1285. // Writes out user information
  1286. //
  1287. DWORD WINAPI
  1288. MprAdminUserWrite (
  1289. IN HANDLE hUser,
  1290. IN DWORD dwLevel,
  1291. IN const LPBYTE pRasUser)
  1292. {
  1293. DWORD dwErr;
  1294. MPR_USER * pUser = (MPR_USER*)hUser;
  1295. if (!hUser || !pRasUser || (dwLevel != 0 && dwLevel != 1))
  1296. return ERROR_INVALID_PARAMETER;
  1297. // Write out the info
  1298. dwErr = SdoUserSetInfo (
  1299. pUser->pServer->hSdo,
  1300. pUser->hUser,
  1301. dwLevel,
  1302. pRasUser);
  1303. if (dwErr != NO_ERROR)
  1304. {
  1305. return dwErr;
  1306. }
  1307. // Commit the settings
  1308. SdoCommitUser(pUser->pServer->hSdo, pUser->hUser, TRUE);
  1309. return NO_ERROR;
  1310. }
  1311. //
  1312. // Deprecated function used only in NT4
  1313. //
  1314. DWORD APIENTRY
  1315. MprAdminUserSetInfo(
  1316. IN const WCHAR * lpszServer,
  1317. IN const WCHAR * lpszUser,
  1318. IN DWORD dwLevel,
  1319. IN const LPBYTE pRasUser
  1320. )
  1321. {
  1322. DWORD dwErr = NO_ERROR;
  1323. HANDLE hUser = NULL, hServer = NULL;
  1324. if (dwLevel == 0)
  1325. {
  1326. return RasAdminUserSetInfo(lpszServer, lpszUser, dwLevel, pRasUser);
  1327. }
  1328. else if (dwLevel == 1)
  1329. {
  1330. RAS_USER_0 RasUser0;
  1331. PRAS_USER_1 pRasUser1 = (PRAS_USER_1)pRasUser;
  1332. do
  1333. {
  1334. // Initialize the data
  1335. //
  1336. ZeroMemory(&RasUser0, sizeof(RasUser0));
  1337. RasUser0.bfPrivilege = pRasUser1->bfPrivilege;
  1338. wcsncpy(
  1339. RasUser0.wszPhoneNumber,
  1340. pRasUser1->wszPhoneNumber,
  1341. (sizeof(RasUser0.wszPhoneNumber) / sizeof(WCHAR)) - 1);
  1342. RasUser0.bfPrivilege &= ~RASPRIV_DialinPolicy;
  1343. if (pRasUser1->bfPrivilege2 & RASPRIV2_DialinPolicy)
  1344. {
  1345. RasUser0.bfPrivilege |= RASPRIV_DialinPolicy;
  1346. }
  1347. dwErr = MprAdminUserServerConnect(
  1348. (PWCHAR)lpszServer,
  1349. TRUE,
  1350. &hServer);
  1351. if (dwErr != NO_ERROR)
  1352. {
  1353. break;
  1354. }
  1355. dwErr = MprAdminUserOpen(hServer, (PWCHAR)lpszUser, &hUser);
  1356. if (dwErr != NO_ERROR)
  1357. {
  1358. break;
  1359. }
  1360. dwErr = MprAdminUserWrite(hUser, dwLevel, (LPBYTE)&RasUser0);
  1361. if (dwErr != NO_ERROR)
  1362. {
  1363. break;
  1364. }
  1365. } while (FALSE);
  1366. // Cleanup
  1367. {
  1368. if (hUser)
  1369. {
  1370. MprAdminUserClose(hUser);
  1371. }
  1372. if (hServer)
  1373. {
  1374. MprAdminUserServerDisconnect(hServer);
  1375. }
  1376. }
  1377. return dwErr;
  1378. }
  1379. return ERROR_INVALID_LEVEL;
  1380. }
  1381. //
  1382. // Deprecated function used only in NT4
  1383. //
  1384. DWORD APIENTRY
  1385. MprAdminUserGetInfo(
  1386. IN const WCHAR * lpszServer,
  1387. IN const WCHAR * lpszUser,
  1388. IN DWORD dwLevel,
  1389. OUT LPBYTE pRasUser
  1390. )
  1391. {
  1392. DWORD dwErr = NO_ERROR;
  1393. HANDLE hUser = NULL, hServer = NULL;
  1394. if (dwLevel == 0)
  1395. {
  1396. return RasAdminUserGetInfo(lpszServer, lpszUser, dwLevel, pRasUser);
  1397. }
  1398. else if (dwLevel == 1)
  1399. {
  1400. RAS_USER_0 RasUser0;
  1401. PRAS_USER_1 pRasUser1 = (PRAS_USER_1)pRasUser;
  1402. if (pRasUser1 == NULL)
  1403. {
  1404. return ERROR_INVALID_PARAMETER;
  1405. }
  1406. do
  1407. {
  1408. dwErr = MprAdminUserServerConnect(
  1409. (PWCHAR)lpszServer,
  1410. TRUE,
  1411. &hServer);
  1412. if (dwErr != NO_ERROR)
  1413. {
  1414. break;
  1415. }
  1416. dwErr = MprAdminUserOpen(hServer, (PWCHAR)lpszUser, &hUser);
  1417. if (dwErr != NO_ERROR)
  1418. {
  1419. break;
  1420. }
  1421. dwErr = MprAdminUserRead(hUser, dwLevel, (LPBYTE)&RasUser0);
  1422. if (dwErr != NO_ERROR)
  1423. {
  1424. break;
  1425. }
  1426. ZeroMemory(pRasUser1, sizeof(*pRasUser1));
  1427. pRasUser1->bfPrivilege = RasUser0.bfPrivilege;
  1428. wcsncpy(
  1429. pRasUser1->wszPhoneNumber,
  1430. RasUser0.wszPhoneNumber,
  1431. (sizeof(RasUser0.wszPhoneNumber) / sizeof(WCHAR)) - 1);
  1432. if (RasUser0.bfPrivilege & RASPRIV_DialinPolicy)
  1433. {
  1434. pRasUser1->bfPrivilege2 |= RASPRIV2_DialinPolicy;
  1435. pRasUser1->bfPrivilege &= ~RASPRIV_DialinPrivilege;
  1436. pRasUser1->bfPrivilege &= ~RASPRIV_DialinPolicy;
  1437. }
  1438. } while (FALSE);
  1439. // Cleanup
  1440. {
  1441. if (hUser)
  1442. {
  1443. MprAdminUserClose(hUser);
  1444. }
  1445. if (hServer)
  1446. {
  1447. MprAdminUserServerDisconnect(hServer);
  1448. }
  1449. }
  1450. return dwErr;
  1451. }
  1452. return ERROR_INVALID_LEVEL;
  1453. }
  1454. //
  1455. // Upgrades information from NT4 SAM (located on pszServer) to NT5 SDO's.
  1456. // Will upgrade the information into local .mdb files or into the DS
  1457. // depending on the value of bLocal.
  1458. //
  1459. DWORD APIENTRY
  1460. MprAdminUpgradeUsers(
  1461. IN PWCHAR pszServer,
  1462. IN BOOL bLocal)
  1463. {
  1464. WCHAR pszBuffer[1024], *pszServerFmt;
  1465. MIGRATE_NT4_USER_CB MigrateInfo;
  1466. IAS_PARAM_CB IasParams;
  1467. DWORD dwErr;
  1468. // Format the server name
  1469. pszServerFmt = FormatServerNameForNetApis(pszServer, pszBuffer);
  1470. // Intialize the data
  1471. ZeroMemory(&IasParams, sizeof(IasParams));
  1472. ZeroMemory(&MigrateInfo, sizeof(MigrateInfo));
  1473. MigrateInfo.pIasParams = &IasParams;
  1474. MigrateInfo.pszServer = pszServerFmt;
  1475. // Load the ias helper
  1476. dwErr = IasLoadParamInfo(&IasParams);
  1477. if (dwErr != NO_ERROR)
  1478. {
  1479. return dwErr;
  1480. }
  1481. // Enumerate the users, migrating their information as
  1482. // we go
  1483. //
  1484. dwErr = EnumUsers(
  1485. pszServerFmt,
  1486. MigrateNt4UserInfo,
  1487. (HANDLE)&MigrateInfo);
  1488. // Cleanup
  1489. {
  1490. IasUnloadParamInfo(&IasParams);
  1491. }
  1492. return dwErr;
  1493. }
  1494. DWORD APIENTRY
  1495. MprAdminGetPDCServer(
  1496. IN const WCHAR * lpszDomain,
  1497. IN const WCHAR * lpszServer,
  1498. OUT LPWSTR lpszUasServer
  1499. )
  1500. {
  1501. return(RasAdminGetPDCServer(lpszDomain, lpszServer, lpszUasServer));
  1502. }
  1503. //
  1504. // Determines the role of the given computer (NTW, NTS, NTS DC, etc.)
  1505. //
  1506. DWORD GetMachineRole(
  1507. IN PWCHAR pszMachine,
  1508. OUT DSROLE_MACHINE_ROLE * peRole)
  1509. {
  1510. PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pGlobalDomainInfo = NULL;
  1511. DWORD dwErr = NO_ERROR;
  1512. if (!peRole)
  1513. {
  1514. return ERROR_INVALID_PARAMETER;
  1515. }
  1516. //
  1517. // Get the name of the domain this machine is a member of
  1518. //
  1519. do
  1520. {
  1521. dwErr = DsRoleGetPrimaryDomainInformation(
  1522. pszMachine,
  1523. DsRolePrimaryDomainInfoBasic,
  1524. (LPBYTE *)&pGlobalDomainInfo );
  1525. if (dwErr != NO_ERROR)
  1526. {
  1527. break;
  1528. }
  1529. *peRole = pGlobalDomainInfo->MachineRole;
  1530. } while (FALSE);
  1531. // Cleanup
  1532. {
  1533. if (pGlobalDomainInfo)
  1534. {
  1535. DsRoleFreeMemory (pGlobalDomainInfo);
  1536. }
  1537. }
  1538. return dwErr;
  1539. }
  1540. //
  1541. // Determines the build number of a given machine
  1542. //
  1543. DWORD GetNtosBuildNumber(
  1544. IN PWCHAR pszMachine,
  1545. OUT LPDWORD lpdwBuild)
  1546. {
  1547. WCHAR pszComputer[1024], pszBuf[64];
  1548. HKEY hkBuild = NULL, hkMachine = NULL;
  1549. DWORD dwErr = NO_ERROR, dwType = REG_SZ, dwSize = sizeof(pszBuf);
  1550. do
  1551. {
  1552. if (pszMachine)
  1553. {
  1554. if (*pszMachine != L'\\')
  1555. {
  1556. wsprintfW(pszComputer, L"\\\\%s", pszMachine);
  1557. }
  1558. else
  1559. {
  1560. wcscpy(pszComputer, pszMachine);
  1561. }
  1562. dwErr = RegConnectRegistry (
  1563. pszComputer,
  1564. HKEY_LOCAL_MACHINE,
  1565. &hkMachine);
  1566. if (dwErr != ERROR_SUCCESS)
  1567. {
  1568. break;
  1569. }
  1570. }
  1571. else
  1572. {
  1573. hkMachine = HKEY_LOCAL_MACHINE;
  1574. }
  1575. // Open the build number key
  1576. dwErr = RegOpenKeyEx (
  1577. hkMachine,
  1578. pszBuildNumPath,
  1579. 0,
  1580. KEY_READ,
  1581. &hkBuild);
  1582. if (dwErr != ERROR_SUCCESS)
  1583. {
  1584. break;
  1585. }
  1586. // Get the value
  1587. dwErr = RegQueryValueExW (
  1588. hkBuild,
  1589. pszBuildVal,
  1590. NULL,
  1591. &dwType,
  1592. (LPBYTE)pszBuf,
  1593. &dwSize);
  1594. if (dwErr != ERROR_SUCCESS)
  1595. {
  1596. break;
  1597. }
  1598. *lpdwBuild = (DWORD) _wtoi(pszBuf);
  1599. } while (FALSE);
  1600. // Cleanup
  1601. {
  1602. if (hkMachine && pszMachine)
  1603. {
  1604. RegCloseKey(hkMachine);
  1605. }
  1606. if (hkBuild)
  1607. {
  1608. RegCloseKey(hkBuild);
  1609. }
  1610. }
  1611. return dwErr;
  1612. }
  1613. //
  1614. // Initalizes all variables needed to directly manipulate
  1615. // ias data (i.e. bypass sdo's)
  1616. //
  1617. DWORD
  1618. IasLoadParamInfo(
  1619. OUT IAS_PARAM_CB * pIasInfo
  1620. )
  1621. {
  1622. if (! pIasInfo)
  1623. {
  1624. return ERROR_INVALID_PARAMETER;
  1625. }
  1626. // Initialize
  1627. ZeroMemory(pIasInfo, sizeof(IAS_PARAM_CB));
  1628. // Load the library
  1629. //
  1630. pIasInfo->hLib = LoadLibraryW( pszIasLibrary );
  1631. if (pIasInfo->hLib == NULL)
  1632. {
  1633. return GetLastError();
  1634. }
  1635. // Load the functions
  1636. //
  1637. pIasInfo->pSetUserProp = (IASSetUserPropFuncPtr)
  1638. GetProcAddress(
  1639. pIasInfo->hLib,
  1640. pszIasSetUserPropFunc);
  1641. pIasInfo->pQueryUserProp = (IASQueryUserPropFuncPtr)
  1642. GetProcAddress(
  1643. pIasInfo->hLib,
  1644. pszIasQueryUserPropFunc);
  1645. pIasInfo->pFreeUserParms = (IASFreeUserParmsFuncPtr)
  1646. GetProcAddress(
  1647. pIasInfo->hLib,
  1648. pszIasFreeUserParmsFunc);
  1649. // Make sure everything loaded correctly
  1650. if (
  1651. (pIasInfo->pSetUserProp == NULL) ||
  1652. (pIasInfo->pQueryUserProp == NULL) ||
  1653. (pIasInfo->pFreeUserParms == NULL)
  1654. )
  1655. {
  1656. FreeLibrary(pIasInfo->hLib);
  1657. return ERROR_CAN_NOT_COMPLETE;
  1658. }
  1659. return NO_ERROR;
  1660. }
  1661. //
  1662. // Cleansup after IasLoadParamInfo
  1663. //
  1664. DWORD
  1665. IasUnloadParamInfo(
  1666. IN IAS_PARAM_CB * pIasInfo
  1667. )
  1668. {
  1669. if (pIasInfo && pIasInfo->hLib)
  1670. {
  1671. FreeLibrary(pIasInfo->hLib);
  1672. }
  1673. return NO_ERROR;
  1674. }
  1675. //
  1676. // Syncs Ias User information so that
  1677. //
  1678. DWORD
  1679. IasSyncUserInfo(
  1680. IN IAS_PARAM_CB * pIasInfo,
  1681. IN PWSTR pszUserParms,
  1682. IN RAS_USER_0 * pRasUser0,
  1683. IN DWORD dwFlags,
  1684. OUT PWSTR* ppszNewUserParams)
  1685. {
  1686. VARIANT var;
  1687. PWSTR pszParms = NULL, pszNewParms = NULL;
  1688. PWCHAR pszAttr = NULL;
  1689. DWORD dwErr;
  1690. // Initialize
  1691. *ppszNewUserParams = NULL;
  1692. // Set the Dialin bit
  1693. VariantInit(&var);
  1694. if (dwFlags & IAS_F_SetDenyAsPolicy)
  1695. {
  1696. if (pRasUser0->bfPrivilege & RASPRIV_DialinPrivilege)
  1697. {
  1698. V_VT(&var) = VT_BOOL;
  1699. V_BOOL(&var) = TRUE;
  1700. }
  1701. else
  1702. {
  1703. V_VT(&var) = VT_EMPTY;
  1704. }
  1705. }
  1706. else
  1707. {
  1708. V_VT(&var) = VT_BOOL;
  1709. if (pRasUser0->bfPrivilege & RASPRIV_DialinPrivilege)
  1710. {
  1711. V_BOOL(&var) = TRUE;
  1712. }
  1713. else
  1714. {
  1715. V_BOOL(&var) = FALSE;
  1716. }
  1717. }
  1718. dwErr = (* (pIasInfo->pSetUserProp))(
  1719. pszUserParms,
  1720. pszAttrDialin,
  1721. &var,
  1722. &pszNewParms);
  1723. VariantClear(&var);
  1724. if (dwErr != NO_ERROR)
  1725. {
  1726. return dwErr;
  1727. }
  1728. // Set the service type
  1729. VariantInit(&var);
  1730. pszParms = pszNewParms;
  1731. pszNewParms = NULL;
  1732. V_VT(&var) = VT_I4;
  1733. if (pRasUser0->bfPrivilege & RASPRIV_NoCallback)
  1734. {
  1735. V_I4(&var) = dwFramed;
  1736. }
  1737. else
  1738. {
  1739. V_I4(&var) = dwFramedCallback;
  1740. }
  1741. dwErr = (* (pIasInfo->pSetUserProp))(
  1742. pszParms,
  1743. pszAttrServiceType,
  1744. &var,
  1745. &pszNewParms);
  1746. (* (pIasInfo->pFreeUserParms))(pszParms);
  1747. VariantClear(&var);
  1748. if (dwErr != NO_ERROR)
  1749. {
  1750. return dwErr;
  1751. }
  1752. // Set the callback number
  1753. VariantInit(&var);
  1754. pszParms = pszNewParms;
  1755. pszNewParms = NULL;
  1756. V_VT(&var) = VT_BSTR;
  1757. V_BSTR(&var) = SysAllocString(pRasUser0->wszPhoneNumber);
  1758. if (V_BSTR(&var) == NULL)
  1759. {
  1760. return ERROR_NOT_ENOUGH_MEMORY;
  1761. }
  1762. if (pRasUser0->bfPrivilege & RASPRIV_AdminSetCallback)
  1763. {
  1764. pszAttr = (PWCHAR)pszAttrCbNumber;
  1765. }
  1766. else
  1767. {
  1768. pszAttr = (PWCHAR)pszAttrSavedCbNumber;
  1769. }
  1770. dwErr = (* (pIasInfo->pSetUserProp))(
  1771. pszParms,
  1772. pszAttr,
  1773. &var,
  1774. &pszNewParms);
  1775. (* (pIasInfo->pFreeUserParms))(pszParms);
  1776. VariantClear(&var);
  1777. if (dwErr != NO_ERROR)
  1778. {
  1779. return dwErr;
  1780. }
  1781. // Delete the callback number as appropriate
  1782. VariantInit(&var);
  1783. pszParms = pszNewParms;
  1784. pszNewParms = NULL;
  1785. V_VT(&var) = VT_EMPTY;
  1786. if (pRasUser0->bfPrivilege & RASPRIV_AdminSetCallback)
  1787. {
  1788. pszAttr = (PWCHAR)pszAttrSavedCbNumber;
  1789. }
  1790. else
  1791. {
  1792. pszAttr = (PWCHAR)pszAttrCbNumber;
  1793. }
  1794. dwErr = (* (pIasInfo->pSetUserProp))(
  1795. pszParms,
  1796. pszAttr,
  1797. &var,
  1798. &pszNewParms);
  1799. if (dwErr != NO_ERROR)
  1800. {
  1801. return dwErr;
  1802. }
  1803. (* (pIasInfo->pFreeUserParms))(pszParms);
  1804. VariantClear(&var);
  1805. // Return the new user parms
  1806. *ppszNewUserParams = pszNewParms;
  1807. return NO_ERROR;
  1808. }
  1809. PWCHAR
  1810. FormatServerNameForNetApis(
  1811. IN PWCHAR pszServer,
  1812. IN PWCHAR pszBuffer)
  1813. /*++
  1814. Routine Description (borrowed from \nt\private\net\access\uasp.c):
  1815. Returns static pointer to server in "\\<server>" format
  1816. --*/
  1817. {
  1818. PWCHAR pszRet = NULL;
  1819. if ((pszServer) && (*pszServer))
  1820. {
  1821. if (*pszServer != L'\\')
  1822. {
  1823. wcscpy(pszBuffer, L"\\\\");
  1824. wcscpy(pszBuffer + 2, pszServer);
  1825. pszRet = pszBuffer;
  1826. }
  1827. else
  1828. {
  1829. pszRet = pszServer;
  1830. }
  1831. }
  1832. return pszRet;
  1833. }
  1834. // Enumerates the local users
  1835. //
  1836. DWORD
  1837. EnumUsers(
  1838. IN PWCHAR pszServer,
  1839. IN pEnumUserCb pCbFunction,
  1840. IN HANDLE hData)
  1841. {
  1842. DWORD dwErr, dwIndex = 0, dwCount = 100, dwEntriesRead, i;
  1843. NET_DISPLAY_USER * pUsers;
  1844. NET_API_STATUS nStatus;
  1845. RAS_USER_0 RasUser0;
  1846. HANDLE hUser = NULL, hServer = NULL;
  1847. // Enumerate the users,
  1848. while (TRUE) {
  1849. // Read in the first block of user names
  1850. nStatus = NetQueryDisplayInformation(
  1851. pszServer,
  1852. 1,
  1853. dwIndex,
  1854. dwCount,
  1855. dwCount * sizeof(NET_DISPLAY_USER),
  1856. &dwEntriesRead,
  1857. &pUsers);
  1858. // Get out if there's an error getting user names
  1859. if ((nStatus != NERR_Success) &&
  1860. (nStatus != ERROR_MORE_DATA))
  1861. {
  1862. break;
  1863. }
  1864. // For each user read in, call the callback function
  1865. for (i = 0; i < dwEntriesRead; i++)
  1866. {
  1867. BOOL bOk;
  1868. bOk = (*pCbFunction)(&(pUsers[i]), hData);
  1869. if (bOk == FALSE)
  1870. {
  1871. nStatus = NERR_Success;
  1872. break;
  1873. }
  1874. }
  1875. // Set the index to read in the next set of users
  1876. dwIndex = pUsers[dwEntriesRead - 1].usri1_next_index;
  1877. // Free the users buffer
  1878. NetApiBufferFree (pUsers);
  1879. // If we've read in everybody, go ahead and break
  1880. if (nStatus != ERROR_MORE_DATA)
  1881. {
  1882. break;
  1883. }
  1884. }
  1885. return NO_ERROR;
  1886. }
  1887. //
  1888. // Callback function for enum users that migrates the nt4 section
  1889. // of user parms into the nt5 section
  1890. //
  1891. // Returns TRUE to continue enumeration, FALSE to stop it.
  1892. //
  1893. BOOL
  1894. MigrateNt4UserInfo(
  1895. IN NET_DISPLAY_USER* pUser,
  1896. IN HANDLE hData)
  1897. {
  1898. NET_API_STATUS nStatus;
  1899. RAS_USER_0 RasUser0;
  1900. PWSTR pszNewUserParms = NULL, pszOldUserParms = NULL, pszTemp = NULL;
  1901. USER_INFO_1013 UserInfo1013;
  1902. MIGRATE_NT4_USER_CB * pMigrateInfo;
  1903. DWORD dwErr = NO_ERROR, dwBytes;
  1904. // Get a reference to the migrate info
  1905. pMigrateInfo = (MIGRATE_NT4_USER_CB*)hData;
  1906. do
  1907. {
  1908. // Read in the old userparms
  1909. dwErr = RasGetUserParms(
  1910. pMigrateInfo->pszServer,
  1911. pUser->usri1_name,
  1912. &pszOldUserParms);
  1913. if (pszOldUserParms == NULL)
  1914. {
  1915. dwErr = NO_ERROR;
  1916. break;
  1917. }
  1918. if (pszOldUserParms != NULL)
  1919. {
  1920. // Make a copy of user parms, since
  1921. // RasAdminUserGetInfoFromUserParms may modify
  1922. // the version we read (trucation).
  1923. //
  1924. dwBytes = (wcslen(pszOldUserParms) + 1) * sizeof(WCHAR);
  1925. pszTemp = LocalAlloc(LMEM_FIXED, dwBytes);
  1926. if (pszTemp == NULL)
  1927. {
  1928. break;
  1929. }
  1930. CopyMemory(pszTemp, pszOldUserParms, dwBytes);
  1931. }
  1932. // Get the associated ras properties
  1933. dwErr = RasAdminUserGetInfoFromUserParms (
  1934. pszTemp,
  1935. 0,
  1936. (LPBYTE)&RasUser0);
  1937. if (dwErr != NO_ERROR)
  1938. {
  1939. continue;
  1940. }
  1941. // Set the information into the new
  1942. // ias section.
  1943. dwErr = IasSyncUserInfo(
  1944. pMigrateInfo->pIasParams,
  1945. pszOldUserParms,
  1946. &RasUser0,
  1947. IAS_F_SetDenyAsPolicy,
  1948. &pszNewUserParms);
  1949. if (dwErr != NO_ERROR)
  1950. {
  1951. break;
  1952. }
  1953. // Commit the information
  1954. UserInfo1013.usri1013_parms = pszNewUserParms;
  1955. nStatus = NetUserSetInfo(
  1956. pMigrateInfo->pszServer,
  1957. pUser->usri1_name,
  1958. 1013,
  1959. (LPBYTE)(&UserInfo1013),
  1960. NULL);
  1961. if (nStatus != NERR_Success)
  1962. {
  1963. break;
  1964. }
  1965. } while (FALSE);
  1966. // Cleanup
  1967. {
  1968. if (pszNewUserParms)
  1969. {
  1970. (* (pMigrateInfo->pIasParams->pFreeUserParms))(pszNewUserParms);
  1971. }
  1972. if (pszOldUserParms)
  1973. {
  1974. RasFreeUserParms(pszOldUserParms);
  1975. }
  1976. if (pszTemp)
  1977. {
  1978. LocalFree(pszTemp);
  1979. }
  1980. }
  1981. return TRUE;
  1982. }