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.

1838 lines
59 KiB

  1. /*************************************************************************
  2. *
  3. * reguc.c
  4. *
  5. * Registry APIs for SAM-based user configuration data
  6. *
  7. * Copyright (c) 1998 Microsoft Corporation
  8. *
  9. *
  10. *
  11. *************************************************************************/
  12. /*
  13. * Includes
  14. */
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <ntlsa.h>
  19. #include <ntsam.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <windows.h>
  23. #include <lm.h>
  24. #include <ntddkbd.h>
  25. #include <ntddmou.h>
  26. #include <winstaw.h>
  27. #include <regapi.h>
  28. #include <regsam.h>
  29. #include <rpc.h>
  30. #include <rpcdce.h>
  31. #include <ntdsapi.h>
  32. #include <mprapi.h>
  33. // For more info, check out \\index1\src\nt\private\security\tools\delegate\ldap.c
  34. #include "usrprop.h"
  35. /*
  36. * !!! WARNING !!! WARNING !!!
  37. *
  38. * A lot of time could be spent on making this calculation accurate and
  39. * automatic, but time is of the essence. So a brute force
  40. * approach is used. The size of the User Configuration section that
  41. * Citrix is going to add to the User Parameters is based on NOT
  42. * ONLY the size of the USERCONFIG structure, but must account for the
  43. * Value names and the buffer management pointers as well, since the
  44. * User Parameters section is a linear buffer that holds CITRIX data
  45. * and Microsoft Services for Netware data.
  46. *
  47. * It is assumed that the overhead of the value name strings and
  48. * the buffer management pointers will NOT be greater than twice the
  49. * maximum data size. If this assumption is false, buffer overruns
  50. * will occur.
  51. *
  52. * Bruce Fortune. 1/31/97.
  53. */
  54. #define CTX_USER_PARAM_MAX_SIZE (3 * sizeof(USERCONFIG))
  55. /*
  56. * CTXPREFIX is the prefix for all value names placed in the User
  57. * Parameters section of the SAM. This is a defensive measure since
  58. * this section of the SAM is shared with MS Services for Netware.
  59. */
  60. #define CTXPREFIX L"Ctx"
  61. /*
  62. * WIN_FLAGS1 is the name of the Flags value that is used to hold
  63. * all of the F1MSK_... flags defined below. This is done in order to
  64. * reduce the amount of space required in the User Parameters section
  65. * of the SAM, since the value name of each flag is eliminated.
  66. */
  67. #define WIN_FLAGS1 L"CfgFlags1"
  68. /*
  69. * WIN_CFGPRESENT is used to indicate that the Citrix configuration
  70. * information is present in the User Parameters section of the user's
  71. * SAM record.
  72. */
  73. #define WIN_CFGPRESENT L"CfgPresent"
  74. #define CFGPRESENT_VALUE 0xB00B1E55
  75. #define F1MSK_INHERITAUTOLOGON 0x80000000
  76. #define F1MSK_INHERITRESETBROKEN 0x40000000
  77. #define F1MSK_INHERITRECONNECTSAME 0x20000000
  78. #define F1MSK_INHERITINITIALPROGRAM 0x10000000
  79. #define F1MSK_INHERITCALLBACK 0x08000000
  80. #define F1MSK_INHERITCALLBACKNUMBER 0x04000000
  81. #define F1MSK_INHERITSHADOW 0x02000000
  82. #define F1MSK_INHERITMAXSESSIONTIME 0x01000000
  83. #define F1MSK_INHERITMAXDISCONNECTIONTIME 0x00800000
  84. #define F1MSK_INHERITMAXIDLETIME 0x00400000
  85. #define F1MSK_INHERITAUTOCLIENT 0x00200000
  86. #define F1MSK_INHERITSECURITY 0x00100000
  87. #define F1MSK_PROMPTFORPASSWORD 0x00080000
  88. #define F1MSK_RESETBROKEN 0x00040000
  89. #define F1MSK_RECONNECTSAME 0x00020000
  90. #define F1MSK_LOGONDISABLED 0x00010000
  91. #define F1MSK_AUTOCLIENTDRIVES 0x00008000
  92. #define F1MSK_AUTOCLIENTLPTS 0x00004000
  93. #define F1MSK_FORCECLIENTLPTDEF 0x00002000
  94. #define F1MSK_DISABLEENCRYPTION 0x00001000
  95. #define F1MSK_HOMEDIRECTORYMAPROOT 0x00000800
  96. #define F1MSK_USEDEFAULTGINA 0x00000400
  97. #define F1MSK_DISABLECPM 0x00000200
  98. #define F1MSK_DISABLECDM 0x00000100
  99. #define F1MSK_DISABLECCM 0x00000080
  100. #define F1MSK_DISABLELPT 0x00000040
  101. #define F1MSK_DISABLECLIP 0x00000020
  102. #define F1MSK_DISABLEEXE 0x00000010
  103. #define F1MSK_WALLPAPERDISABLED 0x00000008
  104. #define F1MSK_DISABLECAM 0x00000004
  105. //#define F1MSK_unused 0x00000002
  106. //#define F1MSK_unused 0x00000001
  107. VOID AnsiToUnicode( WCHAR *, ULONG, CHAR * );
  108. NTSTATUS GetDomainName ( PWCHAR, PWCHAR * );
  109. ULONG GetFlagMask( PUSERCONFIG );
  110. VOID QueryUserConfig( HKEY, PUSERCONFIG, PWINSTATIONNAMEW );
  111. /*******************************************************************************
  112. *
  113. * UsrPropSetValue (UNICODE)
  114. *
  115. * Sets a 1-, 2-, or 4-byte value into the supplied User Parameters buffer
  116. *
  117. * ENTRY:
  118. * pValueName (input)
  119. * Points to the Value Name string
  120. * pValue (input)
  121. * Points to value
  122. * ValueLength (input)
  123. * Number of bytes in the Value
  124. * pUserParms (input)
  125. * Points to the specially formatted User Parameters buffer
  126. * UserParmsLength (input)
  127. * Length in bytes of the pUserParms buffer
  128. *
  129. * EXIT:
  130. * STATUS_SUCCESS - no error
  131. *
  132. ******************************************************************************/
  133. NTSTATUS
  134. UsrPropSetValue(
  135. WCHAR * pValueName,
  136. PVOID pValue,
  137. USHORT ValueLength,
  138. BOOL fDefaultValue,
  139. WCHAR * pUserParms,
  140. ULONG UserParmsLength
  141. )
  142. {
  143. NTSTATUS Status = STATUS_SUCCESS;
  144. UNICODE_STRING uniValue;
  145. LPWSTR lpNewUserParms = NULL;
  146. BOOL fUpdate;
  147. PWCHAR pNameBuf;
  148. ULONG NBLen;
  149. /*
  150. * Prefix the name with a unique string so that other users of
  151. * the user parameters section of the SAM won't collide with our
  152. * value names.
  153. */
  154. NBLen = sizeof(CTXPREFIX) + ((wcslen(pValueName) + 1) * sizeof(WCHAR));
  155. pNameBuf = (PWCHAR) LocalAlloc( LPTR, NBLen );
  156. if ( !pNameBuf ) {
  157. return( STATUS_INSUFFICIENT_RESOURCES );
  158. }
  159. wcscpy( pNameBuf, CTXPREFIX );
  160. wcscat( pNameBuf, pValueName );
  161. uniValue.Buffer = (PWCHAR) pValue;
  162. uniValue.Length = ValueLength;
  163. uniValue.MaximumLength = uniValue.Length;
  164. Status = SetUserProperty( pUserParms,
  165. pNameBuf,
  166. uniValue,
  167. USER_PROPERTY_TYPE_ITEM,
  168. fDefaultValue,
  169. &lpNewUserParms,
  170. &fUpdate );
  171. LocalFree( pNameBuf );
  172. if ((Status == STATUS_SUCCESS) && (lpNewUserParms != NULL)) {
  173. if (fUpdate) {
  174. if ( (wcslen( lpNewUserParms ) * sizeof(WCHAR)) > UserParmsLength ) {
  175. return( STATUS_BUFFER_TOO_SMALL );
  176. }
  177. lstrcpyW( pUserParms, lpNewUserParms);
  178. }
  179. LocalFree( lpNewUserParms );
  180. }
  181. return( Status );
  182. }
  183. /*******************************************************************************
  184. *
  185. * UsrPropGetValue (UNICODE)
  186. *
  187. * Gets a value from the supplied User Parameters buffer
  188. *
  189. * ENTRY:
  190. * pValuegName (input)
  191. * Points to the Value Name string
  192. * pValue (output)
  193. * Points to the buffer to receive the value
  194. * ValueLength (input)
  195. * Number of bytes in the buffer pointer to by pValue
  196. * pUserParms (input)
  197. * Points to the specially formatted User Parameters buffer
  198. *
  199. * EXIT:
  200. * STATUS_SUCCESS - no error
  201. *
  202. ******************************************************************************/
  203. NTSTATUS
  204. UsrPropGetValue(
  205. TCHAR * pValueName,
  206. PVOID pValue,
  207. ULONG ValueLength,
  208. WCHAR * pUserParms
  209. )
  210. {
  211. NTSTATUS Status = STATUS_SUCCESS;
  212. UNICODE_STRING uniValue;
  213. WCHAR Flag;
  214. PWCHAR pNameBuf;
  215. ULONG NBLen;
  216. /*
  217. * Prefix the name with a unique string so that other users of
  218. * the user parameters section of the SAM won't collide with our
  219. * usage.
  220. */
  221. NBLen = sizeof(CTXPREFIX) + ((wcslen(pValueName) + 1) * sizeof(WCHAR));
  222. pNameBuf = (PWCHAR) LocalAlloc( LPTR, NBLen );
  223. if ( !pNameBuf ) {
  224. return( STATUS_INSUFFICIENT_RESOURCES );
  225. }
  226. wcscpy( pNameBuf, CTXPREFIX );
  227. wcscat( pNameBuf, pValueName );
  228. Status = QueryUserProperty( pUserParms, pNameBuf, &Flag, &uniValue );
  229. LocalFree( pNameBuf );
  230. if ( Status != STATUS_SUCCESS ) {
  231. return( Status );
  232. }
  233. if ( !uniValue.Buffer ) {
  234. memset( pValue, 0, ValueLength );
  235. } else {
  236. memcpy( pValue, uniValue.Buffer, ValueLength );
  237. LocalFree( uniValue.Buffer );
  238. }
  239. return( Status );
  240. }
  241. /*******************************************************************************
  242. *
  243. * UsrPropSetString (UNICODE)
  244. *
  245. * Sets a variable length string into the supplied User Parameters buffer
  246. *
  247. * ENTRY:
  248. * pStringName (input)
  249. * Points to the String Name string
  250. * pStringValue (input)
  251. * Points to the string
  252. * pUserParms (input)
  253. * Points to the specially formatted User Parameters buffer
  254. * UserParmsLength (input)
  255. * Length in bytes of the pUserParms buffer
  256. * fDefaultValue
  257. * Indicates that this value is a default value and should not be saved
  258. *
  259. * EXIT:
  260. * STATUS_SUCCESS - no error
  261. *
  262. ******************************************************************************/
  263. NTSTATUS
  264. UsrPropSetString(
  265. WCHAR * pStringName,
  266. WCHAR * pStringValue,
  267. WCHAR * pUserParms,
  268. ULONG UserParmsLength,
  269. BOOL fDefaultValue
  270. )
  271. {
  272. NTSTATUS Status = STATUS_SUCCESS;
  273. UNICODE_STRING uniString;
  274. CHAR * pchTemp = NULL;
  275. LPWSTR lpNewUserParms = NULL;
  276. BOOL fUpdate;
  277. PWCHAR pNameBuf;
  278. ULONG NBLen;
  279. INT nMBLen;
  280. if (pStringValue == NULL) {
  281. uniString.Buffer = NULL;
  282. uniString.Length = 0;
  283. uniString.MaximumLength = 0;
  284. }
  285. else
  286. {
  287. BOOL fDummy;
  288. INT nStringLength = lstrlen(pStringValue) + 1;
  289. // Determine the length of the mulitbyte string
  290. // allocate it and convert to
  291. // this fixes bug 264907
  292. // Next release we'll need to change from ansi code page to
  293. // UTF8.
  294. nMBLen = WideCharToMultiByte(CP_ACP,
  295. 0,
  296. pStringValue,
  297. nStringLength,
  298. pchTemp,
  299. 0,
  300. NULL,
  301. NULL );
  302. pchTemp = ( CHAR * )LocalAlloc( LPTR , nMBLen );
  303. if ( pchTemp == NULL )
  304. {
  305. #ifdef DBG
  306. OutputDebugString( L"REGAPI : UsrPropSetString - STATUS_INSUFFICIENT_RESOURCES\n" );
  307. #endif
  308. Status = STATUS_INSUFFICIENT_RESOURCES;
  309. }
  310. else if( !WideCharToMultiByte( CP_ACP,
  311. 0 ,
  312. pStringValue ,
  313. nStringLength ,
  314. pchTemp ,
  315. nMBLen ,
  316. NULL ,
  317. NULL ) )
  318. {
  319. #ifdef DBG
  320. // OutputDebugString( L"REGAPI : UsrPropSetString - STATUS_UNSUCCESSFUL wctomb failed.\n" );
  321. DbgPrint( "REGAPI : UsrPropSetString - STATUS_UNSUCCESSFUL wctomb failed with 0x%x.\n" , GetLastError( ) );
  322. #endif
  323. Status = STATUS_UNSUCCESSFUL;
  324. }
  325. if( Status == STATUS_SUCCESS )
  326. {
  327. uniString.Buffer = (WCHAR *) pchTemp;
  328. uniString.Length = (USHORT)nMBLen;
  329. uniString.MaximumLength = (USHORT)nMBLen;
  330. }
  331. }
  332. /*
  333. * Prefix the name with a unique string so that other users of
  334. * the user parameters section of the SAM won't collide with our
  335. * usage.
  336. */
  337. NBLen = sizeof(CTXPREFIX) + ((wcslen(pStringName) + 1) * sizeof(WCHAR));
  338. pNameBuf = (PWCHAR) LocalAlloc( LPTR, NBLen );
  339. if ( !pNameBuf ) {
  340. return( STATUS_INSUFFICIENT_RESOURCES );
  341. }
  342. wcscpy( pNameBuf, CTXPREFIX );
  343. wcscat( pNameBuf, pStringName );
  344. Status = Status ? Status : SetUserProperty( pUserParms,
  345. pNameBuf,
  346. uniString,
  347. USER_PROPERTY_TYPE_ITEM,
  348. fDefaultValue,
  349. &lpNewUserParms,
  350. &fUpdate );
  351. LocalFree( pNameBuf );
  352. if ( (Status == STATUS_SUCCESS) && (lpNewUserParms != NULL))
  353. {
  354. if ( fUpdate )
  355. {
  356. if ( (wcslen( lpNewUserParms ) * sizeof(WCHAR)) > UserParmsLength )
  357. {
  358. return( STATUS_BUFFER_TOO_SMALL );
  359. }
  360. lstrcpyW( pUserParms, lpNewUserParms);
  361. }
  362. LocalFree( lpNewUserParms );
  363. }
  364. if ( pchTemp != NULL )
  365. {
  366. LocalFree( pchTemp );
  367. }
  368. return( Status );
  369. }
  370. /*******************************************************************************
  371. *
  372. * UsrPropGetString (UNICODE)
  373. *
  374. * Gets a variable length string from the supplied User Parameters buffer
  375. *
  376. * ENTRY:
  377. * pStringName (input)
  378. * Points to the String Name string
  379. * pStringValue (output)
  380. * Points to the string
  381. * StringValueLength (input)
  382. * Number of bytes in the buffer pointer to by pStringValue
  383. * pUserParms (input)
  384. * Points to the specially formatted User Parameters buffer
  385. *
  386. * EXIT:
  387. * STATUS_SUCCESS - no error
  388. *
  389. ******************************************************************************/
  390. NTSTATUS
  391. UsrPropGetString(
  392. TCHAR * pStringName,
  393. TCHAR * pStringValue,
  394. ULONG StringValueLength,
  395. WCHAR * pUserParms
  396. )
  397. {
  398. NTSTATUS Status = STATUS_SUCCESS;
  399. UNICODE_STRING uniString;
  400. WCHAR Flag;
  401. PWCHAR pNameBuf;
  402. ULONG NBLen;
  403. /*
  404. * Prefix the name with a unique string so that other users of
  405. * the user parameters section of the SAM won't collide with our
  406. * usage.
  407. */
  408. NBLen = sizeof(CTXPREFIX) + ((wcslen(pStringName) + 1) * sizeof(WCHAR));
  409. pNameBuf = (PWCHAR) LocalAlloc( LPTR, NBLen );
  410. if ( !pNameBuf ) {
  411. return( STATUS_INSUFFICIENT_RESOURCES );
  412. }
  413. wcscpy( pNameBuf, CTXPREFIX );
  414. wcscat( pNameBuf, pStringName );
  415. pStringValue[0] = L'\0';
  416. Status = QueryUserProperty( pUserParms, pNameBuf, &Flag, &uniString );
  417. LocalFree( pNameBuf );
  418. if ( !( Status == STATUS_SUCCESS && uniString.Length && uniString.Buffer) ) {
  419. pStringValue[0] = L'\0';
  420. } else {
  421. if ( !MultiByteToWideChar( CP_ACP,
  422. 0,
  423. (CHAR *)uniString.Buffer,
  424. uniString.Length,
  425. pStringValue,
  426. StringValueLength/sizeof(TCHAR) ) ) {
  427. Status = STATUS_UNSUCCESSFUL;
  428. }
  429. }
  430. if ( uniString.Buffer ) {
  431. LocalFree( uniString.Buffer );
  432. }
  433. return( Status );
  434. }
  435. /*******************************************************************************
  436. *
  437. * ConnectToSAM (UNICODE)
  438. *
  439. * Given a Server name and a Domain name, connect to the SAM
  440. *
  441. * ENTRY:
  442. * pServerName (input)
  443. * Points to the Server name
  444. * pDomainValue (input)
  445. * Points to the Domain name
  446. * pSAMHandle (output)
  447. * Pointer to the Handle to the SAM
  448. * pDomainHandle (output)
  449. * Pointer to the Handle to the Domain
  450. * pDomainID (ouptut)
  451. * Pointer to the Domain SID
  452. *
  453. * EXIT:
  454. * STATUS_SUCCESS - no error
  455. *
  456. ******************************************************************************/
  457. NTSTATUS
  458. ConnectToSam(
  459. BOOLEAN fReadOnly,
  460. LPTSTR pServerName,
  461. LPTSTR pDomainName,
  462. SAM_HANDLE * pSAMHandle,
  463. SAM_HANDLE * pDomainHandle,
  464. PSID * pDomainID
  465. )
  466. {
  467. NTSTATUS status;
  468. OBJECT_ATTRIBUTES object_attrib;
  469. UNICODE_STRING UniDomainName;
  470. UNICODE_STRING UniServerName;
  471. *pSAMHandle = NULL;
  472. *pDomainHandle = NULL;
  473. *pDomainID = NULL;
  474. //
  475. // connect to SAM (Security Account Manager)
  476. //
  477. #ifdef DEBUG
  478. DbgPrint( "ConnectToSam: pServerName %ws, pDomainName %ws\n", pServerName, pDomainName );
  479. #endif // DEBUG
  480. RtlInitUnicodeString(&UniServerName, pServerName);
  481. RtlInitUnicodeString(&UniDomainName, pDomainName);
  482. InitializeObjectAttributes(&object_attrib, NULL, 0, NULL, NULL);
  483. status = SamConnect( &UniServerName,
  484. pSAMHandle,
  485. fReadOnly
  486. ? SAM_SERVER_READ |
  487. SAM_SERVER_EXECUTE
  488. : STANDARD_RIGHTS_WRITE |
  489. SAM_SERVER_EXECUTE,
  490. &object_attrib );
  491. #ifdef DEBUG
  492. DbgPrint( "ConnectToSam: SamConnect returned NTSTATUS = 0x%x\n", status );
  493. #endif // DEBUG
  494. if ( status != STATUS_SUCCESS ) {
  495. goto exit;
  496. }
  497. status = SamLookupDomainInSamServer( *pSAMHandle,
  498. &UniDomainName,
  499. pDomainID);
  500. #ifdef DEBUG
  501. DbgPrint( "ConnectToSam: SamLookupDomainInSamServer returned NTSTATUS = 0x%x\n", status );
  502. #endif // DEBUG
  503. if ( status != STATUS_SUCCESS ) {
  504. goto cleanupconnect;
  505. }
  506. status = SamOpenDomain( *pSAMHandle,
  507. fReadOnly
  508. ? DOMAIN_READ |
  509. DOMAIN_LOOKUP |
  510. DOMAIN_READ_PASSWORD_PARAMETERS
  511. : DOMAIN_READ |
  512. DOMAIN_CREATE_ALIAS |
  513. DOMAIN_LOOKUP |
  514. DOMAIN_CREATE_USER |
  515. DOMAIN_READ_PASSWORD_PARAMETERS,
  516. *pDomainID,
  517. pDomainHandle );
  518. #ifdef DEBUG
  519. DbgPrint( "ConnectToSam: SamOpenDomain returned NTSTATUS = 0x%x\n", status );
  520. #endif // DEBUG
  521. if ( status != STATUS_SUCCESS ) {
  522. goto cleanuplookup;
  523. }
  524. return( STATUS_SUCCESS );
  525. /*
  526. * Error returns
  527. */
  528. cleanuplookup:
  529. SamFreeMemory( *pDomainID );
  530. *pDomainID = NULL;
  531. cleanupconnect:
  532. SamCloseHandle( *pSAMHandle );
  533. *pSAMHandle = NULL;
  534. exit:
  535. return( status );
  536. }
  537. /*******************************************************************************
  538. *
  539. * UsrPropQueryUserConfig
  540. *
  541. * Query USERCONFIG info from SAM's User Parameters
  542. *
  543. * ENTRY:
  544. * pUserParms (input)
  545. * pointer to a wide char buffer containing the SAM's User Parameters
  546. * UPlength (input )
  547. * length of the pUserParms buffer
  548. * pUser (output)
  549. * pointer to USERCONFIG structure
  550. *
  551. * EXIT:
  552. * STATUS_SUCCESS - no error
  553. *
  554. ******************************************************************************/
  555. NTSTATUS
  556. UsrPropQueryUserConfig(
  557. WCHAR *pUserParms,
  558. ULONG UPLength,
  559. PUSERCONFIG pUser )
  560. {
  561. ULONG Flags1;
  562. NTSTATUS Status;
  563. ULONG CfgPresent;
  564. USERCONFIG ucDefault;
  565. QueryUserConfig( HKEY_LOCAL_MACHINE , &ucDefault, NULL );
  566. /*
  567. * Check if the configuration exits in the User Parameters
  568. */
  569. if( ( ( Status = UsrPropGetValue( WIN_CFGPRESENT,
  570. &CfgPresent,
  571. sizeof(CfgPresent),
  572. pUserParms ) ) != NO_ERROR ) )
  573. {
  574. KdPrint( ( "UsrPropQueryUserConfig: UsrPropGetValue returned NTSTATUS = 0x%x\n", Status ) );
  575. return( Status );
  576. }
  577. else
  578. {
  579. if( CfgPresent != CFGPRESENT_VALUE )
  580. {
  581. KdPrint( ( "UsrPropQueryUserConfig: UsrPropGetValue returned NTSTATUS = 0x%x but TS-signature was not present\n", Status ) );
  582. return( STATUS_OBJECT_NAME_NOT_FOUND );
  583. }
  584. }
  585. Status = UsrPropGetValue( WIN_FLAGS1,
  586. &Flags1,
  587. sizeof(Flags1),
  588. pUserParms );
  589. if( NT_SUCCESS( Status ) )
  590. {
  591. Status = UsrPropGetValue( WIN_CALLBACK,
  592. &pUser->Callback,
  593. sizeof(pUser->Callback),
  594. pUserParms );
  595. if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
  596. {
  597. pUser->Callback = ucDefault.Callback;
  598. Status = STATUS_SUCCESS;
  599. }
  600. }
  601. if( NT_SUCCESS( Status ) )
  602. {
  603. Status = UsrPropGetValue( WIN_SHADOW,
  604. &pUser->Shadow,
  605. sizeof(pUser->Shadow),
  606. pUserParms );
  607. if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
  608. {
  609. pUser->Shadow = ucDefault.Shadow;
  610. Status = STATUS_SUCCESS;
  611. }
  612. }
  613. if( NT_SUCCESS( Status ) )
  614. {
  615. Status = UsrPropGetValue( WIN_MAXCONNECTIONTIME,
  616. &pUser->MaxConnectionTime,
  617. sizeof(pUser->MaxConnectionTime),
  618. pUserParms );
  619. if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
  620. {
  621. pUser->MaxConnectionTime = ucDefault.MaxConnectionTime;
  622. Status = STATUS_SUCCESS;
  623. }
  624. }
  625. if( NT_SUCCESS( Status ) )
  626. {
  627. Status = UsrPropGetValue( WIN_MAXDISCONNECTIONTIME,
  628. &pUser->MaxDisconnectionTime,
  629. sizeof(pUser->MaxDisconnectionTime),
  630. pUserParms );
  631. if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
  632. {
  633. pUser->MaxDisconnectionTime = ucDefault.MaxDisconnectionTime;
  634. Status = STATUS_SUCCESS;
  635. }
  636. }
  637. if( NT_SUCCESS( Status ) )
  638. {
  639. Status = UsrPropGetValue( WIN_MAXIDLETIME,
  640. &pUser->MaxIdleTime,
  641. sizeof(pUser->MaxIdleTime),
  642. pUserParms );
  643. if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
  644. {
  645. pUser->MaxIdleTime = ucDefault.MaxIdleTime;
  646. Status = STATUS_SUCCESS;
  647. }
  648. }
  649. if( NT_SUCCESS( Status ) )
  650. {
  651. Status = UsrPropGetValue( WIN_KEYBOARDLAYOUT,
  652. &pUser->KeyboardLayout,
  653. sizeof(pUser->KeyboardLayout),
  654. pUserParms );
  655. if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
  656. {
  657. pUser->KeyboardLayout = ucDefault.KeyboardLayout;
  658. Status = STATUS_SUCCESS;
  659. }
  660. }
  661. if( NT_SUCCESS( Status ) )
  662. {
  663. Status = UsrPropGetValue( WIN_MINENCRYPTIONLEVEL,
  664. &pUser->MinEncryptionLevel,
  665. sizeof(pUser->MinEncryptionLevel),
  666. pUserParms );
  667. if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
  668. {
  669. pUser->MinEncryptionLevel = ucDefault.MinEncryptionLevel;
  670. Status = STATUS_SUCCESS;
  671. }
  672. }
  673. // String properties that do not exist are init to NULL
  674. // default values are null so need to fix if ret status is a failure.
  675. if( NT_SUCCESS( Status ) )
  676. {
  677. Status = UsrPropGetString( WIN_WORKDIRECTORY,
  678. pUser->WorkDirectory,
  679. sizeof(pUser->WorkDirectory),
  680. pUserParms );
  681. if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
  682. {
  683. Status = STATUS_SUCCESS;
  684. }
  685. }
  686. if( NT_SUCCESS( Status ) )
  687. {
  688. Status = UsrPropGetString( WIN_NWLOGONSERVER,
  689. pUser->NWLogonServer,
  690. sizeof(pUser->NWLogonServer),
  691. pUserParms );
  692. if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
  693. {
  694. Status = STATUS_SUCCESS;
  695. }
  696. }
  697. if( NT_SUCCESS( Status ) )
  698. {
  699. Status = UsrPropGetString( WIN_WFHOMEDIR,
  700. pUser->WFHomeDir,
  701. sizeof(pUser->WFHomeDir),
  702. pUserParms );
  703. if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
  704. {
  705. Status = STATUS_SUCCESS;
  706. }
  707. }
  708. if( NT_SUCCESS( Status ) )
  709. {
  710. Status = UsrPropGetString( WIN_WFHOMEDIRDRIVE,
  711. pUser->WFHomeDirDrive,
  712. sizeof(pUser->WFHomeDirDrive),
  713. pUserParms );
  714. if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
  715. {
  716. Status = STATUS_SUCCESS;
  717. }
  718. }
  719. if( NT_SUCCESS( Status ) )
  720. {
  721. Status = UsrPropGetString( WIN_WFPROFILEPATH,
  722. pUser->WFProfilePath,
  723. sizeof(pUser->WFProfilePath),
  724. pUserParms );
  725. if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
  726. {
  727. Status = STATUS_SUCCESS;
  728. }
  729. if(!NT_SUCCESS( Status ))
  730. {
  731. pUser->fErrorInvalidProfile = TRUE;
  732. }
  733. }
  734. if( NT_SUCCESS( Status ) )
  735. {
  736. Status = UsrPropGetString( WIN_INITIALPROGRAM,
  737. pUser->InitialProgram,
  738. sizeof(pUser->InitialProgram),
  739. pUserParms );
  740. if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
  741. {
  742. Status = STATUS_SUCCESS;
  743. }
  744. }
  745. if( NT_SUCCESS( Status ) )
  746. {
  747. Status = UsrPropGetString( WIN_CALLBACKNUMBER,
  748. pUser->CallbackNumber,
  749. sizeof(pUser->CallbackNumber),
  750. pUserParms );
  751. if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
  752. {
  753. Status = STATUS_SUCCESS;
  754. }
  755. }
  756. if( !( NT_SUCCESS( Status ) ) )
  757. {
  758. return( Status );
  759. }
  760. pUser->fInheritAutoLogon =
  761. Flags1 & F1MSK_INHERITAUTOLOGON ? TRUE : FALSE;
  762. pUser->fInheritResetBroken =
  763. Flags1 & F1MSK_INHERITRESETBROKEN ? TRUE : FALSE;
  764. pUser->fInheritReconnectSame =
  765. Flags1 & F1MSK_INHERITRECONNECTSAME ? TRUE : FALSE;
  766. pUser->fInheritInitialProgram =
  767. Flags1 & F1MSK_INHERITINITIALPROGRAM ? TRUE : FALSE;
  768. pUser->fInheritCallback =
  769. Flags1 & F1MSK_INHERITCALLBACK ? TRUE : FALSE;
  770. pUser->fInheritCallbackNumber =
  771. Flags1 & F1MSK_INHERITCALLBACKNUMBER ? TRUE : FALSE;
  772. pUser->fInheritShadow =
  773. Flags1 & F1MSK_INHERITSHADOW ? TRUE : FALSE;
  774. pUser->fInheritMaxSessionTime =
  775. Flags1 & F1MSK_INHERITMAXSESSIONTIME ? TRUE : FALSE;
  776. pUser->fInheritMaxDisconnectionTime =
  777. Flags1 & F1MSK_INHERITMAXDISCONNECTIONTIME ? TRUE : FALSE;
  778. pUser->fInheritMaxIdleTime =
  779. Flags1 & F1MSK_INHERITMAXIDLETIME ? TRUE : FALSE;
  780. pUser->fInheritAutoClient =
  781. Flags1 & F1MSK_INHERITAUTOCLIENT ? TRUE : FALSE;
  782. pUser->fInheritSecurity =
  783. Flags1 & F1MSK_INHERITSECURITY ? TRUE : FALSE;
  784. pUser->fPromptForPassword =
  785. Flags1 & F1MSK_PROMPTFORPASSWORD ? TRUE : FALSE;
  786. pUser->fResetBroken =
  787. Flags1 & F1MSK_RESETBROKEN ? TRUE : FALSE;
  788. pUser->fReconnectSame =
  789. Flags1 & F1MSK_RECONNECTSAME ? TRUE : FALSE;
  790. pUser->fLogonDisabled =
  791. Flags1 & F1MSK_LOGONDISABLED ? TRUE : FALSE;
  792. pUser->fAutoClientDrives =
  793. Flags1 & F1MSK_AUTOCLIENTDRIVES ? TRUE : FALSE;
  794. pUser->fAutoClientLpts =
  795. Flags1 & F1MSK_AUTOCLIENTLPTS ? TRUE : FALSE;
  796. pUser->fForceClientLptDef =
  797. Flags1 & F1MSK_FORCECLIENTLPTDEF ? TRUE : FALSE;
  798. pUser->fDisableEncryption =
  799. Flags1 & F1MSK_DISABLEENCRYPTION ? TRUE : FALSE;
  800. pUser->fHomeDirectoryMapRoot =
  801. Flags1 & F1MSK_HOMEDIRECTORYMAPROOT ? TRUE : FALSE;
  802. pUser->fUseDefaultGina =
  803. Flags1 & F1MSK_USEDEFAULTGINA ? TRUE : FALSE;
  804. pUser->fDisableCpm =
  805. Flags1 & F1MSK_DISABLECPM ? TRUE : FALSE;
  806. pUser->fDisableCdm =
  807. Flags1 & F1MSK_DISABLECDM ? TRUE : FALSE;
  808. pUser->fDisableCcm =
  809. Flags1 & F1MSK_DISABLECCM ? TRUE : FALSE;
  810. pUser->fDisableLPT =
  811. Flags1 & F1MSK_DISABLELPT ? TRUE : FALSE;
  812. pUser->fDisableClip =
  813. Flags1 & F1MSK_DISABLECLIP ? TRUE : FALSE;
  814. pUser->fDisableExe =
  815. Flags1 & F1MSK_DISABLEEXE ? TRUE : FALSE;
  816. pUser->fWallPaperDisabled =
  817. Flags1 & F1MSK_WALLPAPERDISABLED ? TRUE : FALSE;
  818. pUser->fDisableCam =
  819. Flags1 & F1MSK_DISABLECAM ? TRUE : FALSE;
  820. return( STATUS_SUCCESS );
  821. }
  822. /*******************************************************************************
  823. *
  824. * UsrPropMergeUserConfig
  825. *
  826. * Merge USERCONFIG structure into User Properties section of SAM
  827. *
  828. * ENTRY:
  829. * pUserParms (input/output)
  830. * pointer to a wide char buffer containing the SAM's User Parameters
  831. * UPlength (input )
  832. * length of the pUserParms buffer
  833. * pUser (input)
  834. * pointer to USERCONFIG structure
  835. *
  836. * EXIT:
  837. * STATUS_SUCCESS - no error
  838. *
  839. * NOTES:
  840. * Certain properties have to be stored regardless if they're default or not
  841. * this is done to maintain compatibility for TSE4.0 and W2K servers
  842. ******************************************************************************/
  843. NTSTATUS
  844. UsrPropMergeUserConfig(
  845. WCHAR *pUserParms,
  846. ULONG UPLength,
  847. PUSERCONFIG pUser )
  848. {
  849. ULONG Flags1;
  850. NTSTATUS Status;
  851. USERCONFIG ucDefault;
  852. ULONG CfgPresent = CFGPRESENT_VALUE;
  853. BOOL fDefaultValue = FALSE;
  854. // 1st parameter forces default values to be placed in ucDefault
  855. QueryUserConfig( HKEY_LOCAL_MACHINE , &ucDefault, NULL );
  856. Flags1 = GetFlagMask( pUser );
  857. // this value needs to be written out
  858. Status = UsrPropSetValue( WIN_CFGPRESENT,
  859. &CfgPresent,
  860. sizeof(CfgPresent),
  861. FALSE,
  862. pUserParms,
  863. UPLength );
  864. if( NT_SUCCESS( Status ) )
  865. {
  866. // these values must be written out for TS4 & TS5.0
  867. Status = UsrPropSetValue( WIN_FLAGS1,
  868. &Flags1,
  869. sizeof(Flags1),
  870. FALSE,
  871. pUserParms,
  872. UPLength );
  873. }
  874. if( NT_SUCCESS( Status ) )
  875. {
  876. fDefaultValue = ( pUser->Callback == ucDefault.Callback );
  877. Status = UsrPropSetValue( WIN_CALLBACK,
  878. &pUser->Callback,
  879. sizeof(pUser->Callback),
  880. fDefaultValue,
  881. pUserParms,
  882. UPLength );
  883. }
  884. if( NT_SUCCESS( Status ) )
  885. {
  886. // this value must be written out for backcompat servers
  887. Status = UsrPropSetValue( WIN_SHADOW,
  888. &pUser->Shadow,
  889. sizeof(pUser->Shadow),
  890. FALSE,
  891. pUserParms,
  892. UPLength );
  893. }
  894. if( NT_SUCCESS( Status ) )
  895. {
  896. fDefaultValue = ( pUser->MaxConnectionTime == ucDefault.MaxConnectionTime );
  897. Status = UsrPropSetValue( WIN_MAXCONNECTIONTIME,
  898. &pUser->MaxConnectionTime,
  899. sizeof(pUser->MaxConnectionTime),
  900. fDefaultValue,
  901. pUserParms,
  902. UPLength );
  903. }
  904. if( NT_SUCCESS( Status ) )
  905. {
  906. fDefaultValue = ( pUser->MaxDisconnectionTime == ucDefault.MaxDisconnectionTime );
  907. Status = UsrPropSetValue( WIN_MAXDISCONNECTIONTIME,
  908. &pUser->MaxDisconnectionTime,
  909. sizeof(pUser->MaxDisconnectionTime),
  910. fDefaultValue,
  911. pUserParms,
  912. UPLength );
  913. }
  914. if( NT_SUCCESS( Status ) )
  915. {
  916. fDefaultValue = ( pUser->MaxIdleTime == ucDefault.MaxIdleTime );
  917. Status = UsrPropSetValue( WIN_MAXIDLETIME,
  918. &pUser->MaxIdleTime,
  919. sizeof(pUser->MaxIdleTime),
  920. fDefaultValue,
  921. pUserParms,
  922. UPLength );
  923. }
  924. if( NT_SUCCESS( Status ) )
  925. {
  926. fDefaultValue = ( pUser->KeyboardLayout == ucDefault.KeyboardLayout );
  927. Status = UsrPropSetValue( WIN_KEYBOARDLAYOUT,
  928. &pUser->KeyboardLayout,
  929. sizeof(pUser->KeyboardLayout),
  930. fDefaultValue,
  931. pUserParms,
  932. UPLength );
  933. }
  934. if( NT_SUCCESS( Status ) )
  935. {
  936. // always store minencryption level for backwards compatibilty purposes
  937. Status = UsrPropSetValue( WIN_MINENCRYPTIONLEVEL,
  938. &pUser->MinEncryptionLevel,
  939. sizeof(pUser->MinEncryptionLevel),
  940. FALSE,
  941. pUserParms,
  942. UPLength );
  943. }
  944. if( NT_SUCCESS( Status ) )
  945. {
  946. fDefaultValue = ( pUser->WorkDirectory[0] == 0 );
  947. Status = UsrPropSetString( WIN_WORKDIRECTORY,
  948. pUser->WorkDirectory,
  949. pUserParms,
  950. UPLength,
  951. fDefaultValue );
  952. }
  953. if( NT_SUCCESS( Status ) )
  954. {
  955. fDefaultValue = ( pUser->NWLogonServer[0] == 0 );
  956. Status = UsrPropSetString( WIN_NWLOGONSERVER,
  957. pUser->NWLogonServer,
  958. pUserParms,
  959. UPLength,
  960. fDefaultValue );
  961. }
  962. if( NT_SUCCESS( Status ) )
  963. {
  964. fDefaultValue = ( pUser->WFHomeDir[0] == 0 );
  965. Status = UsrPropSetString( WIN_WFHOMEDIR,
  966. pUser->WFHomeDir,
  967. pUserParms,
  968. UPLength,
  969. fDefaultValue );
  970. }
  971. if( NT_SUCCESS( Status ) )
  972. {
  973. fDefaultValue = ( pUser->WFHomeDirDrive[0] == 0 );
  974. Status = UsrPropSetString( WIN_WFHOMEDIRDRIVE,
  975. pUser->WFHomeDirDrive,
  976. pUserParms,
  977. UPLength,
  978. fDefaultValue );
  979. }
  980. if( NT_SUCCESS( Status ) )
  981. {
  982. fDefaultValue = ( pUser->WFProfilePath[0] == 0 );
  983. Status = UsrPropSetString( WIN_WFPROFILEPATH,
  984. pUser->WFProfilePath,
  985. pUserParms,
  986. UPLength,
  987. fDefaultValue );
  988. }
  989. if( NT_SUCCESS( Status ) )
  990. {
  991. fDefaultValue = ( pUser->InitialProgram[0] == 0 );
  992. Status = UsrPropSetString( WIN_INITIALPROGRAM,
  993. pUser->InitialProgram,
  994. pUserParms,
  995. UPLength,
  996. fDefaultValue );
  997. }
  998. if( NT_SUCCESS( Status ) )
  999. {
  1000. fDefaultValue = ( pUser->CallbackNumber[0] == 0 );
  1001. Status = UsrPropSetString( WIN_CALLBACKNUMBER,
  1002. pUser->CallbackNumber,
  1003. pUserParms,
  1004. UPLength,
  1005. fDefaultValue );
  1006. }
  1007. return( Status );
  1008. }
  1009. /*******************************************************************************
  1010. GetFlagMask
  1011. Assembles a bitmask of flags set in pUser
  1012. *******************************************************************************/
  1013. ULONG GetFlagMask( PUSERCONFIG pUser )
  1014. {
  1015. ULONG Flags1 = 0;
  1016. if ( pUser->fInheritAutoLogon ) {
  1017. Flags1 |= F1MSK_INHERITAUTOLOGON;
  1018. }
  1019. if ( pUser->fInheritResetBroken ) {
  1020. Flags1 |= F1MSK_INHERITRESETBROKEN;
  1021. }
  1022. if ( pUser->fInheritReconnectSame ) {
  1023. Flags1 |= F1MSK_INHERITRECONNECTSAME;
  1024. }
  1025. if ( pUser->fInheritInitialProgram ) {
  1026. Flags1 |= F1MSK_INHERITINITIALPROGRAM;
  1027. }
  1028. if ( pUser->fInheritCallback ) {
  1029. Flags1 |= F1MSK_INHERITCALLBACK;
  1030. }
  1031. if ( pUser->fInheritCallbackNumber ) {
  1032. Flags1 |= F1MSK_INHERITCALLBACKNUMBER;
  1033. }
  1034. if ( pUser->fInheritShadow ) {
  1035. Flags1 |= F1MSK_INHERITSHADOW;
  1036. }
  1037. if ( pUser->fInheritMaxSessionTime ) {
  1038. Flags1 |= F1MSK_INHERITMAXSESSIONTIME;
  1039. }
  1040. if ( pUser->fInheritMaxDisconnectionTime ) {
  1041. Flags1 |= F1MSK_INHERITMAXDISCONNECTIONTIME;
  1042. }
  1043. if ( pUser->fInheritMaxIdleTime ) {
  1044. Flags1 |= F1MSK_INHERITMAXIDLETIME;
  1045. }
  1046. if ( pUser->fInheritAutoClient ) {
  1047. Flags1 |= F1MSK_INHERITAUTOCLIENT;
  1048. }
  1049. if ( pUser->fInheritSecurity ) {
  1050. Flags1 |= F1MSK_INHERITSECURITY;
  1051. }
  1052. if ( pUser->fPromptForPassword ) {
  1053. Flags1 |= F1MSK_PROMPTFORPASSWORD;
  1054. }
  1055. if ( pUser->fResetBroken ) {
  1056. Flags1 |= F1MSK_RESETBROKEN;
  1057. }
  1058. if ( pUser->fReconnectSame ) {
  1059. Flags1 |= F1MSK_RECONNECTSAME;
  1060. }
  1061. if ( pUser->fLogonDisabled ) {
  1062. Flags1 |= F1MSK_LOGONDISABLED;
  1063. }
  1064. if ( pUser->fAutoClientDrives ) {
  1065. Flags1 |= F1MSK_AUTOCLIENTDRIVES;
  1066. }
  1067. if ( pUser->fAutoClientLpts ) {
  1068. Flags1 |= F1MSK_AUTOCLIENTLPTS;
  1069. }
  1070. if ( pUser->fForceClientLptDef ) {
  1071. Flags1 |= F1MSK_FORCECLIENTLPTDEF;
  1072. }
  1073. if ( pUser->fDisableEncryption ) {
  1074. Flags1 |= F1MSK_DISABLEENCRYPTION;
  1075. }
  1076. if ( pUser->fHomeDirectoryMapRoot ) {
  1077. Flags1 |= F1MSK_HOMEDIRECTORYMAPROOT;
  1078. }
  1079. if ( pUser->fUseDefaultGina ) {
  1080. Flags1 |= F1MSK_USEDEFAULTGINA;
  1081. }
  1082. if ( pUser->fDisableCpm ) {
  1083. Flags1 |= F1MSK_DISABLECPM;
  1084. }
  1085. if ( pUser->fDisableCdm ) {
  1086. Flags1 |= F1MSK_DISABLECDM;
  1087. }
  1088. if ( pUser->fDisableCcm ) {
  1089. Flags1 |= F1MSK_DISABLECCM;
  1090. }
  1091. if ( pUser->fDisableLPT ) {
  1092. Flags1 |= F1MSK_DISABLELPT;
  1093. }
  1094. if ( pUser->fDisableClip ) {
  1095. Flags1 |= F1MSK_DISABLECLIP;
  1096. }
  1097. if ( pUser->fDisableExe ) {
  1098. Flags1 |= F1MSK_DISABLEEXE;
  1099. }
  1100. if ( pUser->fWallPaperDisabled ) {
  1101. Flags1 |= F1MSK_WALLPAPERDISABLED;
  1102. }
  1103. if ( pUser->fDisableCam ) {
  1104. Flags1 |= F1MSK_DISABLECAM;
  1105. }
  1106. return Flags1;
  1107. }
  1108. /*******************************************************************************
  1109. *
  1110. * RegMergeUserConfigWithUserParameters
  1111. *
  1112. * Merge the User Configuration with the supplied SAM's User
  1113. * Parameters buffer.
  1114. *
  1115. * ENTRY:
  1116. * pUserParms (input/output)
  1117. * pointer to a wide char buffer containing the SAM's User Parameters
  1118. * UPlength (input)
  1119. * length of the pUserParms buffer
  1120. * pUser (input)
  1121. * pointer to USERCONFIG structure
  1122. *
  1123. * EXIT:
  1124. * STATUS_SUCCESS - no error
  1125. *
  1126. ******************************************************************************/
  1127. NTSTATUS
  1128. RegMergeUserConfigWithUserParameters(
  1129. PUSER_PARAMETERS_INFORMATION pUserParmInfo,
  1130. PUSERCONFIGW pUser,
  1131. PUSER_PARAMETERS_INFORMATION pNewUserParmInfo
  1132. )
  1133. {
  1134. NTSTATUS status;
  1135. ULONG ObjectID;
  1136. PWCHAR lpNewUserParms = NULL;
  1137. ULONG UPLength;
  1138. WCHAR *pUserParms;
  1139. /*
  1140. * Compute the size the user parameter buffer must be
  1141. * in order to accommodate the CITRIX data plus the existing
  1142. * User Parameters data.
  1143. */
  1144. KdPrint( ("TSUSEREX: User parameter length is %d\n", pUserParmInfo->Parameters.Length ) );
  1145. UPLength = (pUserParmInfo->Parameters.Length +
  1146. CTX_USER_PARAM_MAX_SIZE) *
  1147. sizeof(WCHAR);
  1148. pUserParms = (WCHAR *) LocalAlloc( LPTR, UPLength );
  1149. if ( pUserParms == NULL ) {
  1150. status = STATUS_INSUFFICIENT_RESOURCES;
  1151. goto exit;
  1152. }
  1153. /*
  1154. * Copy SAM data to the local buffer.
  1155. * Let the Set/Get operation terminate the buffer.
  1156. */
  1157. memcpy( pUserParms,
  1158. pUserParmInfo->Parameters.Buffer,
  1159. pUserParmInfo->Parameters.Length );
  1160. /*
  1161. * Zero fill the unused portion of the pUserParms buffer.
  1162. */
  1163. memset( &pUserParms[ pUserParmInfo->Parameters.Length / sizeof(WCHAR) ],
  1164. 0,
  1165. UPLength - pUserParmInfo->Parameters.Length );
  1166. status = UsrPropMergeUserConfig( pUserParms, UPLength, pUser );
  1167. if ( status != NO_ERROR ) {
  1168. goto cleanupoperation;
  1169. }
  1170. RtlInitUnicodeString( &pNewUserParmInfo->Parameters, pUserParms );
  1171. return( STATUS_SUCCESS );
  1172. /*
  1173. * Error returns
  1174. */
  1175. cleanupoperation:
  1176. LocalFree( pUserParms );
  1177. exit:
  1178. return( status );
  1179. }
  1180. /*******************************************************************************
  1181. *
  1182. * RegGetUserConfigFromUserParameters
  1183. *
  1184. * Get the User Configuration from the supplied SAM's
  1185. * User Parameters buffer.
  1186. *
  1187. * ENTRY:
  1188. * pUserParmInfo (input)
  1189. * pointer to a USER_PARAMETERS_INFORMATION structure obtained from
  1190. * a user's SAM entry
  1191. * pUser (input)
  1192. * pointer to USERCONFIG structure
  1193. *
  1194. * EXIT:
  1195. * STATUS_SUCCESS - no error
  1196. *
  1197. ******************************************************************************/
  1198. NTSTATUS
  1199. RegGetUserConfigFromUserParameters(
  1200. PUSER_PARAMETERS_INFORMATION pUserParmInfo,
  1201. PUSERCONFIGW pUser
  1202. )
  1203. {
  1204. NTSTATUS status;
  1205. ULONG ObjectID;
  1206. PWCHAR lpNewUserParms = NULL;
  1207. ULONG UPLength;
  1208. WCHAR *pUserParms;
  1209. /*
  1210. * Compute the size the user parameter buffer must be
  1211. * in order to accommodate the existing User Parameters.
  1212. */
  1213. UPLength = pUserParmInfo->Parameters.Length + sizeof(WCHAR);
  1214. pUserParms = (WCHAR *) LocalAlloc( LPTR, UPLength );
  1215. if ( pUserParms == NULL ) {
  1216. status = STATUS_INSUFFICIENT_RESOURCES;
  1217. goto exit;
  1218. }
  1219. /*
  1220. * Copy SAM data to the local buffer and terminate the buffer.
  1221. */
  1222. memcpy( pUserParms,
  1223. pUserParmInfo->Parameters.Buffer,
  1224. pUserParmInfo->Parameters.Length );
  1225. pUserParms[ pUserParmInfo->Parameters.Length / sizeof(WCHAR) ] = L'\0';
  1226. /*
  1227. * Extract the User Configuration from the SAM's User
  1228. * Parameters.
  1229. */
  1230. status = UsrPropQueryUserConfig( pUserParms, UPLength, pUser );
  1231. LocalFree( pUserParms );
  1232. if ( status != NO_ERROR ) {
  1233. goto exit;
  1234. }
  1235. return( STATUS_SUCCESS );
  1236. /*
  1237. * Error returns
  1238. */
  1239. exit:
  1240. #ifdef DEBUG
  1241. DbgPrint( "RegGetUserConfigFromUserParameters: status = 0x%x\n", status );
  1242. #endif // DEBUG
  1243. return( status );
  1244. }
  1245. /*******************************************************************************
  1246. *
  1247. * RegSAMUserConfig
  1248. *
  1249. * Set or Get the User Configuration for a user from the Domain whose
  1250. * PDC is server is given.
  1251. *
  1252. * ENTRY:
  1253. * fGetConfig (input)
  1254. * TRUE for Get config, FALSE for Set configuration
  1255. * pUsername (input)
  1256. * points to the user name
  1257. * pServerName (input)
  1258. * points to the name of the server. UNC names permitted.
  1259. * pUser (input/output)
  1260. * pointer to USERCONFIG structure
  1261. *
  1262. * EXIT:
  1263. * STATUS_SUCCESS - no error
  1264. *
  1265. ******************************************************************************/
  1266. DWORD
  1267. RegSAMUserConfig(
  1268. BOOLEAN fGetConfig,
  1269. PWCHAR pUserName,
  1270. PWCHAR pServerName,
  1271. PUSERCONFIGW pUser
  1272. )
  1273. {
  1274. NTSTATUS status;
  1275. UNICODE_STRING UniUserName;
  1276. PULONG pRids = NULL;
  1277. PSID_NAME_USE pSidNameUse = NULL;
  1278. ULONG ObjectID;
  1279. SID_NAME_USE SidNameUse;
  1280. SAM_HANDLE Handle = (SAM_HANDLE) 0;
  1281. PUSER_PARAMETERS_INFORMATION UserParmInfo = NULL;
  1282. ULONG UPLength;
  1283. SAM_HANDLE SAMHandle = NULL;
  1284. SAM_HANDLE DomainHandle = NULL;
  1285. PWCHAR ServerName = NULL;
  1286. PSID DomainID = NULL;
  1287. PWCHAR pUserParms;
  1288. PWCHAR pDomainName = NULL;
  1289. WCHAR wCompName[MAX_COMPUTERNAME_LENGTH+1];
  1290. ULONG openFlag;
  1291. DWORD dwErr = ERROR_SUCCESS;
  1292. ULONG cValues;
  1293. HANDLE hDS = NULL;
  1294. PDS_NAME_RESULTW pDsResult = NULL;
  1295. typedef DWORD (WINAPI *PFNDSCRACKNAMES) ( HANDLE, DS_NAME_FLAGS, DS_NAME_FORMAT, \
  1296. DS_NAME_FORMAT, DWORD, LPTSTR *, PDS_NAME_RESULT *);
  1297. typedef void (WINAPI *PFNDSFREENAMERESULT) (DS_NAME_RESULT *);
  1298. typedef DWORD (WINAPI *PFNDSBIND) (TCHAR *, TCHAR *, HANDLE *);
  1299. typedef DWORD (WINAPI *PFNDSUNBIND) (HANDLE *);
  1300. PFNDSCRACKNAMES pfnDsCrackNamesW;
  1301. PFNDSFREENAMERESULT pfnDsFreeNameResultW;
  1302. PFNDSBIND pfnDsBindW;
  1303. PFNDSUNBIND pfnDsUnBindW;
  1304. // vars used for handling UPN anmes
  1305. WCHAR tmpUserName[MAX_PATH];
  1306. WCHAR *pUserAlias;
  1307. HINSTANCE hNtdsApi = NULL;
  1308. // We dont' care about the domain since we get it otherwise.
  1309. // WCHAR tmpDomainName[ MAX_PATH];
  1310. // tmpDomainName[0]=NULL;
  1311. tmpUserName[0]=0;
  1312. pUserAlias=NULL;
  1313. #ifdef DEBUG
  1314. DbgPrint( "RegSAMUserConfig %s, User %ws, Server %ws\n", fGetConfig ? "GET" : "SET", pUserName, pServerName ? pServerName : L"-NULL-" );
  1315. #endif // DEBUG
  1316. if (pServerName == NULL) {
  1317. UPLength = MAX_COMPUTERNAME_LENGTH + 1;
  1318. if (!GetComputerName(wCompName, &UPLength)) {
  1319. status = STATUS_INSUFFICIENT_RESOURCES;
  1320. goto exit;
  1321. }
  1322. }
  1323. // init this to the name passed in, if it is not a UPN name, we will continue to use
  1324. // the names passed into this function.
  1325. pUserAlias = pUserName;
  1326. //
  1327. //
  1328. // NEW code to handle UPN if the name passed in contains a '@' in the name.
  1329. // The call to CrackName is to seperate the UPN name into the user alias by
  1330. // contacting the DS and looking in the Gloabl-Catalog.
  1331. //
  1332. //
  1333. if ( wcschr(pUserName,L'@') != NULL )
  1334. {
  1335. hNtdsApi = LoadLibrary(TEXT("ntdsapi.dll"));
  1336. if ( hNtdsApi )
  1337. {
  1338. pfnDsCrackNamesW = (PFNDSCRACKNAMES)GetProcAddress(hNtdsApi, "DsCrackNamesW");
  1339. pfnDsFreeNameResultW = (PFNDSFREENAMERESULT)GetProcAddress(hNtdsApi, "DsFreeNameResultW");
  1340. pfnDsBindW = (PFNDSBIND)GetProcAddress(hNtdsApi, "DsBindW");
  1341. pfnDsUnBindW = (PFNDSUNBIND)GetProcAddress(hNtdsApi, "DsUnBindW");
  1342. if (pfnDsBindW && pfnDsCrackNamesW )
  1343. {
  1344. dwErr = pfnDsBindW(NULL, NULL, &hDS);
  1345. }
  1346. else
  1347. {
  1348. dwErr = ERROR_INVALID_FUNCTION;
  1349. }
  1350. if(dwErr == ERROR_SUCCESS)
  1351. {
  1352. dwErr = pfnDsCrackNamesW(hDS,
  1353. DS_NAME_NO_FLAGS,
  1354. DS_UNKNOWN_NAME,
  1355. DS_NT4_ACCOUNT_NAME,
  1356. 1,
  1357. &pUserName,
  1358. &pDsResult);
  1359. if(dwErr == ERROR_SUCCESS)
  1360. {
  1361. if(pDsResult)
  1362. {
  1363. if( pDsResult->rItems )
  1364. {
  1365. if (pDsResult->rItems[0].pName )
  1366. {
  1367. // no error
  1368. status = STATUS_SUCCESS;
  1369. wcsncpy(tmpUserName, pDsResult->rItems[0].pName, MAX_PATH-1);
  1370. tmpUserName[MAX_PATH-1] = L'\0';
  1371. KdPrint(("RegSAMUserConfig: tmpUserName=%ws\n",tmpUserName));
  1372. // do we have a non-null name?
  1373. if ( tmpUserName[0] ) {
  1374. pUserAlias = wcschr(tmpUserName,L'\\');
  1375. pUserAlias++; //move pass the wack.
  1376. // we are not using the domain name, we already have this
  1377. // wcscpy(tmpDomainName, pDsResult->rItems[0].pDomain);
  1378. }
  1379. }
  1380. else
  1381. {
  1382. KdPrint(("RegSAMUserConfig: pDsResult->rItems[0].pName is NULL\n"));
  1383. }
  1384. }
  1385. else
  1386. {
  1387. KdPrint(("RegSAMUserConfig: pDsResult->rItems=0x%lx\n",pDsResult->rItems));
  1388. }
  1389. }
  1390. else
  1391. {
  1392. KdPrint(("RegSAMUserConfig: pDsResult=0x%lx\n",pDsResult));
  1393. }
  1394. }
  1395. else
  1396. {
  1397. switch( dwErr )
  1398. {
  1399. case ERROR_INVALID_PARAMETER:
  1400. status = STATUS_INVALID_PARAMETER;
  1401. break;
  1402. case ERROR_NOT_ENOUGH_MEMORY:
  1403. status = STATUS_NO_MEMORY;
  1404. break;
  1405. default:
  1406. status = STATUS_UNSUCCESSFUL;
  1407. break;
  1408. }
  1409. // have decided to continue using the passed-in pUserName instead of what
  1410. // would have been returned from CrackName. Hence, no need to exit.
  1411. // goto exit;
  1412. }
  1413. }
  1414. else
  1415. {
  1416. status = STATUS_UNSUCCESSFUL; // DsBindW doesn't have a clean set of errors.
  1417. // have decided to continue using the passed-in pUserName instead of what
  1418. // would have been returned from DsBind/CrackName. Hence, no need to exit.
  1419. // goto exit;
  1420. }
  1421. }
  1422. else
  1423. {
  1424. status = STATUS_DLL_NOT_FOUND;
  1425. // have decided to continue using the passed-in pUserName instead of what
  1426. // would have been returned from DsBind/CrackName. Hence, no need to exit.
  1427. // goto exit;
  1428. }
  1429. }
  1430. #ifdef DEBUG
  1431. DbgPrint( "RegSAMUserConfig: pUserAlias=%ws\n", pUserAlias);
  1432. #endif // DEBUG
  1433. status = GetDomainName( pServerName, &pDomainName );
  1434. #ifdef DEBUG
  1435. DbgPrint( "RegSAMUserConfig: GetDomainName returned NTSTATUS = 0x%x\n", status );
  1436. #endif // DEBUG
  1437. if ( status != STATUS_SUCCESS ) {
  1438. goto exit;
  1439. }
  1440. /*
  1441. * With the PDC Server name and the Domain Name,
  1442. * connect to the SAM
  1443. */
  1444. status = ConnectToSam( fGetConfig,
  1445. pServerName,
  1446. pDomainName,
  1447. &SAMHandle,
  1448. &DomainHandle,
  1449. &DomainID );
  1450. #ifdef DEBUG
  1451. DbgPrint( "RegSAMUserConfig: ConnectToSam returned NTSTATUS = 0x%x\n", status );
  1452. #endif // DEBUG
  1453. if ( status != STATUS_SUCCESS ) {
  1454. goto cleanupconnect;
  1455. }
  1456. RtlInitUnicodeString( &UniUserName, pUserAlias );
  1457. status = SamLookupNamesInDomain( DomainHandle,
  1458. 1,
  1459. &UniUserName,
  1460. &pRids,
  1461. &pSidNameUse );
  1462. #ifdef DEBUG
  1463. DbgPrint( "RegSAMUserConfig: SamLookupNamesInDomain returned NTSTATUS = 0x%x\n", status );
  1464. #endif // DEBUG
  1465. if ((status != STATUS_SUCCESS) ||
  1466. (pRids == NULL) ||
  1467. (pSidNameUse == NULL)) {
  1468. goto cleanuplookup;
  1469. }
  1470. /*
  1471. * Found the user name in the SAM, copy and free SAM info
  1472. */
  1473. ObjectID = pRids[ 0 ];
  1474. SidNameUse = pSidNameUse[ 0 ];
  1475. SamFreeMemory( pRids );
  1476. SamFreeMemory( pSidNameUse );
  1477. /*
  1478. * Open the SAM entry for this user
  1479. */
  1480. openFlag = fGetConfig ? USER_READ
  1481. : USER_WRITE_ACCOUNT| USER_READ;
  1482. #ifdef DEBUG
  1483. DbgPrint("calling SamOpenUSer with flag = 0x%x\n", openFlag);
  1484. #endif
  1485. status = SamOpenUser( DomainHandle,
  1486. openFlag,
  1487. ObjectID,
  1488. &Handle );
  1489. // For getting config parametesr...
  1490. // The call will fail if it goes to the DC, for that case, change
  1491. // flag, since DC does allow access to read user-parameters (for
  1492. // legacy compat reasons).
  1493. if (!NT_SUCCESS( status ) && fGetConfig )
  1494. {
  1495. openFlag = 0;
  1496. #ifdef DEBUG
  1497. DbgPrint("calling SamOpenUSer with flag = 0x%x\n", openFlag);
  1498. #endif
  1499. status = SamOpenUser( DomainHandle,
  1500. openFlag,
  1501. ObjectID,
  1502. &Handle );
  1503. }
  1504. #ifdef DEBUG
  1505. DbgPrint( "RegSAMUserConfig: SamOpenUser returned NTSTATUS = 0x%x\n", status );
  1506. #endif // DEBUG
  1507. if ( status != STATUS_SUCCESS ) {
  1508. goto cleanupsamopen;
  1509. }
  1510. /*
  1511. * Get the user parameters from the SAM
  1512. */
  1513. status = SamQueryInformationUser( Handle,
  1514. UserParametersInformation,
  1515. (PVOID *) &UserParmInfo );
  1516. KdPrint( ( "RegSAMUserConfig: SamQueryInformationUser returned NTSTATUS = 0x%x\n", status ) );
  1517. if ( status != STATUS_SUCCESS || UserParmInfo == NULL ) {
  1518. goto cleanupsamquery;
  1519. }
  1520. if( fGetConfig )
  1521. {
  1522. /*
  1523. * Extract the User Configuration from the SAM's User
  1524. * Parameters.
  1525. *
  1526. * For Whistler builds and higher we assume that not every field
  1527. * has been stored in the SAM we'll need to retrieve the default
  1528. * values first
  1529. */
  1530. KdPrint( ( "RegSAMUserConfig: UserParmInfo %d\n", UserParmInfo->Parameters.Length ) );
  1531. status = RegGetUserConfigFromUserParameters( UserParmInfo, pUser );
  1532. KdPrint( ( "RegSAMUserConfig: RegGetUserConfigFromUserParameters returned NTSTATUS = 0x%x\n", status ) );
  1533. SamFreeMemory( UserParmInfo );
  1534. UserParmInfo = NULL;
  1535. if ( status != NO_ERROR )
  1536. {
  1537. goto cleanupoperation;
  1538. }
  1539. }
  1540. else
  1541. {
  1542. USER_PARAMETERS_INFORMATION NewUserParmInfo;
  1543. /*
  1544. * Set the SAM based on the supplied User Configuration.
  1545. */
  1546. status = RegMergeUserConfigWithUserParameters( UserParmInfo,
  1547. pUser,
  1548. &NewUserParmInfo );
  1549. KdPrint( ( "RegSAMUserConfig: RegMergeUserConfigWithUserParameters returned NTSTATUS = 0x%x\n", status ) );
  1550. SamFreeMemory( UserParmInfo );
  1551. UserParmInfo = NULL;
  1552. if( status != NO_ERROR )
  1553. {
  1554. goto cleanupoperation;
  1555. }
  1556. //
  1557. //This code is back-porting of a Win2K SP3 fix:
  1558. // Winse #25510 : As per KBArticle Q317853
  1559. // See also KBArticle Q277631
  1560. //
  1561. //
  1562. // MprAdminUser APIs
  1563. //
  1564. {
  1565. typedef DWORD (APIENTRY *MPR_ADMIN_USER_GET_INFO)(
  1566. IN const WCHAR * lpszServer,
  1567. IN const WCHAR * lpszUser,
  1568. IN DWORD dwLevel,
  1569. OUT LPBYTE lpbBuffer
  1570. );
  1571. typedef DWORD (APIENTRY *MPR_ADMIN_USER_SET_INFO)(
  1572. IN const WCHAR * lpszServer,
  1573. IN const WCHAR * lpszUser,
  1574. IN DWORD dwLevel,
  1575. IN const LPBYTE lpbBuffer
  1576. );
  1577. //
  1578. //This code initializes RAS userparams
  1579. //If we don't do this, SamSetInformationUser()
  1580. //will set Remote Access Permission (msNPAllowDialin)
  1581. //to a wrong value.
  1582. //
  1583. RAS_USER_1 ru1;
  1584. MPR_ADMIN_USER_GET_INFO pMprAdminUserGetInfo = NULL;
  1585. MPR_ADMIN_USER_SET_INFO pMprAdminUserSetInfo = NULL;
  1586. HMODULE hMprDLL = LoadLibrary(L"mprapi.dll");
  1587. if(hMprDLL)
  1588. {
  1589. pMprAdminUserGetInfo = (MPR_ADMIN_USER_GET_INFO)GetProcAddress(hMprDLL,"MprAdminUserGetInfo");
  1590. pMprAdminUserSetInfo = (MPR_ADMIN_USER_SET_INFO)GetProcAddress(hMprDLL,"MprAdminUserSetInfo");
  1591. if(pMprAdminUserGetInfo && pMprAdminUserSetInfo)
  1592. {
  1593. if(pMprAdminUserGetInfo( pServerName, pUserName, 1, (PBYTE) &ru1 ) == NO_ERROR )
  1594. {
  1595. pMprAdminUserSetInfo( pServerName, pUserName, 1, (PBYTE) &ru1 );
  1596. }
  1597. }
  1598. FreeLibrary(hMprDLL);
  1599. }
  1600. }
  1601. status = SamSetInformationUser( Handle,
  1602. UserParametersInformation,
  1603. (PVOID) &NewUserParmInfo );
  1604. KdPrint( ( "RegSAMUserConfig: NewUserParmInfo.Parameters.Length = %d\n" , NewUserParmInfo.Parameters.Length ) );
  1605. KdPrint( ( "RegSAMUserConfig: SamSetInformationUser returned NTSTATUS = 0x%x\n", status ) );
  1606. LocalFree( NewUserParmInfo.Parameters.Buffer );
  1607. if ( status != STATUS_SUCCESS )
  1608. {
  1609. goto cleanupoperation;
  1610. }
  1611. }
  1612. cleanupoperation:
  1613. if ( UserParmInfo ) {
  1614. SamFreeMemory( UserParmInfo );
  1615. }
  1616. cleanupsamquery:
  1617. if ( Handle != (SAM_HANDLE) 0 ) {
  1618. SamCloseHandle( Handle );
  1619. }
  1620. cleanupsamopen:
  1621. cleanuplookup:
  1622. if ( SAMHandle != (SAM_HANDLE) 0 ) {
  1623. SamCloseHandle( SAMHandle );
  1624. }
  1625. if ( DomainHandle != (SAM_HANDLE) 0 ) {
  1626. SamCloseHandle( DomainHandle );
  1627. }
  1628. if ( DomainID != (PSID) 0 ) {
  1629. SamFreeMemory( DomainID );
  1630. }
  1631. cleanupconnect:
  1632. if ( pDomainName ) {
  1633. NetApiBufferFree( pDomainName );
  1634. }
  1635. exit:
  1636. if (hNtdsApi)
  1637. {
  1638. if (hDS)
  1639. {
  1640. if ( pfnDsUnBindW ) // it should never be otherwise.
  1641. pfnDsUnBindW( & hDS );
  1642. }
  1643. if (pDsResult)
  1644. {
  1645. if (pfnDsFreeNameResultW ) // it should never be otherwise.
  1646. pfnDsFreeNameResultW( pDsResult );
  1647. }
  1648. FreeLibrary(hNtdsApi);
  1649. }
  1650. #ifdef DEBUG
  1651. DbgPrint( "RegSAMUserConfig %s NTSTATUS = 0x%x\n", fGetConfig ? "GET" : "SET", status );
  1652. #endif // DEBUG
  1653. return( RtlNtStatusToDosError( status ) );
  1654. }
  1655.