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.

3644 lines
80 KiB

  1. /*++
  2. Copyright (c) 1993-1995 Microsoft Corporation
  3. Module Name:
  4. NTNetaAPI.c
  5. Abstract:
  6. Author:
  7. Arthur Hanson (arth) 16-Jun-1994
  8. Revision History:
  9. --*/
  10. #include "globals.h"
  11. #include <ntlsa.h>
  12. #include <ntsam.h>
  13. #include <ntddnwfs.h>
  14. #include <align.h>
  15. #include <math.h>
  16. #include "convapi.h"
  17. #include "ntnetapi.h"
  18. #include "nwnetapi.h"
  19. #include "loghours.h"
  20. #include "usrprop.h"
  21. #include "crypt.h"
  22. // #include <nwstruct.h>
  23. #include <nwconv.h>
  24. #include "fpnwapi.h"
  25. #ifdef DEBUG
  26. int ErrorBoxRetry(LPTSTR szFormat, ...);
  27. #endif
  28. void ErrorIt(LPTSTR szFormat, ...);
  29. NTSTATUS ACEAdd( PSECURITY_DESCRIPTOR pSD, PSID pSid, ACCESS_MASK AccessMask, ULONG AceFlags, PSECURITY_DESCRIPTOR *ppNewSD );
  30. static LPTSTR LocalName = NULL;
  31. // +3 for leading slashes and ending NULL
  32. static TCHAR CachedServer[MAX_SERVER_NAME_LEN+3];
  33. static BOOL LocalMachine = FALSE;
  34. // keep this around so we don't have to keep re-do query
  35. static LPSERVER_INFO_101 ServInfo = NULL;
  36. // #define TYPE_DOMAIN SV_TYPE_DOMAIN_CTRL | SV_TYPE_DOMAIN_BAKCTRL | SV_TYPE_DOMAIN_MEMBER
  37. #define TYPE_DOMAIN SV_TYPE_DOMAIN_CTRL | SV_TYPE_DOMAIN_BAKCTRL
  38. static SAM_HANDLE SAMHandle = (SAM_HANDLE) 0;
  39. static SAM_HANDLE DomainHandle = (SAM_HANDLE) 0;
  40. static PSID DomainID;
  41. static WCHAR UserParms[1024];
  42. #define NCP_LSA_SECRET_KEY L"G$MNSEncryptionKey"
  43. #define NCP_LSA_SECRET_LENGTH USER_SESSION_KEY_LENGTH
  44. static char Secret[USER_SESSION_KEY_LENGTH];
  45. static HANDLE FPNWLib = NULL;
  46. static DWORD (FAR * NWVolumeAdd) (LPWSTR, DWORD, PNWVOLUMEINFO) = NULL;
  47. //
  48. // This bit is set when the server is running on a NTAS machine or
  49. // the object is from a trusted domain. NWConv is always on NTAS
  50. //
  51. #define BINDLIB_REMOTE_DOMAIN_BIAS 0x10000000
  52. //
  53. // misc macros that are useful
  54. //
  55. #define SWAPWORD(w) ((WORD)((w & 0xFF) << 8)|(WORD)(w >> 8))
  56. #define SWAPLONG(l) MAKELONG(SWAPWORD(HIWORD(l)),SWAPWORD(LOWORD(l)))
  57. typedef struct _NT_CONN_BUFFER {
  58. struct _NT_CONN_BUFFER *next;
  59. struct _NT_CONN_BUFFER *prev;
  60. LPTSTR Name;
  61. } NT_CONN_BUFFER;
  62. static NT_CONN_BUFFER *NTConnListStart = NULL;
  63. static NT_CONN_BUFFER *NTConnListEnd = NULL;
  64. HANDLE FpnwHandle = NULL;
  65. static FARPROC pFpnwVolumeEnum = NULL;
  66. static FARPROC pFpnwApiBufferFree = NULL;
  67. /////////////////////////////////////////////////////////////////////////
  68. LPSTR
  69. FPNWSecretGet(
  70. LPTSTR ServerName
  71. )
  72. /*++
  73. Routine Description:
  74. Checks the given machine for the FPNW secret.
  75. Arguments:
  76. Return Value:
  77. --*/
  78. {
  79. SECURITY_QUALITY_OF_SERVICE QualityOfService;
  80. OBJECT_ATTRIBUTES ObjectAttributes;
  81. LSA_HANDLE PolicyHandle;
  82. LSA_HANDLE SecretHandle;
  83. NTSTATUS Status;
  84. UNICODE_STRING UnicodeSecretName;
  85. PUNICODE_STRING punicodeCurrentValue;
  86. PUSER_INFO_2 pUserInfo = NULL;
  87. static TCHAR LocServer[MAX_SERVER_NAME_LEN+3];
  88. UNICODE_STRING UnicodeServerName;
  89. BOOL ret = TRUE;
  90. memset(Secret, 0, USER_SESSION_KEY_LENGTH);
  91. wsprintf(LocServer, TEXT("\\\\%s"), ServerName);
  92. // Verify & init secret name.
  93. RtlInitUnicodeString( &UnicodeSecretName, NCP_LSA_SECRET_KEY );
  94. RtlInitUnicodeString( &UnicodeServerName, LocServer);
  95. // Prepare to open the policy object.
  96. QualityOfService.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
  97. QualityOfService.ImpersonationLevel = SecurityImpersonation;
  98. QualityOfService.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  99. QualityOfService.EffectiveOnly = FALSE;
  100. InitializeObjectAttributes( &ObjectAttributes, NULL, 0L, NULL, NULL );
  101. ObjectAttributes.SecurityQualityOfService = &QualityOfService;
  102. // Open a handle to the target machine's LSA policy.
  103. Status = LsaOpenPolicy( &UnicodeServerName, &ObjectAttributes, 0, &PolicyHandle );
  104. if( !NT_SUCCESS( Status ) ) {
  105. ret = FALSE;
  106. goto FatalExit0;
  107. }
  108. // Open the secret object.
  109. Status = LsaOpenSecret( PolicyHandle, &UnicodeSecretName, SECRET_QUERY_VALUE, &SecretHandle );
  110. if( !NT_SUCCESS( Status ) ) {
  111. ret = FALSE;
  112. goto FatalExit1;
  113. }
  114. // Query the secret.
  115. Status = LsaQuerySecret( SecretHandle, &punicodeCurrentValue, NULL, NULL, NULL );
  116. if( !NT_SUCCESS( Status ) ) {
  117. ret = FALSE;
  118. goto FatalExit2;
  119. }
  120. if (punicodeCurrentValue != NULL) {
  121. memcpy(Secret, punicodeCurrentValue->Buffer, USER_SESSION_KEY_LENGTH);
  122. LsaFreeMemory( (PVOID)punicodeCurrentValue );
  123. }
  124. FatalExit2:
  125. LsaClose( SecretHandle );
  126. FatalExit1:
  127. LsaClose( PolicyHandle );
  128. FatalExit0:
  129. if (ret)
  130. return Secret;
  131. else
  132. return NULL;
  133. } // FPNWSecretGet
  134. /////////////////////////////////////////////////////////////////////////
  135. NTSTATUS
  136. SetGraceLoginAllowed(
  137. USHORT ushGraceLoginAllowed
  138. )
  139. /*++
  140. Routine Description:
  141. Store Grace Login Allowed in UserParms.
  142. Arguments:
  143. Return Value:
  144. --*/
  145. {
  146. NTSTATUS err = NERR_Success;
  147. USHORT ushTemp = ushGraceLoginAllowed;
  148. UNICODE_STRING uniGraceLoginAllowed;
  149. LPWSTR lpNewUserParms = NULL;
  150. BOOL fUpdate;
  151. uniGraceLoginAllowed.Buffer = &ushTemp;
  152. uniGraceLoginAllowed.Length = 2;
  153. uniGraceLoginAllowed.MaximumLength = 2;
  154. err = SetUserProperty (UserParms, GRACELOGINALLOWED, uniGraceLoginAllowed, USER_PROPERTY_TYPE_ITEM, &lpNewUserParms, &fUpdate);
  155. if ((err == NERR_Success) && (lpNewUserParms != NULL)) {
  156. if (fUpdate)
  157. lstrcpyW(UserParms, lpNewUserParms);
  158. LocalFree(lpNewUserParms);
  159. }
  160. return err;
  161. } // SetGraceLoginAllowed
  162. /////////////////////////////////////////////////////////////////////////
  163. NTSTATUS
  164. SetGraceLoginRemainingTimes(
  165. USHORT ushGraceLoginRemainingTimes
  166. )
  167. /*++
  168. Routine Description:
  169. Store Grace Login Remaining Times in UserParms. if ushGraceLogin is 0,
  170. "GraceLogin" field will be deleted from UserParms.
  171. Arguments:
  172. Return Value:
  173. --*/
  174. {
  175. NTSTATUS err = NERR_Success;
  176. USHORT ushTemp = ushGraceLoginRemainingTimes;
  177. UNICODE_STRING uniGraceLoginRemainingTimes;
  178. LPWSTR lpNewUserParms = NULL;
  179. BOOL fUpdate;
  180. uniGraceLoginRemainingTimes.Buffer = &ushTemp;
  181. uniGraceLoginRemainingTimes.Length = 2;
  182. uniGraceLoginRemainingTimes.MaximumLength = 2;
  183. err = SetUserProperty (UserParms, GRACELOGINREMAINING, uniGraceLoginRemainingTimes, USER_PROPERTY_TYPE_ITEM, &lpNewUserParms, &fUpdate);
  184. if ((err == NERR_Success) && (lpNewUserParms != NULL)) {
  185. if (fUpdate)
  186. lstrcpyW(UserParms, lpNewUserParms);
  187. LocalFree(lpNewUserParms);
  188. }
  189. return err;
  190. } // SetGraceLoginRemainingTimes
  191. /////////////////////////////////////////////////////////////////////////
  192. NTSTATUS
  193. SetMaxConnections(
  194. USHORT ushMaxConnections
  195. )
  196. /*++
  197. Routine Description:
  198. Store Maximum Concurret Connections in UserParms. If ushMaxConnections
  199. is 0xffff or 0, "MaxConnections" field will be deleted from UserParms,
  200. otherwise the value is stored.
  201. Arguments:
  202. Return Value:
  203. --*/
  204. {
  205. NTSTATUS err = NERR_Success;
  206. USHORT ushTemp = ushMaxConnections;
  207. UNICODE_STRING uniMaxConnections;
  208. LPWSTR lpNewUserParms = NULL;
  209. BOOL fUpdate;
  210. uniMaxConnections.Buffer = &ushMaxConnections;
  211. uniMaxConnections.Length = 2;
  212. uniMaxConnections.MaximumLength = 2;
  213. err = SetUserProperty (UserParms, MAXCONNECTIONS, uniMaxConnections, USER_PROPERTY_TYPE_ITEM, &lpNewUserParms, &fUpdate);
  214. if ((err == NERR_Success) && (lpNewUserParms != NULL)) {
  215. if (fUpdate)
  216. lstrcpyW(UserParms, lpNewUserParms);
  217. LocalFree(lpNewUserParms);
  218. }
  219. return err;
  220. } // SetMaxConnections
  221. /////////////////////////////////////////////////////////////////////////
  222. NTSTATUS
  223. SetNWPasswordAge(
  224. BOOL fExpired
  225. )
  226. /*++
  227. Routine Description:
  228. If fExpired is TRUE, set the NWPasswordSet field to be all fs.
  229. otherwise set it to be the current time.
  230. Arguments:
  231. Return Value:
  232. --*/
  233. {
  234. NTSTATUS err = NERR_Success;
  235. LARGE_INTEGER currentTime;
  236. LPWSTR lpNewUserParms = NULL;
  237. UNICODE_STRING uniPasswordAge;
  238. BOOL fUpdate;
  239. if (fExpired) {
  240. currentTime.HighPart = 0xffffffff;
  241. currentTime.LowPart = 0xffffffff;
  242. } else
  243. NtQuerySystemTime (&currentTime);
  244. uniPasswordAge.Buffer = (PWCHAR) &currentTime;
  245. uniPasswordAge.Length = sizeof (LARGE_INTEGER);
  246. uniPasswordAge.MaximumLength = sizeof (LARGE_INTEGER);
  247. err = SetUserProperty (UserParms, NWTIMEPASSWORDSET, uniPasswordAge, USER_PROPERTY_TYPE_ITEM, &lpNewUserParms, &fUpdate);
  248. if ((err == NERR_Success) &&(lpNewUserParms != NULL)) {
  249. if (fUpdate)
  250. lstrcpyW(UserParms, lpNewUserParms);
  251. LocalFree(lpNewUserParms);
  252. }
  253. return err;
  254. } // SetNWPasswordAge
  255. /////////////////////////////////////////////////////////////////////////
  256. NTSTATUS
  257. SetNWPassword(
  258. DWORD dwUserId,
  259. const TCHAR *pchNWPassword,
  260. BOOL ForcePasswordChange
  261. )
  262. /*++
  263. Routine Description:
  264. Set "NWPassword" field is fIsNetWareUser is TRUE, Otherwise, delete
  265. the field from UserParms.
  266. Arguments:
  267. Return Value:
  268. --*/
  269. {
  270. NTSTATUS err;
  271. TCHAR pchEncryptedNWPassword[NWENCRYPTEDPASSWORDLENGTH + 1];
  272. LPWSTR lpNewUserParms = NULL;
  273. BOOL fUpdate;
  274. UNICODE_STRING uniPassword;
  275. #ifdef DEBUG
  276. dprintf(TEXT("Set NetWare password: [%s]\r\n"), pchNWPassword);
  277. #endif
  278. do {
  279. // Now munge the UserID to the format required by ReturnNetwareForm...
  280. dwUserId |= BINDLIB_REMOTE_DOMAIN_BIAS;
  281. err = ReturnNetwareForm( Secret, dwUserId, pchNWPassword, (UCHAR *) pchEncryptedNWPassword );
  282. if ( err != NERR_Success )
  283. break;
  284. uniPassword.Buffer = pchEncryptedNWPassword;
  285. uniPassword.Length = NWENCRYPTEDPASSWORDLENGTH * sizeof (WCHAR);
  286. uniPassword.MaximumLength = NWENCRYPTEDPASSWORDLENGTH * sizeof (WCHAR);
  287. err = SetUserProperty (UserParms, NWPASSWORD, uniPassword, USER_PROPERTY_TYPE_ITEM, &lpNewUserParms, &fUpdate);
  288. if ((err == NERR_Success) && (lpNewUserParms != NULL)) {
  289. if (fUpdate)
  290. lstrcpyW(UserParms, lpNewUserParms);
  291. LocalFree(lpNewUserParms);
  292. if ((err = SetNWPasswordAge (ForcePasswordChange)) != NERR_Success )
  293. break;
  294. }
  295. } while (FALSE);
  296. return err;
  297. } // SetNWPassword
  298. /////////////////////////////////////////////////////////////////////////
  299. NTSTATUS
  300. SetNWWorkstations(
  301. const TCHAR * pchNWWorkstations
  302. )
  303. /*++
  304. Routine Description:
  305. Store NetWare allowed workstation addresses to UserParms. If
  306. pchNWWorkstations is NULL, this function will delete "NWLgonFrom"
  307. field from UserParms.
  308. Arguments:
  309. Return Value:
  310. --*/
  311. {
  312. NTSTATUS err = NERR_Success;
  313. UNICODE_STRING uniNWWorkstations;
  314. CHAR * pchTemp = NULL;
  315. LPWSTR lpNewUserParms = NULL;
  316. BOOL fUpdate;
  317. if (pchNWWorkstations == NULL) {
  318. uniNWWorkstations.Buffer = NULL;
  319. uniNWWorkstations.Length = 0;
  320. uniNWWorkstations.MaximumLength = 0;
  321. } else {
  322. BOOL fDummy;
  323. INT nStringLength = lstrlen(pchNWWorkstations) + 1;
  324. pchTemp = (CHAR *) LocalAlloc (LPTR, nStringLength);
  325. if ( pchTemp == NULL )
  326. err = ERROR_NOT_ENOUGH_MEMORY;
  327. if ( err == NERR_Success && !WideCharToMultiByte (CP_ACP, 0, pchNWWorkstations, nStringLength, pchTemp, nStringLength, NULL, &fDummy))
  328. err = GetLastError();
  329. if ( err == NERR_Success ) {
  330. uniNWWorkstations.Buffer = (WCHAR *) pchTemp;
  331. uniNWWorkstations.Length = (USHORT) nStringLength;
  332. uniNWWorkstations.MaximumLength = (USHORT) nStringLength;
  333. }
  334. }
  335. err = err? err: SetUserProperty (UserParms, NWLOGONFROM, uniNWWorkstations, USER_PROPERTY_TYPE_ITEM, &lpNewUserParms, &fUpdate);
  336. if ((err == NERR_Success) && (lpNewUserParms != NULL)) {
  337. if (fUpdate)
  338. lstrcpyW(UserParms, lpNewUserParms);
  339. LocalFree(lpNewUserParms);
  340. }
  341. if (pchTemp != NULL)
  342. LocalFree (pchTemp);
  343. return err;
  344. } // SetNWWorkstations
  345. /////////////////////////////////////////////////////////////////////////
  346. NTSTATUS SetNWHomeDir(
  347. const TCHAR * pchNWHomeDir
  348. )
  349. /*++
  350. Routine Description:
  351. Store NetWare Home Directory to UserParms If pchNWWorkstations is NULL,
  352. this function will delete "NWLgonFrom" field from UserParms.
  353. Arguments:
  354. Return Value:
  355. --*/
  356. {
  357. NTSTATUS err = NERR_Success;
  358. UNICODE_STRING uniNWHomeDir;
  359. CHAR * pchTemp = NULL;
  360. LPWSTR lpNewUserParms = NULL;
  361. BOOL fUpdate;
  362. if (pchNWHomeDir == NULL) {
  363. uniNWHomeDir.Buffer = NULL;
  364. uniNWHomeDir.Length = 0;
  365. uniNWHomeDir.MaximumLength = 0;
  366. } else {
  367. BOOL fDummy;
  368. INT nStringLength = lstrlen(pchNWHomeDir) + 1;
  369. pchTemp = (CHAR *) LocalAlloc (LPTR, nStringLength);
  370. if ( pchTemp == NULL )
  371. err = ERROR_NOT_ENOUGH_MEMORY;
  372. if ( err == NERR_Success && !WideCharToMultiByte (CP_ACP, 0, pchNWHomeDir, nStringLength, pchTemp, nStringLength, NULL, &fDummy))
  373. err = GetLastError();
  374. if ( err == NERR_Success ) {
  375. uniNWHomeDir.Buffer = (WCHAR *) pchTemp;
  376. uniNWHomeDir.Length = (USHORT) nStringLength;
  377. uniNWHomeDir.MaximumLength = (USHORT) nStringLength;
  378. }
  379. }
  380. err = err? err : SetUserProperty (UserParms, NWHOMEDIR, uniNWHomeDir, USER_PROPERTY_TYPE_ITEM, &lpNewUserParms, &fUpdate);
  381. if ((err == NERR_Success) && (lpNewUserParms != NULL)) {
  382. if (fUpdate)
  383. lstrcpyW(UserParms, lpNewUserParms);
  384. LocalFree(lpNewUserParms);
  385. }
  386. if (pchTemp != NULL)
  387. LocalFree (pchTemp);
  388. return err;
  389. } // SetNWHomeDir
  390. /////////////////////////////////////////////////////////////////////////
  391. DWORD
  392. NTObjectIDGet(
  393. LPTSTR ObjectName
  394. )
  395. /*++
  396. Routine Description:
  397. Arguments:
  398. Return Value:
  399. --*/
  400. {
  401. NTSTATUS status;
  402. UNICODE_STRING UniNewObjectName;
  403. PULONG pRids = NULL;
  404. PSID_NAME_USE pSidNameUse = NULL;
  405. ULONG ObjectID = 0;
  406. RtlInitUnicodeString(&UniNewObjectName, ObjectName);
  407. status = SamLookupNamesInDomain(DomainHandle,
  408. 1,
  409. &UniNewObjectName,
  410. &pRids,
  411. &pSidNameUse);
  412. if ((status == STATUS_SUCCESS) && (pRids != NULL) && (pSidNameUse != NULL)) {
  413. // Found the name - so copy and free SAM garbage
  414. ObjectID = pRids[0];
  415. ObjectID |= BINDLIB_REMOTE_DOMAIN_BIAS;
  416. SamFreeMemory(pRids);
  417. SamFreeMemory(pSidNameUse);
  418. }
  419. return ObjectID;
  420. } // NTObjectIDGet
  421. /////////////////////////////////////////////////////////////////////////
  422. DWORD
  423. NTSAMParmsSet(
  424. LPTSTR ObjectName,
  425. FPNW_INFO fpnw,
  426. LPTSTR Password,
  427. BOOL ForcePasswordChange
  428. )
  429. /*++
  430. Routine Description:
  431. Arguments:
  432. Return Value:
  433. --*/
  434. {
  435. NTSTATUS status;
  436. UNICODE_STRING UniNewObjectName;
  437. PULONG pRids = NULL;
  438. PSID_NAME_USE pSidNameUse = NULL;
  439. ULONG ObjectID;
  440. SID_NAME_USE SidNameUse;
  441. SAM_HANDLE Handle = (SAM_HANDLE) 0;
  442. PUSER_PARAMETERS_INFORMATION UserParmInfo = NULL;
  443. USER_PARAMETERS_INFORMATION NewUserParmInfo;
  444. LPWSTR lpNewUserParms = NULL;
  445. RtlInitUnicodeString(&UniNewObjectName, ObjectName);
  446. status = SamLookupNamesInDomain(DomainHandle,
  447. 1,
  448. &UniNewObjectName,
  449. &pRids,
  450. &pSidNameUse);
  451. if ((status == STATUS_SUCCESS) && (pRids != NULL) && (pSidNameUse != NULL)) {
  452. // Found the name - so copy and free SAM garbage
  453. ObjectID = pRids[0];
  454. SidNameUse = pSidNameUse[0];
  455. SamFreeMemory(pRids);
  456. SamFreeMemory(pSidNameUse);
  457. status = SamOpenUser(DomainHandle,
  458. STANDARD_RIGHTS_READ |
  459. STANDARD_RIGHTS_WRITE |
  460. USER_ALL_ACCESS,
  461. ObjectID,
  462. &Handle);
  463. // Now get the user parms
  464. if (status == STATUS_SUCCESS)
  465. status = SamQueryInformationUser(Handle, UserParametersInformation, (PVOID *) &UserParmInfo);
  466. memset(UserParms, 0, sizeof(UserParms));
  467. if ((status == STATUS_SUCCESS) && (UserParmInfo != NULL)) {
  468. memcpy(UserParms, UserParmInfo->Parameters.Buffer, UserParmInfo->Parameters.Length * sizeof(WCHAR));
  469. SamFreeMemory(UserParmInfo);
  470. if (
  471. ((status = SetNWPassword (ObjectID, Password, ForcePasswordChange)) == NERR_Success) &&
  472. ((status = SetMaxConnections (fpnw.MaxConnections)) == NERR_Success) &&
  473. ((status = SetGraceLoginAllowed (fpnw.GraceLoginAllowed)) == NERR_Success) &&
  474. ((status = SetGraceLoginRemainingTimes (fpnw.GraceLoginRemaining)) == NERR_Success) &&
  475. ((status = SetNWWorkstations (fpnw.LoginFrom)) == NERR_Success) &&
  476. ((status = SetNWHomeDir (fpnw.HomeDir)) == NERR_Success) )
  477. {
  478. RtlInitUnicodeString(&NewUserParmInfo.Parameters, UserParms);
  479. status = SamSetInformationUser(Handle, UserParametersInformation, (PVOID) &NewUserParmInfo);
  480. }
  481. }
  482. }
  483. if (Handle != (SAM_HANDLE) 0)
  484. SamCloseHandle(Handle);
  485. return 0;
  486. } // NTSAMParmsSet
  487. /////////////////////////////////////////////////////////////////////////
  488. DWORD
  489. NTSAMConnect(
  490. LPTSTR ServerName,
  491. LPTSTR DomainName
  492. )
  493. /*++
  494. Routine Description:
  495. Arguments:
  496. Return Value:
  497. --*/
  498. {
  499. NTSTATUS status;
  500. OBJECT_ATTRIBUTES object_attrib;
  501. UNICODE_STRING UniDomainName;
  502. UNICODE_STRING UniServerName;
  503. //
  504. // Do all the garbage for connecting to SAM
  505. //
  506. RtlInitUnicodeString(&UniServerName, ServerName);
  507. RtlInitUnicodeString(&UniDomainName, DomainName);
  508. InitializeObjectAttributes(&object_attrib, NULL, 0, NULL, NULL);
  509. status = SamConnect(&UniServerName, &SAMHandle, SAM_SERVER_ALL_ACCESS, &object_attrib);
  510. if (status == STATUS_SUCCESS)
  511. status = SamLookupDomainInSamServer(SAMHandle, &UniDomainName, &DomainID);
  512. if (status == STATUS_SUCCESS)
  513. status = SamOpenDomain(SAMHandle, DOMAIN_ALL_ACCESS, DomainID, &DomainHandle);
  514. FPNWSecretGet(ServerName);
  515. return (DWORD) status;
  516. } // NTSAMConnect
  517. /////////////////////////////////////////////////////////////////////////
  518. VOID
  519. NTSAMClose()
  520. /*++
  521. Routine Description:
  522. Arguments:
  523. Return Value:
  524. --*/
  525. {
  526. if (DomainHandle != (SAM_HANDLE) 0)
  527. SamCloseHandle(DomainHandle);
  528. if (DomainID != (PSID) 0)
  529. SamFreeMemory(DomainID);
  530. if (SAMHandle != (SAM_HANDLE) 0)
  531. SamCloseHandle(SAMHandle);
  532. SAMHandle = (SAM_HANDLE) 0;
  533. DomainHandle = (SAM_HANDLE) 0;
  534. DomainID = (PSID) 0;
  535. } // NTSAMClose
  536. /////////////////////////////////////////////////////////////////////////
  537. DWORD
  538. NTServerSet(
  539. LPTSTR ServerName
  540. )
  541. /*++
  542. Routine Description:
  543. Arguments:
  544. Return Value:
  545. --*/
  546. {
  547. // Fixup the destination server name
  548. lstrcpy(CachedServer, TEXT("\\\\"));
  549. lstrcat(CachedServer, ServerName);
  550. if (!LocalName)
  551. GetLocalName(&LocalName);
  552. if (lstrcmpi(ServerName, LocalName) == 0)
  553. LocalMachine = TRUE;
  554. else
  555. LocalMachine = FALSE;
  556. if (FpnwHandle == NULL)
  557. FpnwHandle = LoadLibrary(TEXT("FPNWCLNT.DLL"));
  558. if ((FpnwHandle != NULL) && (pFpnwVolumeEnum == NULL)) {
  559. pFpnwVolumeEnum = GetProcAddress(FpnwHandle, ("FpnwVolumeEnum"));
  560. pFpnwApiBufferFree = GetProcAddress(FpnwHandle, ("FpnwApiBufferFree"));
  561. }
  562. return (0);
  563. } // NTServerSet
  564. /////////////////////////////////////////////////////////////////////////
  565. DWORD
  566. NTServerFree()
  567. /*++
  568. Routine Description:
  569. Arguments:
  570. Return Value:
  571. --*/
  572. {
  573. LocalMachine = FALSE;
  574. lstrcpy(CachedServer, TEXT(""));
  575. return (0);
  576. } // NTServerFree
  577. /////////////////////////////////////////////////////////////////////////
  578. DWORD
  579. FPNWShareAdd(
  580. LPTSTR ShareName,
  581. LPTSTR Path
  582. )
  583. /*++
  584. Routine Description:
  585. Arguments:
  586. Return Value:
  587. --*/
  588. {
  589. NET_API_STATUS Status = 0;
  590. NWVOLUMEINFO NWVol;
  591. if (FPNWLib == NULL)
  592. FPNWLib = LoadLibrary(TEXT("FPNWCLNT.DLL"));
  593. if (FPNWLib == NULL)
  594. return 1;
  595. if (NWVolumeAdd == NULL)
  596. NWVolumeAdd = (DWORD (FAR * ) (LPWSTR, DWORD, PNWVOLUMEINFO)) GetProcAddress(FPNWLib, "NwVolumeAdd");
  597. NWVol.lpVolumeName = AllocMemory((lstrlen(ShareName) + 1) * sizeof(TCHAR));
  598. NWVol.lpPath = AllocMemory((lstrlen(Path) + 1) * sizeof(TCHAR));
  599. if ((NWVol.lpVolumeName == NULL) || (NWVol.lpPath == NULL))
  600. return 1;
  601. lstrcpy(NWVol.lpVolumeName, ShareName);
  602. NWVol.dwType = NWVOL_TYPE_DISKTREE;
  603. NWVol.dwMaxUses = NWVOL_MAX_USES_UNLIMITED;
  604. NWVol.dwCurrentUses = 0;
  605. lstrcpy(NWVol.lpPath, Path);
  606. if (LocalMachine)
  607. Status = NWVolumeAdd(NULL, 1, &NWVol);
  608. else
  609. Status = NWVolumeAdd(CachedServer, 1, &NWVol);
  610. return Status;
  611. } // FPNWShareAdd
  612. /////////////////////////////////////////////////////////////////////////
  613. DWORD
  614. NTShareAdd(
  615. LPTSTR ShareName,
  616. LPTSTR Path
  617. )
  618. /*++
  619. Routine Description:
  620. Arguments:
  621. Return Value:
  622. --*/
  623. {
  624. NET_API_STATUS Status = 0;
  625. SHARE_INFO_2 shi2;
  626. DWORD parmerr;
  627. memset(&shi2, 0, sizeof(SHARE_INFO_2));
  628. shi2.shi2_netname = ShareName;
  629. shi2.shi2_type = STYPE_DISKTREE;
  630. shi2.shi2_max_uses = (DWORD) 0xffffffff;
  631. shi2.shi2_path = Path;
  632. if (LocalMachine)
  633. Status = NetShareAdd(NULL, 2, (LPBYTE) &shi2, &parmerr);
  634. else
  635. Status = NetShareAdd(CachedServer, 2, (LPBYTE) &shi2, &parmerr);
  636. return Status;
  637. } // NTShareAdd
  638. /////////////////////////////////////////////////////////////////////////
  639. DWORD
  640. NTUsersEnum(
  641. USER_LIST **lpUserList
  642. )
  643. /*++
  644. Routine Description:
  645. Arguments:
  646. Return Value:
  647. --*/
  648. {
  649. LPUSER_INFO_0 buffer = NULL;
  650. NET_API_STATUS Status = 0;
  651. DWORD prefmaxlength = 0xffffffff;
  652. DWORD totalentries = 0;
  653. DWORD entriesread = 0;
  654. DWORD resumehandle = 0;
  655. DWORD i;
  656. USER_LIST *UserList = NULL;
  657. USER_BUFFER *UserBuffer = NULL;
  658. if (LocalMachine)
  659. Status = NetUserEnum(NULL, 0, 0, (LPBYTE *) &buffer, prefmaxlength, &entriesread, &totalentries, &resumehandle);
  660. else
  661. Status = NetUserEnum(CachedServer, 0, 0, (LPBYTE *) &buffer, prefmaxlength, &entriesread, &totalentries, &resumehandle);
  662. if (Status == NO_ERROR) {
  663. UserList = AllocMemory(sizeof(USER_LIST) + (sizeof(USER_BUFFER) * entriesread));
  664. if (!UserList) {
  665. Status = ERROR_NOT_ENOUGH_MEMORY;
  666. } else {
  667. UserBuffer = UserList->UserBuffer;
  668. for (i = 0; i < entriesread; i++) {
  669. lstrcpy(UserBuffer[i].Name, buffer[i].usri0_name);
  670. lstrcpy(UserBuffer[i].NewName, buffer[i].usri0_name);
  671. }
  672. qsort((void *) UserBuffer, (size_t) entriesread, sizeof(USER_BUFFER), UserListCompare);
  673. }
  674. }
  675. if (buffer != NULL)
  676. NetApiBufferFree((LPVOID) buffer);
  677. if (UserList != NULL)
  678. UserList->Count = entriesread;
  679. *lpUserList = UserList;
  680. return Status;
  681. } // NTUsersEnum
  682. /////////////////////////////////////////////////////////////////////////
  683. DWORD
  684. NTGroupsEnum(
  685. GROUP_LIST **lpGroupList
  686. )
  687. /*++
  688. Routine Description:
  689. Arguments:
  690. Return Value:
  691. --*/
  692. {
  693. LPGROUP_INFO_0 buffer = NULL;
  694. NET_API_STATUS Status = 0;
  695. DWORD prefmaxlength = 0xffffffff;
  696. DWORD totalentries = 0;
  697. DWORD entriesread = 0;
  698. DWORD_PTR resumehandle = 0;
  699. DWORD i;
  700. GROUP_LIST *GroupList = NULL;
  701. GROUP_BUFFER *GroupBuffer = NULL;
  702. if (LocalMachine)
  703. Status = NetGroupEnum(NULL, 0, (LPBYTE *) &buffer, prefmaxlength, &entriesread, &totalentries, &resumehandle);
  704. else
  705. Status = NetGroupEnum(CachedServer, 0, (LPBYTE *) &buffer, prefmaxlength, &entriesread, &totalentries, &resumehandle);
  706. if (Status == NO_ERROR) {
  707. GroupList = AllocMemory(sizeof(GROUP_LIST) + (sizeof(GROUP_BUFFER) * entriesread));
  708. if (!GroupList) {
  709. Status = ERROR_NOT_ENOUGH_MEMORY;
  710. } else {
  711. GroupBuffer = GroupList->GroupBuffer;
  712. for (i = 0; i < entriesread; i++) {
  713. lstrcpy(GroupBuffer[i].Name, buffer[i].grpi0_name);
  714. lstrcpy(GroupBuffer[i].NewName, buffer[i].grpi0_name);
  715. }
  716. }
  717. }
  718. if (buffer != NULL)
  719. NetApiBufferFree((LPVOID) buffer);
  720. if (GroupList != NULL)
  721. GroupList->Count = entriesread;
  722. *lpGroupList = GroupList;
  723. return Status;
  724. } // NTGroupsEnum
  725. /////////////////////////////////////////////////////////////////////////
  726. DWORD
  727. NTDomainEnum(
  728. SERVER_BROWSE_LIST **lpServList
  729. )
  730. /*++
  731. Routine Description:
  732. Enumerates all NT servers in a given domain.
  733. Arguments:
  734. Return Value:
  735. --*/
  736. {
  737. LPSERVER_INFO_101 buffer = NULL;
  738. NET_API_STATUS Status = 0;
  739. DWORD prefmaxlength = 0xffffffff;
  740. DWORD totalentries = 0;
  741. DWORD entriesread = 0;
  742. DWORD resumehandle = 0;
  743. DWORD i;
  744. BOOL Container = FALSE;
  745. SERVER_BROWSE_LIST *ServList = NULL;
  746. SERVER_BROWSE_BUFFER *SList;
  747. Status = NetServerEnum(NULL, 101, (LPBYTE *) &buffer, prefmaxlength, &entriesread, &totalentries, SV_TYPE_DOMAIN_ENUM, NULL, &resumehandle);
  748. if (Status == NO_ERROR) {
  749. ServList = AllocMemory(sizeof(SERVER_BROWSE_LIST) + (sizeof(SERVER_BROWSE_BUFFER) * entriesread));
  750. if (!ServList) {
  751. Status = ERROR_NOT_ENOUGH_MEMORY;
  752. } else {
  753. ServList->Count = entriesread;
  754. SList = (SERVER_BROWSE_BUFFER *) &ServList->SList;
  755. for (i = 0; i < entriesread; i++) {
  756. lstrcpy(SList[i].Name, buffer[i].sv101_name);
  757. lstrcpy(SList[i].Description, buffer[i].sv101_comment);
  758. SList[i].Container = FALSE;
  759. SList[i].child = NULL;
  760. }
  761. }
  762. }
  763. if (buffer != NULL)
  764. NetApiBufferFree((LPVOID) buffer);
  765. *lpServList = ServList;
  766. return Status;
  767. } // NTDomainEnum
  768. /////////////////////////////////////////////////////////////////////////
  769. DWORD
  770. NTServerEnum(
  771. LPTSTR szContainer,
  772. SERVER_BROWSE_LIST **lpServList
  773. )
  774. /*++
  775. Routine Description:
  776. Enumerates all NT servers in a given domain.
  777. Arguments:
  778. Return Value:
  779. --*/
  780. {
  781. LPSERVER_INFO_101 buffer = NULL;
  782. NET_API_STATUS Status = 0;
  783. DWORD prefmaxlength = 0xffffffff;
  784. DWORD totalentries = 0;
  785. DWORD entriesread = 0;
  786. DWORD resumehandle = 0;
  787. DWORD i;
  788. BOOL Container = FALSE;
  789. SERVER_BROWSE_LIST *ServList = NULL;
  790. SERVER_BROWSE_BUFFER *SList;
  791. if (((szContainer != NULL) && (lstrlen(szContainer))))
  792. Container = TRUE;
  793. if (Container)
  794. Status = NetServerEnum(NULL, 101, (LPBYTE *) &buffer, prefmaxlength, &entriesread, &totalentries, SV_TYPE_NT, szContainer, &resumehandle);
  795. else
  796. Status = NetServerEnum(NULL, 101, (LPBYTE *) &buffer, prefmaxlength, &entriesread, &totalentries, SV_TYPE_DOMAIN_ENUM, NULL, &resumehandle);
  797. if (Status == NO_ERROR) {
  798. ServList = AllocMemory(sizeof(SERVER_BROWSE_LIST) + (sizeof(SERVER_BROWSE_BUFFER) * entriesread));
  799. if (!ServList) {
  800. Status = ERROR_NOT_ENOUGH_MEMORY;
  801. } else {
  802. ServList->Count = entriesread;
  803. SList = (SERVER_BROWSE_BUFFER *) &ServList->SList;
  804. for (i = 0; i < entriesread; i++) {
  805. lstrcpy(SList[i].Name, buffer[i].sv101_name);
  806. lstrcpy(SList[i].Description, buffer[i].sv101_comment);
  807. SList[i].Container = !Container;
  808. SList[i].child = NULL;
  809. }
  810. }
  811. }
  812. if (buffer != NULL)
  813. NetApiBufferFree((LPVOID) buffer);
  814. *lpServList = ServList;
  815. return Status;
  816. } // NTServerEnum
  817. /////////////////////////////////////////////////////////////////////////
  818. BOOL
  819. NTShareNameValidate(
  820. LPTSTR szShareName
  821. )
  822. /*++
  823. Routine Description:
  824. Arguments:
  825. Return Value:
  826. --*/
  827. {
  828. TCHAR *ptr = szShareName;
  829. BOOL ret;
  830. ret = TRUE;
  831. if (*ptr) {
  832. // go to end
  833. while (*ptr)
  834. ptr++;
  835. // now back up to last character
  836. ptr--;
  837. if (*ptr == TEXT('$')) // for ADMIN$, IPC$, etc...
  838. ret = FALSE;
  839. } else
  840. // Don't allow zero length - not sure why we would ever get these...
  841. ret = FALSE;
  842. return ret;
  843. } // NTShareNameValidate
  844. /////////////////////////////////////////////////////////////////////////
  845. DWORD
  846. NTSharesEnum(
  847. SHARE_LIST **lpShares,
  848. DRIVE_LIST *Drives
  849. )
  850. /*++
  851. Routine Description:
  852. Arguments:
  853. Return Value:
  854. --*/
  855. {
  856. LPSHARE_INFO_2 buffer = NULL;
  857. NET_API_STATUS Status = 0;
  858. DWORD prefmaxlength = 0xffffffff;
  859. DWORD totalentries = 0;
  860. DWORD entriesread = 0;
  861. DWORD ActualEntries = 0;
  862. DWORD resumehandle = 0;
  863. DWORD i, di;
  864. SHARE_LIST *ShareList = NULL;
  865. SHARE_BUFFER *SList;
  866. DRIVE_BUFFER *DList;
  867. ULONG TotalDrives;
  868. TCHAR Drive[2];
  869. PFPNWVOLUMEINFO VolumeInfo, VolumeEntry;
  870. BOOL Found;
  871. if (LocalMachine)
  872. Status = NetShareEnum(NULL, 2, (LPBYTE *) &buffer, prefmaxlength, &entriesread, &totalentries, &resumehandle);
  873. else
  874. Status = NetShareEnum(CachedServer, 2, (LPBYTE *) &buffer, prefmaxlength, &entriesread, &totalentries, &resumehandle);
  875. if (Status == NO_ERROR) {
  876. // We have the list - but need to prune out IPC$, Admin$, etc...
  877. for (i = 0; i < entriesread; i++)
  878. if ((buffer[i].shi2_type == STYPE_DISKTREE) && NTShareNameValidate(buffer[i].shi2_netname))
  879. ActualEntries++;
  880. ShareList = AllocMemory(sizeof(SHARE_LIST) + (sizeof(SHARE_BUFFER) * ActualEntries));
  881. if (!ShareList) {
  882. Status = ERROR_NOT_ENOUGH_MEMORY;
  883. } else {
  884. SList = (SHARE_BUFFER *) &ShareList->SList;
  885. ShareList->Count = ActualEntries;
  886. ActualEntries = 0;
  887. TotalDrives = 0;
  888. Drive[1] = TEXT('\0');
  889. if (Drives != NULL) {
  890. DList = Drives->DList;
  891. TotalDrives = Drives->Count;
  892. }
  893. // loop through copying the data
  894. for (i = 0; i < entriesread; i++)
  895. if ((buffer[i].shi2_type == STYPE_DISKTREE) && NTShareNameValidate(buffer[i].shi2_netname)) {
  896. lstrcpy(SList[ActualEntries].Name, buffer[i].shi2_netname);
  897. lstrcpy(SList[ActualEntries].Path, buffer[i].shi2_path);
  898. SList[ActualEntries].Index = (USHORT) ActualEntries;
  899. // Scan drive list looking for match to share path
  900. for (di = 0; di < TotalDrives; di++) {
  901. // Get first char from path - should be drive letter
  902. Drive[0] = *buffer[i].shi2_path;
  903. if (!lstrcmpi(Drive, DList[di].Drive))
  904. SList[ActualEntries].Drive = &DList[di];
  905. }
  906. ActualEntries++;
  907. }
  908. }
  909. }
  910. //
  911. // Now loop through any FPNW shares and tack those on as well
  912. //
  913. VolumeInfo = NULL;
  914. resumehandle = entriesread = 0;
  915. if (pFpnwVolumeEnum != NULL)
  916. if (LocalMachine)
  917. Status = (ULONG) (*pFpnwVolumeEnum) ( NULL, 1, (LPBYTE *)&VolumeInfo, &entriesread, &resumehandle );
  918. else
  919. Status = (ULONG) (*pFpnwVolumeEnum) ( CachedServer, 1, (LPBYTE *)&VolumeInfo, &entriesread, &resumehandle );
  920. #if DBG
  921. dprintf(TEXT("Status: 0x%lX Entries: %lu\n"), Status, entriesread);
  922. #endif
  923. if ( !Status && entriesread ) {
  924. if (ShareList)
  925. ShareList = ReallocMemory(ShareList, sizeof(SHARE_LIST) + (sizeof(SHARE_BUFFER) * (ActualEntries + entriesread)));
  926. else
  927. ShareList = AllocMemory(sizeof(SHARE_LIST) + (sizeof(SHARE_BUFFER) * entriesread));
  928. if (!ShareList) {
  929. Status = ERROR_NOT_ENOUGH_MEMORY;
  930. } else {
  931. SList = (SHARE_BUFFER *) &ShareList->SList; // reset pointer...
  932. // loop through copying the data
  933. for (i = 0; i < entriesread; i++) {
  934. //
  935. // Make sure not in NT Share list already
  936. //
  937. Found = FALSE;
  938. for (di = 0; di < ShareList->Count; di++)
  939. if (!lstrcmpi(SList[di].Name, VolumeInfo[i].lpVolumeName))
  940. Found = TRUE;
  941. if ((!Found) && (VolumeInfo[i].dwType == FPNWVOL_TYPE_DISKTREE) ) {
  942. lstrcpy(SList[ActualEntries].Name, VolumeInfo[i].lpVolumeName);
  943. lstrcpy(SList[ActualEntries].Path, VolumeInfo[i].lpPath);
  944. SList[ActualEntries].Index = (USHORT) ActualEntries;
  945. // Scan drive list looking for match to share path
  946. for (di = 0; di < TotalDrives; di++) {
  947. // Get first char from path - should be drive letter
  948. Drive[0] = *VolumeInfo[i].lpPath;
  949. if (!lstrcmpi(Drive, DList[di].Drive))
  950. SList[ActualEntries].Drive = &DList[di];
  951. }
  952. ActualEntries++;
  953. }
  954. }
  955. }
  956. }
  957. if (ShareList)
  958. ShareList->Count = ActualEntries;
  959. if (VolumeInfo && (pFpnwApiBufferFree != NULL))
  960. (*pFpnwApiBufferFree) ( VolumeInfo );
  961. if (buffer != NULL)
  962. NetApiBufferFree((LPVOID) buffer);
  963. *lpShares = ShareList;
  964. return Status;
  965. } // NTSharesEnum
  966. /////////////////////////////////////////////////////////////////////////
  967. DWORD
  968. NTGroupSave(
  969. LPTSTR Name
  970. )
  971. /*++
  972. Routine Description:
  973. Arguments:
  974. Return Value:
  975. --*/
  976. {
  977. static NET_API_STATUS Status = 0;
  978. GROUP_INFO_0 grpi0;
  979. DWORD err;
  980. grpi0.grpi0_name = Name;
  981. if (LocalMachine)
  982. Status = NetGroupAdd(NULL, 0, (LPBYTE) &grpi0, &err);
  983. else {
  984. Status = NetGroupAdd(CachedServer, 0, (LPBYTE) &grpi0, &err);
  985. }
  986. return Status;
  987. } // NTGroupSave
  988. /////////////////////////////////////////////////////////////////////////
  989. DWORD
  990. NTGroupUserAdd(
  991. LPTSTR GroupName,
  992. LPTSTR UserName,
  993. BOOL Local
  994. )
  995. /*++
  996. Routine Description:
  997. Arguments:
  998. Return Value:
  999. --*/
  1000. {
  1001. NET_API_STATUS Status = 0;
  1002. SID *pUserSID = NULL;
  1003. if (LocalMachine)
  1004. if (Local) {
  1005. pUserSID = NTSIDGet(NULL, UserName);
  1006. if (pUserSID != NULL)
  1007. Status = NetLocalGroupAddMember(NULL, GroupName, pUserSID);
  1008. } else
  1009. Status = NetGroupAddUser(NULL, GroupName, UserName);
  1010. else {
  1011. if (Local) {
  1012. pUserSID = NTSIDGet(CachedServer, UserName);
  1013. if (pUserSID != NULL)
  1014. Status = NetLocalGroupAddMember(CachedServer, GroupName, pUserSID);
  1015. } else
  1016. Status = NetGroupAddUser(CachedServer, GroupName, UserName);
  1017. }
  1018. // If complaining because user is already there, ignore
  1019. if (Status == NERR_UserInGroup)
  1020. Status = 0;
  1021. return Status;
  1022. } // NTGroupUserAdd
  1023. /////////////////////////////////////////////////////////////////////////
  1024. DWORD
  1025. NTUserInfoSave(
  1026. NT_USER_INFO *NT_UInfo,
  1027. PFPNW_INFO fpnw
  1028. )
  1029. /*++
  1030. Routine Description:
  1031. Arguments:
  1032. Return Value:
  1033. --*/
  1034. {
  1035. static NET_API_STATUS Status = 0;
  1036. struct _USER_INFO_3 *usri3;
  1037. DWORD err;
  1038. usri3 = (struct _USER_INFO_3 *) NT_UInfo;
  1039. // Map logon hours to GMT time - as NetAPI re-fixes it
  1040. NetpRotateLogonHours(NT_UInfo->logon_hours, UNITS_PER_WEEK, TRUE);
  1041. if (LocalMachine)
  1042. Status = NetUserAdd(NULL, 3, (LPBYTE) usri3, &err);
  1043. else
  1044. Status = NetUserAdd(CachedServer, 3, (LPBYTE) usri3, &err);
  1045. if ((!Status) && (fpnw != NULL)) {
  1046. // Need to get user info via LSA call before calling setuserparms
  1047. }
  1048. return Status;
  1049. } // NTUserInfoSave
  1050. #define NEW_NULL_PASSWD TEXT(" ")
  1051. /////////////////////////////////////////////////////////////////////////
  1052. DWORD
  1053. NTUserInfoSet(
  1054. NT_USER_INFO *NT_UInfo,
  1055. PFPNW_INFO fpnw
  1056. )
  1057. /*++
  1058. Routine Description:
  1059. Arguments:
  1060. Return Value:
  1061. --*/
  1062. {
  1063. LPWSTR Password;
  1064. LPWSTR Name;
  1065. static NET_API_STATUS Status = 0;
  1066. struct _USER_INFO_3 *usri3;
  1067. DWORD err;
  1068. // Tell it not to replace the password
  1069. Password = NT_UInfo->password;
  1070. NT_UInfo->password = NULL;
  1071. Name = NT_UInfo->name;
  1072. usri3 = (struct _USER_INFO_3 *) NT_UInfo;
  1073. // Map logon hours to GMT time - as NetAPI re-fixes it
  1074. NetpRotateLogonHours(NT_UInfo->logon_hours, UNITS_PER_WEEK, TRUE);
  1075. if (LocalMachine)
  1076. Status = NetUserSetInfo(NULL, Name, 3, (LPBYTE) usri3, &err);
  1077. else
  1078. Status = NetUserSetInfo(CachedServer, Name, 3, (LPBYTE) usri3, &err);
  1079. if ((!Status) && (fpnw != NULL)) {
  1080. }
  1081. // Reset the password in our data structure.
  1082. NT_UInfo->password = Password;
  1083. return Status;
  1084. } // NTUserInfoSet
  1085. /////////////////////////////////////////////////////////////////////////
  1086. VOID
  1087. NTUserRecInit(
  1088. LPTSTR UserName,
  1089. NT_USER_INFO *NT_UInfo
  1090. )
  1091. /*++
  1092. Routine Description:
  1093. Initializes a user record, uses static variables for string holders
  1094. so is not re-entrant, and will overwrite previous records data if
  1095. called again.
  1096. Arguments:
  1097. Return Value:
  1098. --*/
  1099. {
  1100. static TCHAR uname[UNLEN + 1];
  1101. static TCHAR upassword[ENCRYPTED_PWLEN];
  1102. static TCHAR uhomedir[PATHLEN + 1];
  1103. static TCHAR ucomment[MAXCOMMENTSZ + 1];
  1104. static TCHAR uscriptpath[PATHLEN + 1];
  1105. static TCHAR ufullname[MAXCOMMENTSZ + 1];
  1106. static TCHAR uucomment[MAXCOMMENTSZ + 1];
  1107. static TCHAR uparms[MAXCOMMENTSZ + 1];
  1108. static TCHAR uworkstations[1];
  1109. static BYTE ulogonhours[21];
  1110. static TCHAR ulogonserver[1];
  1111. static TCHAR uprofile[1];
  1112. static TCHAR uhome_dir_drive[1];
  1113. // init all the static data holders.
  1114. memset(uname, 0, sizeof( uname ));
  1115. lstrcpy(uname, UserName);
  1116. memset(upassword, 0, sizeof( upassword ));
  1117. memset(uhomedir, 0, sizeof( uhomedir ));
  1118. memset(ucomment, 0, sizeof( ucomment ));
  1119. memset(uscriptpath, 0, sizeof( uscriptpath ));
  1120. memset(ufullname, 0, sizeof( ufullname ));
  1121. memset(uucomment, 0, sizeof( uucomment ));
  1122. memset(uparms, 0, sizeof( uparms ));
  1123. memset(uworkstations, 0, sizeof( uworkstations ));
  1124. memset(ulogonhours, 0, sizeof( ulogonhours ));
  1125. memset(ulogonserver, 0, sizeof( ulogonserver ));
  1126. memset(uprofile, 0, sizeof( uprofile ));
  1127. memset(uhome_dir_drive, 0, sizeof( uhome_dir_drive ));
  1128. memset(NT_UInfo, 0, sizeof(NT_USER_INFO));
  1129. // point the passed in record to these data holders
  1130. NT_UInfo->name = uname;
  1131. NT_UInfo->password = upassword;
  1132. NT_UInfo->home_dir = uhomedir;
  1133. NT_UInfo->comment = ucomment;
  1134. NT_UInfo->script_path = uscriptpath;
  1135. NT_UInfo->full_name = ufullname;
  1136. NT_UInfo->usr_comment = uucomment;
  1137. NT_UInfo->parms = uparms;
  1138. NT_UInfo->workstations = uworkstations;
  1139. NT_UInfo->logon_hours = ulogonhours;
  1140. NT_UInfo->logon_server = ulogonserver;
  1141. NT_UInfo->profile = uprofile;
  1142. NT_UInfo->home_dir_drive = uhome_dir_drive;
  1143. NT_UInfo->units_per_week = UNITS_PER_WEEK;
  1144. // Set the default values for special fields
  1145. NT_UInfo->primary_group_id = DOMAIN_GROUP_RID_USERS;
  1146. NT_UInfo->priv = USER_PRIV_USER;
  1147. NT_UInfo->acct_expires = TIMEQ_FOREVER;
  1148. NT_UInfo->max_storage = USER_MAXSTORAGE_UNLIMITED;
  1149. NT_UInfo->flags = UF_SCRIPT;
  1150. } // NTUserRecInit
  1151. /////////////////////////////////////////////////////////////////////////
  1152. LPTSTR
  1153. NTDriveShare(
  1154. LPTSTR DriveLetter
  1155. )
  1156. /*++
  1157. Routine Description:
  1158. Arguments:
  1159. Return Value:
  1160. --*/
  1161. {
  1162. static TCHAR RootPath[MAX_SERVER_NAME_LEN + 3];
  1163. if (LocalMachine)
  1164. wsprintf(RootPath, TEXT("%s:\\"), DriveLetter);
  1165. else
  1166. wsprintf(RootPath, TEXT("%s\\%s$\\"), CachedServer, DriveLetter);
  1167. return RootPath;
  1168. } // NTDriveShare
  1169. /////////////////////////////////////////////////////////////////////////
  1170. VOID
  1171. NTDriveInfoGet(
  1172. DRIVE_BUFFER *DBuff
  1173. )
  1174. /*++
  1175. Routine Description:
  1176. Arguments:
  1177. Return Value:
  1178. --*/
  1179. {
  1180. DWORD volMaxCompLength, volFileSystemFlags;
  1181. DWORD sectorsPC, bytesPS, FreeClusters, Clusters;
  1182. TCHAR NameBuffer[20];
  1183. TCHAR volName[20];
  1184. LPTSTR RootPath;
  1185. UINT previousErrorMode;
  1186. //
  1187. // Disable DriveAccess Error, because no media is inserted onto specified drive.
  1188. //
  1189. previousErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS|
  1190. SEM_NOOPENFILEERRORBOX);
  1191. volMaxCompLength = volFileSystemFlags = 0;
  1192. sectorsPC = bytesPS = FreeClusters = Clusters = 0;
  1193. // First get file system type
  1194. RootPath = NTDriveShare(DBuff->Drive);
  1195. if (GetVolumeInformation(RootPath, volName, sizeof(volName), NULL, &volMaxCompLength, &volFileSystemFlags, NameBuffer, sizeof(NameBuffer))) {
  1196. if (GetDriveType(RootPath) == DRIVE_CDROM)
  1197. lstrcpy(DBuff->DriveType, Lids(IDS_S_49));
  1198. else
  1199. lstrcpyn(DBuff->DriveType, NameBuffer, sizeof(DBuff->DriveType)-1);
  1200. lstrcpyn(DBuff->Name, volName, sizeof(DBuff->Name)-1);
  1201. if (!lstrcmpi(NameBuffer, Lids(IDS_S_9)))
  1202. DBuff->Type = DRIVE_TYPE_NTFS;
  1203. }
  1204. else {
  1205. if (GetDriveType(RootPath) == DRIVE_CDROM)
  1206. lstrcpy(DBuff->DriveType, Lids(IDS_S_49));
  1207. else
  1208. lstrcpy(DBuff->DriveType, TEXT("\0"));
  1209. lstrcpy(DBuff->Name, TEXT("\0"));
  1210. if (!lstrcmpi(NameBuffer, Lids(IDS_S_9)))
  1211. DBuff->Type = DRIVE_TYPE_NTFS;
  1212. }
  1213. if (GetDiskFreeSpace(RootPath, &sectorsPC, &bytesPS, &FreeClusters, &Clusters)) {
  1214. DBuff->TotalSpace = Clusters * sectorsPC * bytesPS;
  1215. DBuff->FreeSpace = FreeClusters * sectorsPC * bytesPS;
  1216. }
  1217. else {
  1218. DBuff->TotalSpace = 0;
  1219. DBuff->FreeSpace = 0;
  1220. }
  1221. //
  1222. // Back to original error mode.
  1223. //
  1224. SetErrorMode(previousErrorMode);
  1225. } // NTDriveInfoGet
  1226. /////////////////////////////////////////////////////////////////////////
  1227. BOOL
  1228. NTDriveValidate(
  1229. TCHAR DriveLetter
  1230. )
  1231. /*++
  1232. Routine Description:
  1233. Arguments:
  1234. Return Value:
  1235. --*/
  1236. {
  1237. BOOL ret = FALSE;
  1238. // Just make sure it isn't one of the two floppys
  1239. if (!((DriveLetter == TEXT('A')) || (DriveLetter == TEXT('B'))))
  1240. ret = TRUE;
  1241. return ret;
  1242. } // NTDriveValidate
  1243. /////////////////////////////////////////////////////////////////////////
  1244. VOID
  1245. NTDrivesEnum(
  1246. DRIVE_LIST **lpDrives
  1247. )
  1248. /*++
  1249. Routine Description:
  1250. Arguments:
  1251. Return Value:
  1252. --*/
  1253. {
  1254. TCHAR *buffer = NULL;
  1255. NET_API_STATUS Status = 0;
  1256. DWORD entriesread, totalentries, resumehandle, actualentries, i;
  1257. DRIVE_LIST *DriveList;
  1258. DRIVE_BUFFER *DList;
  1259. entriesread = totalentries = resumehandle = actualentries = 0;
  1260. if (LocalMachine)
  1261. Status = NetServerDiskEnum(NULL, 0, (LPBYTE *) &buffer, 0xFFFFFFFF, &entriesread, &totalentries, &resumehandle);
  1262. else
  1263. Status = NetServerDiskEnum(CachedServer, 0, (LPBYTE *) &buffer, 0xFFFFFFFF, &entriesread, &totalentries, &resumehandle);
  1264. if (Status == NO_ERROR) {
  1265. // We have the list - but need to prune out A:, B:
  1266. for (i = 0; i < entriesread; i++)
  1267. if (NTDriveValidate(buffer[i * 3]))
  1268. actualentries++;
  1269. // temporarily use i to hold total size of data structure
  1270. i = sizeof(DRIVE_LIST) + (sizeof(DRIVE_BUFFER) * actualentries);
  1271. DriveList = AllocMemory(i);
  1272. if (!DriveList) {
  1273. Status = ERROR_NOT_ENOUGH_MEMORY;
  1274. } else {
  1275. memset(DriveList, 0, i);
  1276. DList = (DRIVE_BUFFER *) &DriveList->DList;
  1277. DriveList->Count = actualentries;
  1278. // Now fill in the individual data items
  1279. actualentries = 0;
  1280. for (i = 0; i < entriesread; i++)
  1281. if (NTDriveValidate(buffer[i * 3])) {
  1282. DList[actualentries].Drive[0] = buffer[i * 3];
  1283. NTDriveInfoGet(&DList[actualentries]);
  1284. actualentries++;
  1285. }
  1286. }
  1287. }
  1288. if (buffer != NULL)
  1289. NetApiBufferFree((LPVOID) buffer);
  1290. *lpDrives = DriveList;
  1291. return;
  1292. } // NTDrivesEnum
  1293. /////////////////////////////////////////////////////////////////////////
  1294. VOID
  1295. NTServerGetInfo(
  1296. LPTSTR ServerName
  1297. )
  1298. /*++
  1299. Routine Description:
  1300. Arguments:
  1301. Return Value:
  1302. --*/
  1303. {
  1304. TCHAR LocServer[MAX_SERVER_NAME_LEN + 3];
  1305. NET_API_STATUS Status = 0;
  1306. if (ServInfo != NULL)
  1307. NetApiBufferFree((LPVOID) ServInfo);
  1308. ServInfo = NULL;
  1309. wsprintf(LocServer, TEXT("\\\\%s"), ServerName);
  1310. if (!LocalName)
  1311. GetLocalName(&LocalName);
  1312. if (lstrcmpi(ServerName, LocalName) == 0)
  1313. Status = NetServerGetInfo(NULL, 101, (LPBYTE *) &ServInfo);
  1314. else
  1315. Status = NetServerGetInfo(LocServer, 101, (LPBYTE *) &ServInfo);
  1316. if (Status) {
  1317. ServInfo = NULL;
  1318. return;
  1319. }
  1320. } // NTServerGetInfo
  1321. /////////////////////////////////////////////////////////////////////////
  1322. NT_CONN_BUFFER *
  1323. NTConnListFind(
  1324. LPTSTR ServerName
  1325. )
  1326. /*++
  1327. Routine Description:
  1328. Arguments:
  1329. Return Value:
  1330. --*/
  1331. {
  1332. BOOL Found = FALSE;
  1333. static NT_CONN_BUFFER *ServList;
  1334. ServList = NTConnListStart;
  1335. while ((ServList && !Found)) {
  1336. if (!lstrcmpi(ServList->Name, ServerName))
  1337. Found = TRUE;
  1338. else
  1339. ServList = ServList->next;
  1340. }
  1341. if (!Found)
  1342. ServList = NULL;
  1343. return (ServList);
  1344. } // NTConnListFind
  1345. /////////////////////////////////////////////////////////////////////////
  1346. NT_CONN_BUFFER *
  1347. NTConnListAdd(
  1348. LPTSTR ServerName
  1349. )
  1350. /*++
  1351. Routine Description:
  1352. Arguments:
  1353. Return Value:
  1354. --*/
  1355. {
  1356. static NT_CONN_BUFFER *tmpPtr;
  1357. ULONG Size, strlen1;
  1358. tmpPtr = NULL;
  1359. strlen1 = (lstrlen(ServerName) + 1) * sizeof(TCHAR);
  1360. Size = sizeof(NT_CONN_BUFFER) + strlen1;
  1361. tmpPtr = AllocMemory(Size);
  1362. if (tmpPtr != NULL) {
  1363. // init it to NULL's
  1364. memset(tmpPtr, 0, Size);
  1365. tmpPtr->Name = (LPTSTR) ((BYTE *) tmpPtr + sizeof(NT_CONN_BUFFER));
  1366. lstrcpy(tmpPtr->Name, ServerName);
  1367. // link it into the list
  1368. if (!NTConnListStart)
  1369. NTConnListStart = NTConnListEnd = tmpPtr;
  1370. else {
  1371. NTConnListEnd->next = tmpPtr;
  1372. tmpPtr->prev = NTConnListEnd;
  1373. NTConnListEnd = tmpPtr;
  1374. }
  1375. }
  1376. return (tmpPtr);
  1377. } // NTConnListAdd
  1378. /////////////////////////////////////////////////////////////////////////
  1379. VOID
  1380. NTConnListDelete(
  1381. NT_CONN_BUFFER *tmpPtr
  1382. )
  1383. /*++
  1384. Routine Description:
  1385. Arguments:
  1386. Return Value:
  1387. --*/
  1388. {
  1389. NT_CONN_BUFFER *PrevPtr;
  1390. NT_CONN_BUFFER *NextPtr;
  1391. if (tmpPtr == NULL)
  1392. return;
  1393. // Now unlink the actual server record
  1394. PrevPtr = tmpPtr->prev;
  1395. NextPtr = tmpPtr->next;
  1396. if (PrevPtr)
  1397. PrevPtr->next = NextPtr;
  1398. if (NextPtr)
  1399. NextPtr->prev = PrevPtr;
  1400. // Check if at end of list
  1401. if (NTConnListEnd == tmpPtr)
  1402. NTConnListEnd = PrevPtr;
  1403. // Check if at start of list
  1404. if (NTConnListStart == tmpPtr)
  1405. NTConnListStart = NextPtr;
  1406. FreeMemory(tmpPtr);
  1407. } // NTConnListDelete
  1408. /////////////////////////////////////////////////////////////////////////
  1409. VOID
  1410. NTConnListDeleteAll()
  1411. /*++
  1412. Routine Description:
  1413. Arguments:
  1414. Return Value:
  1415. --*/
  1416. {
  1417. static TCHAR LocServer[MAX_SERVER_NAME_LEN + 3];
  1418. NT_CONN_BUFFER *ServList;
  1419. NT_CONN_BUFFER *ServListNext;
  1420. // Now remove the entries from the internal list
  1421. ServList = NTConnListStart;
  1422. while (ServList) {
  1423. ServListNext = ServList->next;
  1424. wsprintf(LocServer, Lids(IDS_S_10), ServList->Name);
  1425. WNetCancelConnection2(LocServer, 0, FALSE);
  1426. NTConnListDelete(ServList);
  1427. ServList = ServListNext;
  1428. }
  1429. } // NTConnListDeleteAll
  1430. /////////////////////////////////////////////////////////////////////////
  1431. VOID
  1432. NTUseDel(
  1433. LPTSTR ServerName
  1434. )
  1435. /*++
  1436. Routine Description:
  1437. Arguments:
  1438. Return Value:
  1439. --*/
  1440. {
  1441. static TCHAR LocServer[MAX_SERVER_NAME_LEN + 3];
  1442. NT_CONN_BUFFER *NTConn;
  1443. // Find it in our connection list - if it exists get rid of it.
  1444. NTConn = NTConnListFind(ServerName);
  1445. if (NTConn != NULL)
  1446. NTConnListDelete(NTConn);
  1447. NTServerFree();
  1448. wsprintf(LocServer, Lids(IDS_S_10), ServerName);
  1449. WNetCancelConnection2(LocServer, 0, FALSE);
  1450. } // NTUseDel
  1451. /////////////////////////////////////////////////////////////////////////
  1452. BOOL
  1453. NTServerValidate(
  1454. HWND hWnd,
  1455. LPTSTR ServerName
  1456. )
  1457. /*++
  1458. Routine Description:
  1459. Validates a given server - makes sure it can be connected to and
  1460. that the user has admin privs on it.
  1461. Arguments:
  1462. Return Value:
  1463. --*/
  1464. {
  1465. BOOL ret = FALSE;
  1466. DWORD idsErr = 0;
  1467. DWORD lastErr = 0;
  1468. DWORD Size;
  1469. NET_API_STATUS Status;
  1470. LPUSER_INFO_1 UserInfo1 = NULL;
  1471. TCHAR UserName[MAX_NT_USER_NAME_LEN + 1];
  1472. TCHAR ServName[MAX_SERVER_NAME_LEN + 3]; // +3 for leading slashes and ending NULL
  1473. LPVOID lpMessageBuffer = NULL;
  1474. NTServerSet(ServerName);
  1475. // server already connected then return success
  1476. if (NTConnListFind(ServerName)) {
  1477. return TRUE;
  1478. }
  1479. CursorHourGlass();
  1480. // Get Current Logged On User
  1481. lstrcpy(UserName, TEXT(""));
  1482. Size = sizeof(UserName);
  1483. WNetGetUser(NULL, UserName, &Size);
  1484. // Fixup the destination server name
  1485. lstrcpy(ServName, TEXT( "\\\\" ));
  1486. lstrcat(ServName, ServerName);
  1487. // Make an ADMIN$ connection to the server
  1488. if (UseAddPswd(hWnd, UserName, ServName, Lids(IDS_S_11), NT_PROVIDER)) {
  1489. // Double check we have admin privs
  1490. // Get connection to the system and check for admin privs...
  1491. Status = NetUserGetInfo(ServName, UserName, 1, (LPBYTE *) &UserInfo1);
  1492. if (Status == ERROR_SUCCESS) {
  1493. // Got User info, now make sure admin flag is set
  1494. if (!(UserInfo1->usri1_priv & USER_PRIV_ADMIN)) {
  1495. idsErr = IDS_E_6;
  1496. goto cleanup;
  1497. }
  1498. // We may have a connection to admin$ and we may have proven
  1499. // that the user we made the connection with really is an admin
  1500. // but sitting at the local machine we still may have a problem
  1501. // acquiring all of the administrative information necessary to
  1502. // accomplish a successful conversion. each and every one of the
  1503. // functions that make network calls should return errors and if
  1504. // that were the case then the errors would propagate up and we
  1505. // could deal with the access denial reasonably. unfortunately,
  1506. // alot of assumptions are made after the success of this call
  1507. // so we must perform yet another test here...
  1508. if (LocalMachine) {
  1509. DWORD EntriesRead = 0;
  1510. DWORD TotalEntries = 0;
  1511. LPSHARE_INFO_2 ShareInfo2 = NULL;
  1512. Status = NetShareEnum(
  1513. ServName,
  1514. 2,
  1515. (LPBYTE *) &ShareInfo2,
  1516. MAX_PREFERRED_LENGTH,
  1517. &EntriesRead,
  1518. &TotalEntries,
  1519. NULL
  1520. );
  1521. if (ShareInfo2 != NULL)
  1522. NetApiBufferFree((LPVOID) ShareInfo2); // discarded...
  1523. if (Status != ERROR_SUCCESS) {
  1524. idsErr = (Status == ERROR_ACCESS_DENIED) ? IDS_E_6 : IDS_E_5;
  1525. goto cleanup;
  1526. }
  1527. }
  1528. // Now get server info and make certain this is an NT server
  1529. // instead of an LM type server. Note: Info from the call is
  1530. // cached and used later, so don't remove it!!
  1531. NTServerGetInfo(ServerName);
  1532. if (ServInfo) {
  1533. if (ServInfo->sv101_platform_id == SV_PLATFORM_ID_NT) {
  1534. if (ServInfo->sv101_type & (TYPE_DOMAIN)) {
  1535. // If NTAS and have admin privs then we are set
  1536. // then add it to our connection list...
  1537. NTConnListAdd(ServerName);
  1538. ret = TRUE;
  1539. } else {
  1540. idsErr = IDS_E_8;
  1541. }
  1542. } else {
  1543. idsErr = IDS_E_8;
  1544. }
  1545. } else {
  1546. idsErr = IDS_E_7;
  1547. }
  1548. } else {
  1549. // determine error string id and bail out...
  1550. idsErr = (Status == ERROR_ACCESS_DENIED) ? IDS_E_6 : IDS_E_5;
  1551. }
  1552. } else if (lastErr = GetLastError()) {
  1553. // error string id
  1554. idsErr = IDS_E_9;
  1555. // use system default language resource
  1556. FormatMessage(
  1557. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  1558. FORMAT_MESSAGE_FROM_SYSTEM,
  1559. NULL,
  1560. lastErr,
  1561. 0,
  1562. (LPTSTR)&lpMessageBuffer,
  1563. 0,
  1564. NULL
  1565. );
  1566. }
  1567. cleanup:
  1568. if (lpMessageBuffer) {
  1569. WarningError(Lids((WORD)(DWORD)idsErr), ServerName, lpMessageBuffer);
  1570. LocalFree(lpMessageBuffer);
  1571. } else if (idsErr) {
  1572. WarningError(Lids((WORD)(DWORD)idsErr), ServerName);
  1573. }
  1574. if (UserInfo1 != NULL)
  1575. NetApiBufferFree((LPVOID) UserInfo1);
  1576. CursorNormal();
  1577. return ret;
  1578. } // NTServerValidate
  1579. /////////////////////////////////////////////////////////////////////////
  1580. VOID
  1581. NTServerInfoReset(
  1582. HWND hWnd,
  1583. DEST_SERVER_BUFFER *DServ,
  1584. BOOL ResetDomain
  1585. )
  1586. /*++
  1587. Routine Description:
  1588. Arguments:
  1589. Return Value:
  1590. --*/
  1591. {
  1592. LPTSTR apiPDCName = NULL;
  1593. TCHAR PDCName[MAX_SERVER_NAME_LEN + 1];
  1594. TCHAR LocServer[MAX_SERVER_NAME_LEN + 3];
  1595. DOMAIN_BUFFER *DBuff;
  1596. TCHAR Domain[DNLEN + 1];
  1597. NET_API_STATUS Status = 0;
  1598. lstrcpy(PDCName, TEXT(""));
  1599. if (ServInfo) {
  1600. DServ->Type = ServInfo->sv101_type;
  1601. DServ->VerMaj = ServInfo->sv101_version_major;
  1602. DServ->VerMin = ServInfo->sv101_version_minor;
  1603. DServ->IsNTAS = IsNTAS(DServ->Name);
  1604. DServ->IsFPNW = IsFPNW(DServ->Name);
  1605. // If there was no old domain, don't worry about reseting it
  1606. if (ResetDomain && (DServ->Domain == NULL))
  1607. ResetDomain = FALSE;
  1608. // Check if we are a member of a domain.
  1609. if (ServInfo->sv101_type & (TYPE_DOMAIN)) {
  1610. wsprintf(LocServer, TEXT("\\\\%s"), DServ->Name);
  1611. Status = NetGetDCName(LocServer, NULL, (LPBYTE *) &apiPDCName);
  1612. if (!Status) {
  1613. // get rid of leading 2 backslashes
  1614. if (lstrlen(apiPDCName) > 2)
  1615. lstrcpy(PDCName, &apiPDCName[2]);
  1616. if (NTServerValidate(hWnd, PDCName)) {
  1617. DServ->IsFPNW = IsFPNW(PDCName);
  1618. DServ->InDomain = TRUE;
  1619. // Get Domain
  1620. memset(Domain, 0, sizeof(Domain));
  1621. NTDomainGet(DServ->Name, Domain);
  1622. if (ResetDomain) {
  1623. DomainListDelete(DServ->Domain);
  1624. DServ->Domain = NULL;
  1625. }
  1626. // Check if we need to add server to server list
  1627. DBuff = DomainListFind(Domain);
  1628. if (DBuff == NULL) {
  1629. DBuff = DomainListAdd(Domain, PDCName);
  1630. DBuff->Type = ServInfo->sv101_type;
  1631. DBuff->VerMaj = ServInfo->sv101_version_major;
  1632. DBuff->VerMin = ServInfo->sv101_version_minor;
  1633. }
  1634. DBuff->UseCount++;
  1635. DServ->Domain = DBuff;
  1636. } // if Domain valid
  1637. if (apiPDCName != NULL)
  1638. NetApiBufferFree((LPVOID) apiPDCName);
  1639. }
  1640. }
  1641. }
  1642. // make sure we are pointing to the right one
  1643. NTServerSet(DServ->Name);
  1644. // Fill in Drive Lists
  1645. NTDrivesEnum(&DServ->DriveList);
  1646. } // NTServerInfoReset
  1647. /////////////////////////////////////////////////////////////////////////
  1648. VOID
  1649. NTServerInfoSet(
  1650. HWND hWnd,
  1651. LPTSTR ServerName,
  1652. DEST_SERVER_BUFFER *DServ
  1653. )
  1654. /*++
  1655. Routine Description:
  1656. Arguments:
  1657. Return Value:
  1658. --*/
  1659. {
  1660. LPTSTR apiPDCName = NULL;
  1661. NET_API_STATUS Status = 0;
  1662. CursorHourGlass();
  1663. DServ->UseCount++;
  1664. NTServerInfoReset(hWnd, DServ, FALSE);
  1665. // Fill in share and Drive Lists
  1666. NTSharesEnum(&DServ->ShareList, DServ->DriveList);
  1667. #ifdef DEBUG
  1668. {
  1669. DWORD i;
  1670. dprintf(TEXT("Adding NT Server: %s\n"), DServ->Name);
  1671. dprintf(TEXT(" Version: %lu.%lu\n"), DServ->VerMaj, DServ->VerMin);
  1672. if (DServ->InDomain && DServ->Domain)
  1673. dprintf(TEXT(" In Domain: %s [\\\\%s]\n"), DServ->Domain->Name, DServ->Domain->PDCName);
  1674. dprintf(TEXT("\n"));
  1675. dprintf(TEXT(" Drives:\n"));
  1676. dprintf(TEXT(" +-------------------+\n"));
  1677. for (i = 0; i < DServ->DriveList->Count; i++)
  1678. dprintf(TEXT(" %s\n"), DServ->DriveList->DList[i].Drive);
  1679. dprintf(TEXT("\n"));
  1680. dprintf(TEXT(" Shares:\n"));
  1681. dprintf(TEXT(" +-------------------+\n"));
  1682. for (i = 0; i < DServ->ShareList->Count; i++)
  1683. dprintf(TEXT(" %s\n"), DServ->ShareList->SList[i].Name);
  1684. dprintf(TEXT("\n"));
  1685. }
  1686. #endif
  1687. CursorNormal();
  1688. } // NTServerInfoSet
  1689. /////////////////////////////////////////////////////////////////////////
  1690. VOID
  1691. NTLoginTimesLog(
  1692. BYTE *Times
  1693. )
  1694. /*++
  1695. Routine Description:
  1696. Arguments:
  1697. Return Value:
  1698. --*/
  1699. {
  1700. TCHAR *szDays[7];
  1701. DWORD Day;
  1702. DWORD Hours;
  1703. int Bit = 0;
  1704. static TCHAR szHours[80];
  1705. szDays[0] = Lids(IDS_SUN);
  1706. szDays[1] = Lids(IDS_MON);
  1707. szDays[2] = Lids(IDS_TUE);
  1708. szDays[3] = Lids(IDS_WED);
  1709. szDays[4] = Lids(IDS_THU);
  1710. szDays[5] = Lids(IDS_FRI);
  1711. szDays[6] = Lids(IDS_SAT);
  1712. LogWriteLog(1, Lids(IDS_CRLF));
  1713. LogWriteLog(1, Lids(IDS_L_56));
  1714. // while these should be indent 2, there isn't room on 80 cols - so indent 1
  1715. LogWriteLog(1, Lids(IDS_L_1));
  1716. LogWriteLog(1, Lids(IDS_L_2));
  1717. LogWriteLog(1, Lids(IDS_L_3));
  1718. for (Day = 0; Day < 7; Day++) {
  1719. LogWriteLog(1, szDays[Day]);
  1720. lstrcpy(szHours, TEXT(" "));
  1721. for (Hours = 0; Hours < 24; Hours++) {
  1722. if (BitTest(Bit, Times))
  1723. lstrcat(szHours, TEXT("**"));
  1724. else
  1725. lstrcat(szHours, TEXT(" "));
  1726. Bit++;
  1727. lstrcat(szHours, TEXT(" "));
  1728. }
  1729. LogWriteLog(0, szHours);
  1730. LogWriteLog(0, Lids(IDS_CRLF));
  1731. }
  1732. LogWriteLog(0, Lids(IDS_CRLF));
  1733. } // NTLoginTimesLog
  1734. /////////////////////////////////////////////////////////////////////////
  1735. VOID
  1736. NTUserRecLog(
  1737. NT_USER_INFO NT_UInfo
  1738. )
  1739. /*++
  1740. Routine Description:
  1741. Arguments:
  1742. Return Value:
  1743. --*/
  1744. {
  1745. LPTSTR tmpStr;
  1746. LogWriteLog(1, Lids(IDS_L_57));
  1747. LogWriteLog(2, Lids(IDS_L_58), NT_UInfo.full_name);
  1748. LogWriteLog(2, Lids(IDS_L_59), NT_UInfo.password);
  1749. switch(NT_UInfo.priv) {
  1750. case 0:
  1751. tmpStr = Lids(IDS_L_60);
  1752. break;
  1753. case 1:
  1754. tmpStr = Lids(IDS_L_61);
  1755. break;
  1756. case 2:
  1757. tmpStr = Lids(IDS_L_62);
  1758. break;
  1759. }
  1760. LogWriteLog(2, Lids(IDS_L_63), tmpStr);
  1761. LogWriteLog(2, Lids(IDS_L_64), NT_UInfo.home_dir);
  1762. LogWriteLog(2, Lids(IDS_L_65), NT_UInfo.comment);
  1763. // Flags
  1764. LogWriteLog(2, Lids(IDS_L_66));
  1765. if (NT_UInfo.flags & 0x01)
  1766. LogWriteLog(3, Lids(IDS_L_67), Lids(IDS_YES));
  1767. else
  1768. LogWriteLog(3, Lids(IDS_L_67), Lids(IDS_NO));
  1769. if (NT_UInfo.flags & 0x02)
  1770. LogWriteLog(3, Lids(IDS_L_68), Lids(IDS_YES));
  1771. else
  1772. LogWriteLog(3, Lids(IDS_L_68), Lids(IDS_NO));
  1773. if (NT_UInfo.flags & 0x04)
  1774. LogWriteLog(3, Lids(IDS_L_69), Lids(IDS_YES));
  1775. else
  1776. LogWriteLog(3, Lids(IDS_L_69), Lids(IDS_NO));
  1777. if (NT_UInfo.flags & 0x08)
  1778. LogWriteLog(3, Lids(IDS_L_70), Lids(IDS_YES));
  1779. else
  1780. LogWriteLog(3, Lids(IDS_L_70), Lids(IDS_NO));
  1781. if (NT_UInfo.flags & 0x20)
  1782. LogWriteLog(3, Lids(IDS_L_71), Lids(IDS_NO));
  1783. else
  1784. LogWriteLog(3, Lids(IDS_L_71), Lids(IDS_YES));
  1785. if (NT_UInfo.flags & 0x40)
  1786. LogWriteLog(3, Lids(IDS_L_72), Lids(IDS_NO));
  1787. else
  1788. LogWriteLog(3, Lids(IDS_L_72), Lids(IDS_YES));
  1789. // Script path
  1790. LogWriteLog(2, Lids(IDS_L_73), NT_UInfo.script_path);
  1791. LogWriteLog(2, Lids(IDS_L_74), NT_UInfo.full_name);
  1792. LogWriteLog(2, Lids(IDS_L_75), NT_UInfo.logon_server);
  1793. NTLoginTimesLog((BYTE *) NT_UInfo.logon_hours);
  1794. LogWriteLog(0, Lids(IDS_CRLF));
  1795. } // NTUserRecLog
  1796. /////////////////////////////////////////////////////////////////////////
  1797. VOID
  1798. NTDomainSynch(
  1799. DEST_SERVER_BUFFER *DServ
  1800. )
  1801. /*++
  1802. Routine Description:
  1803. Arguments:
  1804. Return Value:
  1805. --*/
  1806. {
  1807. LPBYTE buffer = NULL;
  1808. BOOL UsePDC = FALSE;
  1809. NET_API_STATUS Status;
  1810. TCHAR LocServer[MAX_SERVER_NAME_LEN + 3];
  1811. wsprintf(LocServer, TEXT("\\\\%s"), DServ->Name);
  1812. if ((DServ->InDomain) && (DServ->Domain != NULL)) {
  1813. wsprintf(LocServer, TEXT("\\\\%s"), DServ->Domain->PDCName);
  1814. UsePDC = TRUE;
  1815. }
  1816. if (UsePDC)
  1817. Status = I_NetLogonControl(LocServer, NETLOGON_CONTROL_PDC_REPLICATE, 1, &buffer);
  1818. else
  1819. Status = I_NetLogonControl(LocServer, NETLOGON_CONTROL_SYNCHRONIZE, 1, &buffer);
  1820. if (buffer != NULL)
  1821. NetApiBufferFree(buffer);
  1822. } // NTDomainSynch
  1823. /////////////////////////////////////////////////////////////////////////
  1824. BOOL
  1825. NTDomainInSynch(
  1826. LPTSTR Server
  1827. )
  1828. /*++
  1829. Routine Description:
  1830. Arguments:
  1831. Return Value:
  1832. --*/
  1833. {
  1834. PNETLOGON_INFO_1 buffer = NULL;
  1835. NET_API_STATUS Status;
  1836. Status = I_NetLogonControl(Server, NETLOGON_CONTROL_QUERY, 1, (PBYTE *) &buffer);
  1837. if (Status) {
  1838. return TRUE;
  1839. }
  1840. if (buffer && buffer->netlog1_flags)
  1841. return FALSE;
  1842. if (buffer != NULL)
  1843. NetApiBufferFree(buffer);
  1844. return TRUE;
  1845. } // NTDomainInSynch
  1846. /////////////////////////////////////////////////////////////////////////
  1847. BOOL
  1848. NTDomainGet(
  1849. LPTSTR ServerName,
  1850. LPTSTR Domain
  1851. )
  1852. /*++
  1853. Routine Description:
  1854. Gee - what a simple way to get the domain a server is part of!
  1855. Arguments:
  1856. Return Value:
  1857. --*/
  1858. {
  1859. static TCHAR Serv[MAX_SERVER_NAME_LEN + 3];
  1860. UNICODE_STRING us;
  1861. NTSTATUS ret;
  1862. OBJECT_ATTRIBUTES oa;
  1863. ACCESS_MASK am;
  1864. SECURITY_QUALITY_OF_SERVICE qos;
  1865. LSA_HANDLE hLSA;
  1866. PPOLICY_PRIMARY_DOMAIN_INFO pvBuffer;
  1867. if (ServerName[0] == TEXT('\\'))
  1868. lstrcpy(Serv, ServerName);
  1869. else
  1870. wsprintf(Serv, TEXT("\\\\%s"), ServerName);
  1871. // Set up unicode string structure
  1872. us.Length = (USHORT)(lstrlen(Serv) * sizeof(TCHAR));
  1873. us.MaximumLength = us.Length + sizeof(TCHAR);
  1874. us.Buffer = Serv;
  1875. // only need read access
  1876. am = POLICY_READ | POLICY_VIEW_LOCAL_INFORMATION;
  1877. // set up quality of service
  1878. qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
  1879. qos.ImpersonationLevel = SecurityImpersonation;
  1880. qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  1881. qos.EffectiveOnly = FALSE;
  1882. // Macro sets everything except security field
  1883. InitializeObjectAttributes( &oa, NULL, 0L, NULL, NULL );
  1884. oa.SecurityQualityOfService = &qos;
  1885. ret = LsaOpenPolicy(&us, &oa, am, &hLSA);
  1886. if (!ret) {
  1887. ret = LsaQueryInformationPolicy(hLSA, PolicyPrimaryDomainInformation, (PVOID *) &pvBuffer);
  1888. LsaClose(hLSA);
  1889. if ((!ret) && (pvBuffer != NULL)) {
  1890. lstrcpy(Domain, pvBuffer->Name.Buffer);
  1891. LsaFreeMemory((PVOID) pvBuffer);
  1892. }
  1893. }
  1894. if (ret)
  1895. return FALSE;
  1896. else
  1897. return TRUE;
  1898. } // NTDomainGet
  1899. /////////////////////////////////////////////////////////////////////////
  1900. BOOL
  1901. IsFPNW(
  1902. LPTSTR ServerName
  1903. )
  1904. /*++
  1905. Routine Description:
  1906. Checks the given machine for the FPNW secret.
  1907. Arguments:
  1908. Return Value:
  1909. --*/
  1910. {
  1911. return (FPNWSecretGet(ServerName) != NULL);
  1912. } // IsFPNW
  1913. /////////////////////////////////////////////////////////////////////////
  1914. BOOL
  1915. IsNTAS(
  1916. LPTSTR ServerName
  1917. )
  1918. /*++
  1919. Routine Description:
  1920. Checks the given machines registry to determine if it is an NTAS
  1921. system. The new 'Server' type is also counted as NTAS as all we
  1922. use this for is to determine if local or global groups should be
  1923. used.
  1924. Arguments:
  1925. Return Value:
  1926. --*/
  1927. {
  1928. HKEY hKey, hKey2;
  1929. DWORD dwType, dwSize;
  1930. static TCHAR LocServer[MAX_SERVER_NAME_LEN + 3];
  1931. static TCHAR Type[50];
  1932. LONG Status;
  1933. BOOL ret = FALSE;
  1934. wsprintf(LocServer, TEXT("\\\\%s"), ServerName);
  1935. dwSize = sizeof(Type);
  1936. if (RegConnectRegistry(LocServer, HKEY_LOCAL_MACHINE, &hKey) == ERROR_SUCCESS)
  1937. if ((Status = RegOpenKeyEx(hKey, Lids(IDS_S_12), 0, KEY_READ, &hKey2)) == ERROR_SUCCESS)
  1938. if ((Status = RegQueryValueEx(hKey2, Lids(IDS_S_13), NULL, &dwType, (LPBYTE) Type, &dwSize)) == ERROR_SUCCESS)
  1939. if (!lstrcmpi(Type, Lids(IDS_S_14)))
  1940. ret = TRUE;
  1941. RegCloseKey(hKey);
  1942. return ret;
  1943. } // IsNTAS
  1944. /////////////////////////////////////////////////////////////////////////
  1945. VOID
  1946. NTTrustedDomainsEnum(
  1947. LPTSTR ServerName,
  1948. TRUSTED_DOMAIN_LIST **pTList
  1949. )
  1950. /*++
  1951. Routine Description:
  1952. Arguments:
  1953. Return Value:
  1954. --*/
  1955. {
  1956. static TCHAR Serv[MAX_SERVER_NAME_LEN + 3];
  1957. TRUSTED_DOMAIN_LIST *TList = NULL;
  1958. UNICODE_STRING us;
  1959. NTSTATUS ret;
  1960. OBJECT_ATTRIBUTES oa;
  1961. ACCESS_MASK am;
  1962. SECURITY_QUALITY_OF_SERVICE qos;
  1963. LSA_HANDLE hLSA;
  1964. PPOLICY_PRIMARY_DOMAIN_INFO pvBuffer = NULL;
  1965. LSA_ENUMERATION_HANDLE lsaenumh = 0;
  1966. LSA_TRUST_INFORMATION *lsat;
  1967. ULONG maxrequested = 0xffff;
  1968. ULONG cItems;
  1969. ULONG i;
  1970. if (ServerName[0] == TEXT('\\'))
  1971. lstrcpy(Serv, ServerName);
  1972. else
  1973. wsprintf(Serv, TEXT("\\\\%s"), ServerName);
  1974. // Set up unicode string structure
  1975. us.Length = (USHORT)(lstrlen(Serv) * sizeof(TCHAR));
  1976. us.MaximumLength = us.Length + sizeof(TCHAR);
  1977. us.Buffer = Serv;
  1978. // only need read access
  1979. am = POLICY_READ | POLICY_VIEW_LOCAL_INFORMATION;
  1980. // set up quality of service
  1981. qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
  1982. qos.ImpersonationLevel = SecurityImpersonation;
  1983. qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  1984. qos.EffectiveOnly = FALSE;
  1985. // Macro sets everything except security field
  1986. InitializeObjectAttributes( &oa, NULL, 0L, NULL, NULL );
  1987. oa.SecurityQualityOfService = &qos;
  1988. ret = LsaOpenPolicy(&us, &oa, am, &hLSA);
  1989. if (!ret) {
  1990. ret = LsaEnumerateTrustedDomains(hLSA, &lsaenumh, (PVOID *) &pvBuffer, maxrequested, &cItems);
  1991. LsaClose(hLSA);
  1992. if ((!ret) && (pvBuffer != NULL)) {
  1993. lsat = (LSA_TRUST_INFORMATION *) pvBuffer;
  1994. TList = (TRUSTED_DOMAIN_LIST *) AllocMemory(sizeof(TRUSTED_DOMAIN_LIST) + (cItems * ((MAX_DOMAIN_NAME_LEN + 1) * sizeof(TCHAR))));
  1995. memset(TList, 0, sizeof(TRUSTED_DOMAIN_LIST) + (cItems * ((MAX_DOMAIN_NAME_LEN + 1) * sizeof(TCHAR))));
  1996. if (TList != NULL) {
  1997. TList->Count = cItems;
  1998. for (i = 0; i < cItems; i++)
  1999. memcpy(TList->Name[i], lsat[i].Name.Buffer, lsat[i].Name.Length);
  2000. }
  2001. LsaFreeMemory((PVOID) pvBuffer);
  2002. }
  2003. }
  2004. *pTList = TList;
  2005. } // NTTrustedDomainsEnum
  2006. /////////////////////////////////////////////////////////////////////////
  2007. DOMAIN_BUFFER *
  2008. NTTrustedDomainSet(
  2009. HWND hWnd,
  2010. LPTSTR Server,
  2011. LPTSTR TrustedDomain
  2012. )
  2013. /*++
  2014. Routine Description:
  2015. Arguments:
  2016. Return Value:
  2017. --*/
  2018. {
  2019. LPTSTR apiPDCName = NULL;
  2020. TCHAR PDCName[MAX_SERVER_NAME_LEN];
  2021. TCHAR LocServer[MAX_SERVER_NAME_LEN + 3];
  2022. static DOMAIN_BUFFER *DBuff;
  2023. NET_API_STATUS Status = 0;
  2024. DBuff = NULL;
  2025. lstrcpy(PDCName, TEXT(""));
  2026. wsprintf(LocServer, TEXT("\\\\%s"), Server);
  2027. Status = NetGetDCName(LocServer, TrustedDomain, (LPBYTE *) &apiPDCName);
  2028. if (!Status) {
  2029. // get rid of leading 2 backslashes
  2030. if (lstrlen(apiPDCName) > 2)
  2031. lstrcpy(PDCName, &apiPDCName[2]);
  2032. if (NTServerValidate(hWnd, PDCName)) {
  2033. // Check if we need to add domain to domain list
  2034. DBuff = DomainListFind(TrustedDomain);
  2035. if (DBuff == NULL) {
  2036. DBuff = DomainListAdd(TrustedDomain, PDCName);
  2037. DBuff->Type = ServInfo->sv101_type;
  2038. DBuff->VerMaj = ServInfo->sv101_version_major;
  2039. DBuff->VerMin = ServInfo->sv101_version_minor;
  2040. }
  2041. DBuff->UseCount++;
  2042. } // if Domain valid
  2043. if (apiPDCName != NULL)
  2044. NetApiBufferFree((LPVOID) apiPDCName);
  2045. }
  2046. // make sure we are pointing to the right one
  2047. NTServerSet(Server);
  2048. return DBuff;
  2049. } // NTTrustedDomainSet
  2050. /////////////////////////////////////////////////////////////////////////
  2051. SID *
  2052. NTSIDGet(
  2053. LPTSTR ServerName,
  2054. LPTSTR pUserName
  2055. )
  2056. /*++
  2057. Routine Description:
  2058. Arguments:
  2059. Return Value:
  2060. --*/
  2061. {
  2062. static TCHAR lpszDomain[80];
  2063. DWORD dwDomainLength = 80;
  2064. static UCHAR psnuType[1024];
  2065. static SID UserSID[1024];
  2066. DWORD dwSIDBufSize = 1024;
  2067. BOOL Retry = TRUE;
  2068. // Get SID for user
  2069. while (Retry) {
  2070. if (!LookupAccountName(ServerName, pUserName, UserSID, &dwSIDBufSize,
  2071. lpszDomain, &dwDomainLength, (PSID_NAME_USE) psnuType)) {
  2072. #ifdef DEBUG
  2073. dprintf(TEXT("Error %d: LookupAccountName\n"), GetLastError());
  2074. #endif
  2075. if (GetLastError() == ERROR_NONE_MAPPED)
  2076. if (NTDomainInSynch(ServerName))
  2077. Retry = FALSE;
  2078. else
  2079. Sleep(5000L);
  2080. } else
  2081. return UserSID;
  2082. }
  2083. return NULL;
  2084. } // NTSIDGet
  2085. #define SD_SIZE (65536 + SECURITY_DESCRIPTOR_MIN_LENGTH)
  2086. /////////////////////////////////////////////////////////////////////////
  2087. BOOL
  2088. NTFile_AccessRightsAdd(
  2089. LPTSTR ServerName,
  2090. LPTSTR pUserName,
  2091. LPTSTR pFileName,
  2092. ACCESS_MASK AccessMask,
  2093. BOOL Dir
  2094. )
  2095. /*++
  2096. Routine Description:
  2097. Arguments:
  2098. Return Value:
  2099. --*/
  2100. {
  2101. NTSTATUS ret;
  2102. SID *pUserSID;
  2103. // File SD variables
  2104. static UCHAR ucSDbuf[SD_SIZE];
  2105. PSECURITY_DESCRIPTOR pFileSD = (PSECURITY_DESCRIPTOR) ucSDbuf;
  2106. DWORD dwSDLengthNeeded = 0;
  2107. // New SD variables
  2108. UCHAR NewSD[SECURITY_DESCRIPTOR_MIN_LENGTH];
  2109. PSECURITY_DESCRIPTOR psdNewSD=(PSECURITY_DESCRIPTOR)NewSD;
  2110. // +-----------------------------------------------------------------+
  2111. // | Main Code |
  2112. // +-----------------------------------------------------------------+
  2113. pUserSID = NTSIDGet(ServerName, pUserName);
  2114. if (pUserSID == NULL) {
  2115. LogWriteLog(5, Lids(IDS_L_76), GetLastError());
  2116. ErrorIt(Lids(IDS_L_77), GetLastError(), pUserName);
  2117. return FALSE;
  2118. }
  2119. // Get security descriptor (SD) for file
  2120. if(!GetFileSecurity(pFileName, (SECURITY_INFORMATION) (DACL_SECURITY_INFORMATION),
  2121. pFileSD, SD_SIZE, (LPDWORD) &dwSDLengthNeeded)) {
  2122. #ifdef DEBUG
  2123. dprintf(TEXT("Error %d: GetFileSecurity\n"), GetLastError());
  2124. #endif
  2125. LogWriteLog(5, Lids(IDS_L_76), GetLastError());
  2126. ErrorIt(Lids(IDS_L_77), GetLastError(), pUserName);
  2127. return (FALSE);
  2128. }
  2129. if (Dir)
  2130. ret = ACEAdd(pFileSD, pUserSID, AccessMask, DirRightsMapping.NtAceFlags, &psdNewSD );
  2131. else
  2132. ret = ACEAdd(pFileSD, pUserSID, AccessMask, FileRightsMapping.NtAceFlags, &psdNewSD );
  2133. if (ret) {
  2134. #ifdef DEBUG
  2135. dprintf(TEXT("Error %d: NWAddRight\n"), GetLastError());
  2136. #endif
  2137. LogWriteLog(5, Lids(IDS_L_76), GetLastError());
  2138. ErrorIt(Lids(IDS_L_77), GetLastError(), pUserName);
  2139. return FALSE;
  2140. }
  2141. // Set the SD to the File
  2142. if (!SetFileSecurity(pFileName, DACL_SECURITY_INFORMATION, psdNewSD)) {
  2143. #ifdef DEBUG
  2144. dprintf(TEXT("Error %d: SetFileSecurity\n"), GetLastError());
  2145. #endif
  2146. LogWriteLog(5, Lids(IDS_L_76), GetLastError());
  2147. ErrorIt(Lids(IDS_L_77), GetLastError(), pUserName);
  2148. if (psdNewSD != pFileSD)
  2149. NW_FREE(psdNewSD);
  2150. return FALSE;
  2151. }
  2152. // Free the memory allocated for the new ACL, but only if
  2153. // it was allocated.
  2154. if (psdNewSD != pFileSD)
  2155. NW_FREE(psdNewSD);
  2156. return TRUE;
  2157. } // NTFile_AccessRightsAdd
  2158. /////////////////////////////////////////////////////////////////////////
  2159. NTSTATUS
  2160. ACEAdd(
  2161. PSECURITY_DESCRIPTOR pSD,
  2162. PSID pSid,
  2163. ACCESS_MASK AccessMask,
  2164. ULONG AceFlags,
  2165. PSECURITY_DESCRIPTOR *ppNewSD
  2166. )
  2167. /*++
  2168. Routine Description:
  2169. ACEAdd() - Taken from ChuckC's NWRights.C
  2170. Arguments:
  2171. psd - The security desciptor to modify. This must be a valid
  2172. security descriptor.
  2173. psid - The SID of the user/group for which we are adding this right.
  2174. AccessMask - The access mask that we wish to add.
  2175. ppNewSD - used to return the new Security descriptor.
  2176. Return Value:
  2177. NTSTATUS code
  2178. --*/
  2179. {
  2180. ACL Acl ;
  2181. PACL pAcl, pNewAcl = NULL ;
  2182. PACCESS_ALLOWED_ACE pAccessAce, pNewAce = NULL ;
  2183. NTSTATUS ntstatus ;
  2184. BOOLEAN fDaclPresent, fDaclDefaulted;
  2185. BOOLEAN Found = FALSE;
  2186. LONG i ;
  2187. // validate and initialize
  2188. if (!pSD || !pSid || !ppNewSD || !RtlValidSecurityDescriptor(pSD)) {
  2189. #ifdef DEBUG
  2190. dprintf(TEXT("ACEAdd: got invalid parm\n"));
  2191. #endif
  2192. return (STATUS_INVALID_PARAMETER) ;
  2193. }
  2194. // if AccessMask == 0, no need to add the ACE
  2195. if( !AccessMask ) {
  2196. *ppNewSD = pSD;
  2197. return( STATUS_SUCCESS );
  2198. }
  2199. *ppNewSD = NULL ;
  2200. // extract the DACL from the securiry descriptor
  2201. ntstatus = RtlGetDaclSecurityDescriptor(pSD, &fDaclPresent, &pAcl, &fDaclDefaulted) ;
  2202. if (!NT_SUCCESS(ntstatus)) {
  2203. #ifdef DEBUG
  2204. dprintf(TEXT("ACEAdd: RtlGetDaclSecurityDescriptor failed\n"));
  2205. #endif
  2206. goto CleanupAndExit ;
  2207. }
  2208. // if no DACL present, we create one
  2209. if ((!fDaclPresent) || (pAcl == NULL)) {
  2210. // create Dacl
  2211. ntstatus = RtlCreateAcl(&Acl, sizeof(Acl), ACL_REVISION) ;
  2212. if (!NT_SUCCESS(ntstatus)) {
  2213. #ifdef DEBUG
  2214. dprintf(TEXT("ACEAdd: RtlCreateAcl failed\n"));
  2215. #endif
  2216. goto CleanupAndExit ;
  2217. }
  2218. pAcl = &Acl ;
  2219. }
  2220. // loop thru ACEs, looking for entry with the user/group SID
  2221. pAccessAce = NULL ;
  2222. for (i = 0; i < pAcl->AceCount; i++) {
  2223. ACE_HEADER *pAce ;
  2224. ntstatus = RtlGetAce(pAcl,i,&pAce) ;
  2225. if (!NT_SUCCESS(ntstatus)) {
  2226. #ifdef DEBUG
  2227. dprintf(TEXT("ACEAdd: RtlGetAce failed\n"));
  2228. #endif
  2229. goto CleanupAndExit ;
  2230. }
  2231. if (pAce->AceType == ACCESS_ALLOWED_ACE_TYPE) {
  2232. // found a granting ace, which is what we want
  2233. PSID pAceSid ;
  2234. pAccessAce = (ACCESS_ALLOWED_ACE *) pAce ;
  2235. pAceSid = (PSID) &pAccessAce->SidStart ;
  2236. //
  2237. // is this the same SID?
  2238. // if yes, modify access mask and carry on.
  2239. //
  2240. if (RtlEqualSid(pAceSid, pSid)) {
  2241. ACCESS_MASK access_mask ;
  2242. ASSERT(pAccessAce != NULL) ;
  2243. access_mask = pAccessAce->Mask ;
  2244. if ( (access_mask & AccessMask) == access_mask ) {
  2245. ntstatus = STATUS_MEMBER_IN_GROUP ;
  2246. goto CleanupAndExit ;
  2247. }
  2248. pAccessAce->Mask = AccessMask ;
  2249. Found = TRUE ;
  2250. }
  2251. } else {
  2252. // ignore it. we only deal with granting aces.
  2253. }
  2254. }
  2255. if ( !Found ) { // now set the DACL to have the desired rights
  2256. // reached end of ACE list without finding match. so we need to
  2257. // create a new ACE.
  2258. USHORT NewAclSize, NewAceSize ;
  2259. // calculate the sizes
  2260. NewAceSize = (USHORT)(sizeof(ACE_HEADER) +
  2261. sizeof(ACCESS_MASK) +
  2262. RtlLengthSid(pSid));
  2263. NewAclSize = pAcl->AclSize + NewAceSize ;
  2264. // allocate new ACE and new ACL (since we are growing it)
  2265. pNewAce = (PACCESS_ALLOWED_ACE) NW_ALLOC(NewAceSize) ;
  2266. if (!pNewAce) {
  2267. #ifdef DEBUG
  2268. dprintf(TEXT("ACEAdd: memory allocation failed for new ACE\n"));
  2269. #endif
  2270. ntstatus = STATUS_INSUFFICIENT_RESOURCES ;
  2271. goto CleanupAndExit ;
  2272. }
  2273. pNewAce->Header.AceFlags = (UCHAR)AceFlags;
  2274. pNewAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
  2275. pNewAce->Header.AceSize = NewAceSize;
  2276. pNewAce->Mask = AccessMask;
  2277. RtlCopySid( RtlLengthSid(pSid), (PSID)(&pNewAce->SidStart), pSid );
  2278. pNewAcl = (PACL) NW_ALLOC(NewAclSize) ;
  2279. if (!pNewAcl) {
  2280. #ifdef DEBUG
  2281. dprintf(TEXT("ACEAdd: memory allocation failed for new ACL\n"));
  2282. #endif
  2283. ntstatus = STATUS_INSUFFICIENT_RESOURCES ;
  2284. goto CleanupAndExit ;
  2285. }
  2286. RtlCopyMemory(pNewAcl, pAcl, pAcl->AclSize) ;
  2287. pNewAcl->AclSize = NewAclSize ;
  2288. // Add the ACE to the end of the ACL
  2289. ntstatus = RtlAddAce(pNewAcl, ACL_REVISION, pNewAcl->AceCount, pNewAce, NewAceSize) ;
  2290. if (!NT_SUCCESS(ntstatus)) {
  2291. #ifdef DEBUG
  2292. dprintf(TEXT("ACEAdd: RtlAddAce failed\n"));
  2293. #endif
  2294. goto CleanupAndExit ;
  2295. }
  2296. pAcl = pNewAcl ;
  2297. }
  2298. // set the dacl back into the security descriptor. we need create
  2299. // a new security descriptor, since the old one may not have space
  2300. // for any additional ACE.
  2301. ntstatus = CreateNewSecurityDescriptor(ppNewSD, pSD, pAcl) ;
  2302. if (!NT_SUCCESS(ntstatus)) {
  2303. #ifdef DEBUG
  2304. dprintf(TEXT("ACEAdd: CreateNewSecurityDescriptor failed\n"));
  2305. #endif
  2306. }
  2307. CleanupAndExit:
  2308. if (pNewAcl)
  2309. NW_FREE(pNewAcl) ;
  2310. if (pNewAce)
  2311. NW_FREE(pNewAce) ;
  2312. return ntstatus ;
  2313. } // ACEAdd
  2314. /////////////////////////////////////////////////////////////////////////
  2315. NTSTATUS
  2316. CreateNewSecurityDescriptor(
  2317. PSECURITY_DESCRIPTOR *ppNewSD,
  2318. PSECURITY_DESCRIPTOR pSD,
  2319. PACL pAcl
  2320. )
  2321. /*++
  2322. Routine Description:
  2323. From a SD and a Dacl, create a new SD. The new SD will be fully self
  2324. contained (it is self relative) and does not have pointers to other
  2325. structures.
  2326. Arguments:
  2327. ppNewSD - used to return the new SD. Caller should free with NW_FREE
  2328. pSD - the self relative SD we use to build the new SD
  2329. pAcl - the new DACL that will be used for the new SD
  2330. Return Value:
  2331. NTSTATUS code
  2332. --*/
  2333. {
  2334. PACL pSacl ;
  2335. PSID psidGroup, psidOwner ;
  2336. BOOLEAN fSaclPresent ;
  2337. BOOLEAN fSaclDefaulted, fGroupDefaulted, fOwnerDefaulted ;
  2338. ULONG NewSDSize ;
  2339. SECURITY_DESCRIPTOR NewSD ;
  2340. PSECURITY_DESCRIPTOR pNewSD ;
  2341. NTSTATUS ntstatus ;
  2342. // extract the originals from the securiry descriptor
  2343. ntstatus = RtlGetSaclSecurityDescriptor(pSD, &fSaclPresent, &pSacl, &fSaclDefaulted) ;
  2344. if (!NT_SUCCESS(ntstatus))
  2345. return ntstatus ;
  2346. ntstatus = RtlGetOwnerSecurityDescriptor(pSD, &psidOwner, &fOwnerDefaulted) ;
  2347. if (!NT_SUCCESS(ntstatus))
  2348. return ntstatus ;
  2349. ntstatus = RtlGetGroupSecurityDescriptor(pSD, &psidGroup, &fGroupDefaulted) ;
  2350. if (!NT_SUCCESS(ntstatus))
  2351. return ntstatus ;
  2352. // now create a new SD and set the info in it. we cannot return this one
  2353. // since it has pointers to old SD.
  2354. ntstatus = RtlCreateSecurityDescriptor(&NewSD, SECURITY_DESCRIPTOR_REVISION) ;
  2355. if (!NT_SUCCESS(ntstatus))
  2356. return ntstatus ;
  2357. ntstatus = RtlSetDaclSecurityDescriptor(&NewSD, TRUE, pAcl, FALSE) ;
  2358. if (!NT_SUCCESS(ntstatus))
  2359. return ntstatus ;
  2360. ntstatus = RtlSetSaclSecurityDescriptor(&NewSD, fSaclPresent, pSacl, fSaclDefaulted) ;
  2361. if (!NT_SUCCESS(ntstatus))
  2362. return ntstatus ;
  2363. ntstatus = RtlSetOwnerSecurityDescriptor(&NewSD, psidOwner, fOwnerDefaulted) ;
  2364. if (!NT_SUCCESS(ntstatus))
  2365. return ntstatus ;
  2366. ntstatus = RtlSetGroupSecurityDescriptor(&NewSD, psidGroup, fGroupDefaulted) ;
  2367. if (!NT_SUCCESS(ntstatus))
  2368. return ntstatus ;
  2369. // calculate size needed for the returned SD and allocated it
  2370. NewSDSize = RtlLengthSecurityDescriptor(&NewSD) ;
  2371. pNewSD = (PSECURITY_DESCRIPTOR) NW_ALLOC(NewSDSize) ;
  2372. if (!pNewSD)
  2373. return (STATUS_INSUFFICIENT_RESOURCES) ;
  2374. // convert the absolute to self relative
  2375. ntstatus = RtlAbsoluteToSelfRelativeSD(&NewSD, pNewSD, &NewSDSize) ;
  2376. if (NT_SUCCESS(ntstatus))
  2377. *ppNewSD = pNewSD ;
  2378. else
  2379. NW_FREE(pNewSD) ;
  2380. return ntstatus ;
  2381. } // CreateNewSecurityDescriptor
  2382. /////////////////////////////////////////////////////////////////////////
  2383. LPTSTR
  2384. NTAccessLog(
  2385. ACCESS_MASK AccessMask
  2386. )
  2387. /*++
  2388. Routine Description:
  2389. Arguments:
  2390. Return Value:
  2391. --*/
  2392. {
  2393. static TCHAR AccessDesc[80];
  2394. TCHAR AccessStr[80];
  2395. if (AccessMask == 0) {
  2396. lstrcpy(AccessDesc, Lids(IDS_L_78));
  2397. return AccessDesc;
  2398. } else
  2399. if ((AccessMask & GENERIC_ALL) == GENERIC_ALL) {
  2400. lstrcpy(AccessDesc, Lids(IDS_L_79));
  2401. return AccessDesc;
  2402. } else {
  2403. lstrcpy(AccessStr, TEXT("("));
  2404. if ((AccessMask & GENERIC_READ) == GENERIC_READ)
  2405. lstrcat(AccessStr, Lids(IDS_L_80));
  2406. if ((AccessMask & GENERIC_WRITE) == GENERIC_WRITE)
  2407. lstrcat(AccessStr, Lids(IDS_L_81));
  2408. if ((AccessMask & GENERIC_EXECUTE) == GENERIC_EXECUTE)
  2409. lstrcat(AccessStr, Lids(IDS_L_82));
  2410. if ((AccessMask & DELETE) == DELETE)
  2411. lstrcat(AccessStr, Lids(IDS_L_83));
  2412. if ((AccessMask & WRITE_DAC) == WRITE_DAC)
  2413. lstrcat(AccessStr, Lids(IDS_L_84));
  2414. lstrcat(AccessStr, TEXT(")"));
  2415. // Figured out the individual rights, now need to see if this corresponds
  2416. // to a generic mapping
  2417. if (!lstrcmpi(AccessStr, Lids(IDS_L_85))) {
  2418. lstrcpy(AccessDesc, Lids(IDS_L_86));
  2419. return AccessDesc;
  2420. }
  2421. if (!lstrcmpi(AccessStr, Lids(IDS_L_87))) {
  2422. lstrcpy(AccessDesc, Lids(IDS_L_88));
  2423. return AccessDesc;
  2424. }
  2425. if (!lstrcmpi(AccessStr, Lids(IDS_L_89))) {
  2426. lstrcpy(AccessDesc, Lids(IDS_L_90));
  2427. return AccessDesc;
  2428. }
  2429. if (!lstrcmpi(AccessStr, Lids(IDS_L_91))) {
  2430. lstrcpy(AccessDesc, Lids(IDS_L_92));
  2431. return AccessDesc;
  2432. }
  2433. wsprintf(AccessDesc, Lids(IDS_L_93), AccessStr);
  2434. }
  2435. return AccessDesc;
  2436. } // NTAccessLog
  2437. /////////////////////////////////////////////////////////////////////////
  2438. VOID
  2439. NTUserDefaultsGet(
  2440. NT_DEFAULTS **UDefaults
  2441. )
  2442. /*++
  2443. Routine Description:
  2444. Arguments:
  2445. Return Value:
  2446. --*/
  2447. {
  2448. USER_MODALS_INFO_0 *NTDefaults = NULL;
  2449. NET_API_STATUS Status = 0;
  2450. if (LocalMachine)
  2451. Status = NetUserModalsGet(NULL, 0, (LPBYTE *) &NTDefaults);
  2452. else
  2453. Status = NetUserModalsGet(CachedServer, 0, (LPBYTE *) &NTDefaults);
  2454. if (Status) {
  2455. NTDefaults = NULL;
  2456. return;
  2457. }
  2458. *UDefaults = (NT_DEFAULTS *) NTDefaults;
  2459. } // NTUserDefaultsGet
  2460. /////////////////////////////////////////////////////////////////////////
  2461. DWORD
  2462. NTUserDefaultsSet(
  2463. NT_DEFAULTS NTDefaults
  2464. )
  2465. /*++
  2466. Routine Description:
  2467. Arguments:
  2468. Return Value:
  2469. --*/
  2470. {
  2471. NET_API_STATUS Status = 0;
  2472. DWORD err;
  2473. if (LocalMachine)
  2474. Status = NetUserModalsSet(NULL, 0, (LPBYTE) &NTDefaults, &err);
  2475. else
  2476. Status = NetUserModalsSet(CachedServer, 0, (LPBYTE) &NTDefaults, &err);
  2477. return Status;
  2478. } // NTUserDefaultsSet
  2479. /////////////////////////////////////////////////////////////////////////
  2480. VOID
  2481. NTUserDefaultsLog(
  2482. NT_DEFAULTS UDefaults
  2483. )
  2484. /*++
  2485. Routine Description:
  2486. Arguments:
  2487. Return Value:
  2488. --*/
  2489. {
  2490. LogWriteLog(1, Lids(IDS_L_94), UDefaults.min_passwd_len);
  2491. // Age is in seconds, convert to days
  2492. LogWriteLog(1, Lids(IDS_L_95), UDefaults.max_passwd_age / 86400);
  2493. LogWriteLog(1, Lids(IDS_L_96), UDefaults.force_logoff);
  2494. LogWriteLog(0, Lids(IDS_CRLF));
  2495. } // NTUserDefaultsLog