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.

2764 lines
61 KiB

  1. /*++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. Helper.cpp
  5. Abstract:
  6. Various funtion encapsulate HELP user account
  7. validation, creating.
  8. Author:
  9. HueiWang 2/17/2000
  10. --*/
  11. #include "stdafx.h"
  12. #include <time.h>
  13. #include <stdio.h>
  14. #ifndef __WIN9XBUILD__
  15. #include <windows.h>
  16. #include <ntsecapi.h>
  17. #include <lmcons.h>
  18. #include <lm.h>
  19. #include <sspi.h>
  20. #include <wtsapi32.h>
  21. #include <winbase.h>
  22. #include <security.h>
  23. #endif
  24. #include "Helper.h"
  25. #ifndef __WIN9XBUILD__
  26. #if DBG
  27. void
  28. DebugPrintf(
  29. IN LPCTSTR format, ...
  30. )
  31. /*++
  32. Routine Description:
  33. sprintf() like wrapper around OutputDebugString().
  34. Parameters:
  35. hConsole : Handle to console.
  36. format : format string.
  37. Returns:
  38. None.
  39. Note:
  40. To be replace by generic tracing code.
  41. ++*/
  42. {
  43. TCHAR buf[8096]; // max. error text
  44. DWORD dump;
  45. va_list marker;
  46. va_start(marker, format);
  47. SYSTEMTIME sysTime;
  48. GetSystemTime(&sysTime);
  49. try {
  50. memset(
  51. buf,
  52. 0,
  53. sizeof(buf)
  54. );
  55. _sntprintf(
  56. buf,
  57. sizeof(buf)/sizeof(buf[0]),
  58. _TEXT(" %d [%d:%d:%d:%d:%d.%d] : "),
  59. GetCurrentThreadId(),
  60. sysTime.wMonth,
  61. sysTime.wDay,
  62. sysTime.wHour,
  63. sysTime.wMinute,
  64. sysTime.wSecond,
  65. sysTime.wMilliseconds
  66. );
  67. _vsntprintf(
  68. buf + lstrlen(buf),
  69. sizeof(buf)/sizeof(buf[0]) - lstrlen(buf),
  70. format,
  71. marker
  72. );
  73. OutputDebugString(buf);
  74. }
  75. catch(...) {
  76. }
  77. va_end(marker);
  78. return;
  79. }
  80. #endif
  81. #endif
  82. void
  83. UnixTimeToFileTime(
  84. time_t t,
  85. LPFILETIME pft
  86. )
  87. {
  88. LARGE_INTEGER li;
  89. li.QuadPart = Int32x32To64(t, 10000000) + 116444736000000000;
  90. pft->dwHighDateTime = li.HighPart;
  91. pft->dwLowDateTime = li.LowPart;
  92. }
  93. #ifndef __WIN9XBUILD__
  94. /*----------------------------------------------------------------------------
  95. Routine Description:
  96. This function checks to see whether the specified sid is enabled in
  97. the specified token.
  98. Arguments:
  99. TokenHandle - If present, this token is checked for the sid. If not
  100. present then the current effective token will be used. This must
  101. be an impersonation token.
  102. SidToCheck - The sid to check for presence in the token
  103. IsMember - If the sid is enabled in the token, contains TRUE otherwise
  104. false.
  105. Return Value:
  106. TRUE - The API completed successfully. It does not indicate that the
  107. sid is a member of the token.
  108. FALSE - The API failed. A more detailed status code can be retrieved
  109. via GetLastError()
  110. Note : Code modified from 5.0 \\rastaman\ntwin\src\base\advapi\security.c
  111. ----------------------------------------------------------------------------*/
  112. BOOL
  113. TLSCheckTokenMembership(
  114. IN HANDLE TokenHandle OPTIONAL,
  115. IN PSID SidToCheck,
  116. OUT PBOOL IsMember
  117. )
  118. {
  119. HANDLE ProcessToken = NULL;
  120. HANDLE EffectiveToken = NULL;
  121. DWORD Status = ERROR_SUCCESS;
  122. PISECURITY_DESCRIPTOR SecDesc = NULL;
  123. ULONG SecurityDescriptorSize;
  124. GENERIC_MAPPING GenericMapping = { STANDARD_RIGHTS_READ,
  125. STANDARD_RIGHTS_EXECUTE,
  126. STANDARD_RIGHTS_WRITE,
  127. STANDARD_RIGHTS_ALL };
  128. //
  129. // The size of the privilege set needs to contain the set itself plus
  130. // any privileges that may be used. The privileges that are used
  131. // are SeTakeOwnership and SeSecurity, plus one for good measure
  132. //
  133. BYTE PrivilegeSetBuffer[sizeof(PRIVILEGE_SET) + 3*sizeof(LUID_AND_ATTRIBUTES)];
  134. PPRIVILEGE_SET PrivilegeSet = (PPRIVILEGE_SET) PrivilegeSetBuffer;
  135. ULONG PrivilegeSetLength = sizeof(PrivilegeSetBuffer);
  136. ACCESS_MASK AccessGranted = 0;
  137. BOOL AccessStatus = FALSE;
  138. PACL Dacl = NULL;
  139. #define MEMBER_ACCESS 1
  140. *IsMember = FALSE;
  141. //
  142. // Get a handle to the token
  143. //
  144. if (TokenHandle != NULL)
  145. {
  146. EffectiveToken = TokenHandle;
  147. }
  148. else
  149. {
  150. if(!OpenThreadToken(GetCurrentThread(),
  151. TOKEN_QUERY,
  152. FALSE, // don't open as self
  153. &EffectiveToken))
  154. {
  155. //
  156. // if there is no thread token, try the process token
  157. //
  158. if((Status=GetLastError()) == ERROR_NO_TOKEN)
  159. {
  160. if(!OpenProcessToken(GetCurrentProcess(),
  161. TOKEN_QUERY | TOKEN_DUPLICATE,
  162. &ProcessToken))
  163. {
  164. Status = GetLastError();
  165. }
  166. //
  167. // If we have a process token, we need to convert it to an
  168. // impersonation token
  169. //
  170. if (Status == ERROR_SUCCESS)
  171. {
  172. BOOL Result;
  173. Result = DuplicateToken(ProcessToken,
  174. SecurityImpersonation,
  175. &EffectiveToken);
  176. CloseHandle(ProcessToken);
  177. if (!Result)
  178. {
  179. return(FALSE);
  180. }
  181. }
  182. }
  183. if (Status != ERROR_SUCCESS)
  184. {
  185. goto Cleanup;
  186. }
  187. }
  188. }
  189. //
  190. // Construct a security descriptor to pass to access check
  191. //
  192. //
  193. // The size is equal to the size of an SD + twice the length of the SID
  194. // (for owner and group) + size of the DACL = sizeof ACL + size of the
  195. // ACE, which is an ACE + length of
  196. // ths SID.
  197. //
  198. SecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR) +
  199. sizeof(ACCESS_ALLOWED_ACE) +
  200. sizeof(ACL) +
  201. 3 * GetLengthSid(SidToCheck);
  202. SecDesc = (PISECURITY_DESCRIPTOR) LocalAlloc(LMEM_ZEROINIT, SecurityDescriptorSize );
  203. if (SecDesc == NULL)
  204. {
  205. Status = ERROR_OUTOFMEMORY;
  206. goto Cleanup;
  207. }
  208. Dacl = (PACL) (SecDesc + 1);
  209. InitializeSecurityDescriptor(SecDesc, SECURITY_DESCRIPTOR_REVISION);
  210. //
  211. // Fill in fields of security descriptor
  212. //
  213. SetSecurityDescriptorOwner(SecDesc, SidToCheck, FALSE);
  214. SetSecurityDescriptorGroup(SecDesc, SidToCheck, FALSE);
  215. if(!InitializeAcl( Dacl,
  216. SecurityDescriptorSize - sizeof(SECURITY_DESCRIPTOR),
  217. ACL_REVISION))
  218. {
  219. Status=GetLastError();
  220. goto Cleanup;
  221. }
  222. if(!AddAccessAllowedAce(Dacl, ACL_REVISION, MEMBER_ACCESS, SidToCheck))
  223. {
  224. Status=GetLastError();
  225. goto Cleanup;
  226. }
  227. if(!SetSecurityDescriptorDacl(SecDesc, TRUE, Dacl, FALSE))
  228. {
  229. Status=GetLastError();
  230. goto Cleanup;
  231. }
  232. if(!AccessCheck(SecDesc,
  233. EffectiveToken,
  234. MEMBER_ACCESS,
  235. &GenericMapping,
  236. PrivilegeSet,
  237. &PrivilegeSetLength,
  238. &AccessGranted,
  239. &AccessStatus))
  240. {
  241. Status=GetLastError();
  242. goto Cleanup;
  243. }
  244. //
  245. // if the access check failed, then the sid is not a member of the
  246. // token
  247. //
  248. if ((AccessStatus == TRUE) && (AccessGranted == MEMBER_ACCESS))
  249. {
  250. *IsMember = TRUE;
  251. }
  252. Cleanup:
  253. if (TokenHandle == NULL && EffectiveToken != NULL)
  254. {
  255. CloseHandle(EffectiveToken);
  256. }
  257. if (SecDesc != NULL)
  258. {
  259. LocalFree(SecDesc);
  260. }
  261. return (Status == ERROR_SUCCESS) ? TRUE : FALSE;
  262. }
  263. /*------------------------------------------------------------------------
  264. BOOL IsUserAdmin(BOOL)
  265. returns TRUE if user is an admin
  266. FALSE if user is not an admin
  267. ------------------------------------------------------------------------*/
  268. DWORD
  269. IsUserAdmin(
  270. BOOL* bMember
  271. )
  272. {
  273. PSID psidAdministrators;
  274. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  275. DWORD dwStatus=ERROR_SUCCESS;
  276. do {
  277. if(!AllocateAndInitializeSid(&siaNtAuthority,
  278. 2,
  279. SECURITY_BUILTIN_DOMAIN_RID,
  280. DOMAIN_ALIAS_RID_ADMINS,
  281. 0, 0, 0, 0, 0, 0,
  282. &psidAdministrators))
  283. {
  284. dwStatus=GetLastError();
  285. continue;
  286. }
  287. // assume that we don't find the admin SID.
  288. if(!TLSCheckTokenMembership(NULL,
  289. psidAdministrators,
  290. bMember))
  291. {
  292. dwStatus=GetLastError();
  293. }
  294. FreeSid(psidAdministrators);
  295. } while(FALSE);
  296. return dwStatus;
  297. }
  298. #endif
  299. DWORD
  300. GetRandomNumber(
  301. HCRYPTPROV hProv,
  302. DWORD* pdwRandom
  303. )
  304. /*++
  305. --*/
  306. {
  307. DWORD dwStatus = ERROR_SUCCESS;
  308. if( NULL == hProv )
  309. {
  310. dwStatus = ERROR_INVALID_PARAMETER;
  311. }
  312. else
  313. {
  314. if( !CryptGenRandom(hProv, sizeof(*pdwRandom), (PBYTE)pdwRandom) )
  315. {
  316. dwStatus = GetLastError();
  317. }
  318. }
  319. MYASSERT( ERROR_SUCCESS == dwStatus );
  320. return dwStatus;
  321. }
  322. //-----------------------------------------------------
  323. DWORD
  324. ShuffleCharArray(
  325. IN HCRYPTPROV hProv,
  326. IN int iSizeOfTheArray,
  327. IN OUT TCHAR *lptsTheArray
  328. )
  329. /*++
  330. Routine Description:
  331. Random shuffle content of a char. array.
  332. Parameters:
  333. iSizeOfTheArray : Size of array.
  334. lptsTheArray : On input, the array to be randomly shuffer,
  335. on output, the shuffled array.
  336. Returns:
  337. None.
  338. Note:
  339. Code Modified from winsta\server\wstrpc.c
  340. --*/
  341. {
  342. int i;
  343. int iTotal;
  344. DWORD dwStatus = ERROR_SUCCESS;
  345. if( NULL == hProv )
  346. {
  347. dwStatus = ERROR_INVALID_PARAMETER;
  348. }
  349. else
  350. {
  351. iTotal = iSizeOfTheArray / sizeof(TCHAR);
  352. for (i = 0; i < iTotal && ERROR_SUCCESS == dwStatus; i++)
  353. {
  354. DWORD RandomNum;
  355. TCHAR c;
  356. dwStatus = GetRandomNumber(hProv, &RandomNum);
  357. if( ERROR_SUCCESS == dwStatus )
  358. {
  359. c = lptsTheArray[i];
  360. lptsTheArray[i] = lptsTheArray[RandomNum % iTotal];
  361. lptsTheArray[RandomNum % iTotal] = c;
  362. }
  363. }
  364. }
  365. return dwStatus;
  366. }
  367. //-----------------------------------------------------
  368. DWORD
  369. GenerateRandomBytes(
  370. IN DWORD dwSize,
  371. IN OUT LPBYTE pbBuffer
  372. )
  373. /*++
  374. Description:
  375. Generate fill buffer with random bytes.
  376. Parameters:
  377. dwSize : Size of buffer pbBuffer point to.
  378. pbBuffer : Pointer to buffer to hold the random bytes.
  379. Returns:
  380. TRUE/FALSE
  381. --*/
  382. {
  383. HCRYPTPROV hProv = NULL;
  384. DWORD dwStatus = ERROR_SUCCESS;
  385. //
  386. // Create a Crypto Provider to generate random number
  387. //
  388. if( !CryptAcquireContext(
  389. &hProv,
  390. NULL,
  391. NULL,
  392. PROV_RSA_FULL,
  393. CRYPT_VERIFYCONTEXT
  394. ) )
  395. {
  396. dwStatus = GetLastError();
  397. goto CLEANUPANDEXIT;
  398. }
  399. if( !CryptGenRandom(hProv, dwSize, pbBuffer) )
  400. {
  401. dwStatus = GetLastError();
  402. }
  403. CLEANUPANDEXIT:
  404. if( NULL != hProv )
  405. {
  406. CryptReleaseContext( hProv, 0 );
  407. }
  408. return dwStatus;
  409. }
  410. DWORD
  411. GenerateRandomString(
  412. IN DWORD dwSizeRandomSeed,
  413. IN OUT LPTSTR* pszRandomString
  414. )
  415. /*++
  416. --*/
  417. {
  418. PBYTE lpBuffer = NULL;
  419. DWORD dwStatus = ERROR_SUCCESS;
  420. BOOL bSuccess;
  421. DWORD cbConvertString = 0;
  422. if( 0 == dwSizeRandomSeed || NULL == pszRandomString )
  423. {
  424. dwStatus = ERROR_INVALID_PARAMETER;
  425. MYASSERT(FALSE);
  426. goto CLEANUPANDEXIT;
  427. }
  428. *pszRandomString = NULL;
  429. lpBuffer = (PBYTE)LocalAlloc( LPTR, dwSizeRandomSeed );
  430. if( NULL == lpBuffer )
  431. {
  432. dwStatus = GetLastError();
  433. goto CLEANUPANDEXIT;
  434. }
  435. dwStatus = GenerateRandomBytes( dwSizeRandomSeed, lpBuffer );
  436. if( ERROR_SUCCESS != dwStatus )
  437. {
  438. goto CLEANUPANDEXIT;
  439. }
  440. // Convert to string
  441. bSuccess = CryptBinaryToString(
  442. lpBuffer,
  443. dwSizeRandomSeed,
  444. CRYPT_STRING_BASE64,
  445. 0,
  446. &cbConvertString
  447. );
  448. if( FALSE == bSuccess )
  449. {
  450. dwStatus = GetLastError();
  451. goto CLEANUPANDEXIT;
  452. }
  453. *pszRandomString = (LPTSTR)LocalAlloc( LPTR, (cbConvertString+1)*sizeof(TCHAR) );
  454. if( NULL == *pszRandomString )
  455. {
  456. dwStatus = GetLastError();
  457. goto CLEANUPANDEXIT;
  458. }
  459. bSuccess = CryptBinaryToString(
  460. lpBuffer,
  461. dwSizeRandomSeed,
  462. CRYPT_STRING_BASE64,
  463. *pszRandomString,
  464. &cbConvertString
  465. );
  466. if( FALSE == bSuccess )
  467. {
  468. dwStatus = GetLastError();
  469. }
  470. else
  471. {
  472. if( (*pszRandomString)[cbConvertString - 1] == '\n' &&
  473. (*pszRandomString)[cbConvertString - 2] == '\r' )
  474. {
  475. (*pszRandomString)[cbConvertString - 2] = 0;
  476. }
  477. }
  478. CLEANUPANDEXIT:
  479. if( ERROR_SUCCESS != dwStatus )
  480. {
  481. if( NULL != *pszRandomString )
  482. {
  483. LocalFree(*pszRandomString);
  484. }
  485. }
  486. if( NULL != lpBuffer )
  487. {
  488. LocalFree(lpBuffer);
  489. }
  490. return dwStatus;
  491. }
  492. DWORD
  493. CreatePassword(
  494. OUT TCHAR *pszPassword
  495. )
  496. /*++
  497. Routine Description:
  498. Routine to randomly create a password.
  499. Parameters:
  500. pszPassword : Pointer to buffer to received a randomly generated
  501. password, buffer must be at least
  502. MAX_HELPACCOUNT_PASSWORD+1 characters.
  503. Returns:
  504. None.
  505. Note:
  506. Code copied from winsta\server\wstrpc.c
  507. --*/
  508. {
  509. HCRYPTPROV hProv = NULL;
  510. int nLength = MAX_HELPACCOUNT_PASSWORD;
  511. int iTotal = 0;
  512. DWORD RandomNum = 0;
  513. int i;
  514. time_t timeVal;
  515. DWORD dwStatus = ERROR_SUCCESS;
  516. TCHAR six2pr[64] =
  517. {
  518. _T('A'), _T('B'), _T('C'), _T('D'), _T('E'), _T('F'), _T('G'),
  519. _T('H'), _T('I'), _T('J'), _T('K'), _T('L'), _T('M'), _T('N'),
  520. _T('O'), _T('P'), _T('Q'), _T('R'), _T('S'), _T('T'), _T('U'),
  521. _T('V'), _T('W'), _T('X'), _T('Y'), _T('Z'), _T('a'), _T('b'),
  522. _T('c'), _T('d'), _T('e'), _T('f'), _T('g'), _T('h'), _T('i'),
  523. _T('j'), _T('k'), _T('l'), _T('m'), _T('n'), _T('o'), _T('p'),
  524. _T('q'), _T('r'), _T('s'), _T('t'), _T('u'), _T('v'), _T('w'),
  525. _T('x'), _T('y'), _T('z'), _T('0'), _T('1'), _T('2'), _T('3'),
  526. _T('4'), _T('5'), _T('6'), _T('7'), _T('8'), _T('9'), _T('*'),
  527. _T('_')
  528. };
  529. TCHAR something1[12] =
  530. {
  531. _T('!'), _T('@'), _T('#'), _T('$'), _T('^'), _T('&'), _T('*'),
  532. _T('('), _T(')'), _T('-'), _T('+'), _T('=')
  533. };
  534. TCHAR something2[10] =
  535. {
  536. _T('0'), _T('1'), _T('2'), _T('3'), _T('4'), _T('5'), _T('6'),
  537. _T('7'), _T('8'), _T('9')
  538. };
  539. TCHAR something3[26] =
  540. {
  541. _T('A'), _T('B'), _T('C'), _T('D'), _T('E'), _T('F'), _T('G'),
  542. _T('H'), _T('I'), _T('J'), _T('K'), _T('L'), _T('M'), _T('N'),
  543. _T('O'), _T('P'), _T('Q'), _T('R'), _T('S'), _T('T'), _T('U'),
  544. _T('V'), _T('W'), _T('X'), _T('Y'), _T('Z')
  545. };
  546. TCHAR something4[26] =
  547. {
  548. _T('a'), _T('b'), _T('c'), _T('d'), _T('e'), _T('f'), _T('g'),
  549. _T('h'), _T('i'), _T('j'), _T('k'), _T('l'), _T('m'), _T('n'),
  550. _T('o'), _T('p'), _T('q'), _T('r'), _T('s'), _T('t'), _T('u'),
  551. _T('v'), _T('w'), _T('x'), _T('y'), _T('z')
  552. };
  553. //
  554. // Create a Crypto Provider to generate random number
  555. //
  556. if( !CryptAcquireContext(
  557. &hProv,
  558. NULL,
  559. NULL,
  560. PROV_RSA_FULL,
  561. CRYPT_VERIFYCONTEXT
  562. ) )
  563. {
  564. dwStatus = GetLastError();
  565. goto CLEANUPANDEXIT;
  566. }
  567. //
  568. // Shuffle around the six2pr[] array.
  569. //
  570. dwStatus = ShuffleCharArray(hProv, sizeof(six2pr), six2pr);
  571. if( ERROR_SUCCESS != dwStatus )
  572. {
  573. goto CLEANUPANDEXIT;
  574. }
  575. //
  576. // Assign each character of the password array.
  577. //
  578. iTotal = sizeof(six2pr) / sizeof(TCHAR);
  579. for (i=0; i<nLength && ERROR_SUCCESS == dwStatus; i++)
  580. {
  581. dwStatus = GetRandomNumber(hProv, &RandomNum);
  582. if( ERROR_SUCCESS == dwStatus )
  583. {
  584. pszPassword[i]=six2pr[RandomNum%iTotal];
  585. }
  586. }
  587. if( ERROR_SUCCESS != dwStatus )
  588. {
  589. MYASSERT(FALSE);
  590. goto CLEANUPANDEXIT;
  591. }
  592. //
  593. // In order to meet a possible policy set upon passwords, replace chars
  594. // 2 through 5 with these:
  595. //
  596. // 1) something from !@#$%^&*()-+=
  597. // 2) something from 1234567890
  598. // 3) an uppercase letter
  599. // 4) a lowercase letter
  600. //
  601. dwStatus = ShuffleCharArray(hProv, sizeof(something1), (TCHAR*)&something1);
  602. if( ERROR_SUCCESS != dwStatus )
  603. {
  604. goto CLEANUPANDEXIT;
  605. }
  606. dwStatus = ShuffleCharArray(hProv, sizeof(something2), (TCHAR*)&something2);
  607. if( ERROR_SUCCESS != dwStatus )
  608. {
  609. goto CLEANUPANDEXIT;
  610. }
  611. dwStatus = ShuffleCharArray(hProv, sizeof(something3), (TCHAR*)&something3);
  612. if( ERROR_SUCCESS != dwStatus )
  613. {
  614. goto CLEANUPANDEXIT;
  615. }
  616. dwStatus = ShuffleCharArray(hProv, sizeof(something4), (TCHAR*)&something4);
  617. if( ERROR_SUCCESS != dwStatus )
  618. {
  619. goto CLEANUPANDEXIT;
  620. }
  621. dwStatus = GetRandomNumber(hProv, &RandomNum);
  622. if( ERROR_SUCCESS != dwStatus )
  623. {
  624. goto CLEANUPANDEXIT;
  625. }
  626. iTotal = sizeof(something1) / sizeof(TCHAR);
  627. pszPassword[2] = something1[RandomNum % iTotal];
  628. dwStatus = GetRandomNumber(hProv, &RandomNum);
  629. if( ERROR_SUCCESS != dwStatus )
  630. {
  631. goto CLEANUPANDEXIT;
  632. }
  633. iTotal = sizeof(something2) / sizeof(TCHAR);
  634. pszPassword[3] = something2[RandomNum % iTotal];
  635. dwStatus = GetRandomNumber(hProv, &RandomNum);
  636. if( ERROR_SUCCESS != dwStatus )
  637. {
  638. goto CLEANUPANDEXIT;
  639. }
  640. iTotal = sizeof(something3) / sizeof(TCHAR);
  641. pszPassword[4] = something3[RandomNum % iTotal];
  642. dwStatus = GetRandomNumber(hProv, &RandomNum);
  643. if( ERROR_SUCCESS != dwStatus )
  644. {
  645. goto CLEANUPANDEXIT;
  646. }
  647. iTotal = sizeof(something4) / sizeof(TCHAR);
  648. pszPassword[5] = something4[RandomNum % iTotal];
  649. pszPassword[nLength] = _T('\0');
  650. CLEANUPANDEXIT:
  651. if( NULL != hProv )
  652. {
  653. CryptReleaseContext( hProv, 0 );
  654. }
  655. return dwStatus;
  656. }
  657. //--------------------------------------------------------
  658. #ifndef __WIN9XBUILD__
  659. BOOL
  660. LookupAliasFromRid(
  661. LPWSTR pTargetComputer,
  662. DWORD Rid,
  663. LPWSTR pName,
  664. PDWORD cchName
  665. )
  666. {
  667. BOOL fRet;
  668. PSID pSid = NULL;
  669. SID_IDENTIFIER_AUTHORITY SidIdentifierAuthority = SECURITY_NT_AUTHORITY;
  670. SID_NAME_USE SidNameUse;
  671. ULONG cchDomainName;
  672. WCHAR szDomainName[256];
  673. //
  674. // Sid is the same regardless of machine, since the well-known
  675. // BUILTIN domain is referenced.
  676. //
  677. fRet = AllocateAndInitializeSid(
  678. &SidIdentifierAuthority,
  679. 2,
  680. SECURITY_BUILTIN_DOMAIN_RID,
  681. Rid,
  682. 0, 0, 0, 0, 0, 0,
  683. &pSid
  684. );
  685. if (fRet)
  686. {
  687. cchDomainName = sizeof(szDomainName)/sizeof(szDomainName);
  688. fRet = LookupAccountSidW(
  689. pTargetComputer,
  690. pSid,
  691. pName,
  692. cchName,
  693. szDomainName,
  694. &cchDomainName,
  695. &SidNameUse
  696. );
  697. FreeSid(pSid);
  698. }
  699. return(fRet);
  700. }
  701. DWORD
  702. IsUserInLocalGroup(
  703. IN PBYTE pbUserSid,
  704. IN LPCTSTR pszLocalGroup,
  705. OUT BOOL* pbInGroup
  706. )
  707. /*++
  708. Routine Description:
  709. Check if user is member of specific local group.
  710. Parameters:
  711. pbUserSid : SID of user to be verified.
  712. pszLocalGroup : Name of local group.
  713. pbInGroup : Return TRUE if user is in group, FALSE otherwise.
  714. Returns:
  715. ERROR_SUCCESS or error code, membership is returned via pbInGroup
  716. parameter.
  717. Note:
  718. If 'everyone' is member of the specfied group, routine will
  719. immediately return SUCCESS.
  720. --*/
  721. {
  722. NET_API_STATUS netErr;
  723. LOCALGROUP_MEMBERS_INFO_0* pBuf=NULL;
  724. SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
  725. PSID pEveryoneSID = NULL;
  726. DWORD dwEntries;
  727. DWORD dwTotal;
  728. *pbInGroup = FALSE;
  729. //
  730. // By default add everyone to the group
  731. //
  732. if(AllocateAndInitializeSid( &SIDAuthWorld, 1,
  733. SECURITY_WORLD_RID,
  734. 0, 0, 0, 0, 0, 0, 0,
  735. &pEveryoneSID) )
  736. {
  737. //
  738. // Retrieve group member.
  739. //
  740. netErr = NetLocalGroupGetMembers(
  741. NULL,
  742. pszLocalGroup,
  743. 0,
  744. (LPBYTE *)&pBuf,
  745. MAX_PREFERRED_LENGTH,
  746. &dwEntries,
  747. &dwTotal,
  748. NULL
  749. );
  750. if( NERR_Success == netErr )
  751. {
  752. for(DWORD index=0; index < dwEntries; index++ )
  753. {
  754. if(TRUE == EqualSid( pEveryoneSID, pBuf[index].lgrmi0_sid) )
  755. {
  756. *pbInGroup = TRUE;
  757. break;
  758. }
  759. if(NULL != pbUserSid && TRUE == EqualSid( pbUserSid, pBuf[index].lgrmi0_sid) )
  760. {
  761. *pbInGroup = TRUE;
  762. break;
  763. }
  764. }
  765. NetApiBufferFree( pBuf );
  766. }
  767. FreeSid( pEveryoneSID );
  768. }
  769. else
  770. {
  771. netErr = GetLastError();
  772. }
  773. return netErr;
  774. }
  775. BOOL
  776. IsLocalGroupExists(
  777. IN LPWSTR pszGroupName
  778. )
  779. /*++
  780. Routine Description:
  781. Verify if local group exist on machine.
  782. Parameter:
  783. pszGroupName : Name of the group to be checked.
  784. Returns:
  785. TRUE/FALSE
  786. --*/
  787. {
  788. LOCALGROUP_INFO_1* pGroupInfo1;
  789. NET_API_STATUS netStatus;
  790. BOOL bGroupExists;
  791. //
  792. // Check to see if group exists
  793. //
  794. netStatus = NetLocalGroupGetInfo(
  795. NULL,
  796. pszGroupName,
  797. 1,
  798. (PBYTE *)&pGroupInfo1
  799. );
  800. if( NERR_Success == netStatus )
  801. {
  802. NetApiBufferFree(pGroupInfo1);
  803. }
  804. else
  805. {
  806. SetLastError( netStatus );
  807. }
  808. return ( NERR_Success == netStatus );
  809. }
  810. //---------------------------------------------------------
  811. DWORD
  812. CreateLocalGroup(
  813. IN LPWSTR pszGroupName,
  814. IN LPWSTR pszGroupDesc,
  815. IN BOOL bAddEveryone
  816. )
  817. /*++
  818. Routine Description:
  819. Create a group on local machine.
  820. Parameters:
  821. pszGroupName : Group name.
  822. pszGroupDesc : Group desc.
  823. bAddEveryone : TRUE if add 'everyone' to the group, FALSE
  824. otherwise.
  825. Returns:
  826. ERROR_SUCCESS or error code
  827. --*/
  828. {
  829. NET_API_STATUS netStatus;
  830. LOCALGROUP_INFO_1 GroupInfo;
  831. DWORD dwParmErr;
  832. GroupInfo.lgrpi1_name = pszGroupName;
  833. GroupInfo.lgrpi1_comment = pszGroupDesc;
  834. netStatus = NetLocalGroupAdd(
  835. NULL,
  836. 1,
  837. (LPBYTE)&GroupInfo,
  838. &dwParmErr
  839. );
  840. if( NERR_Success == netStatus )
  841. {
  842. if(FALSE == IsLocalGroupExists(pszGroupName))
  843. {
  844. // We have big problem
  845. netStatus = GetLastError();
  846. }
  847. }
  848. if( NERR_Success == netStatus && TRUE == bAddEveryone )
  849. {
  850. LOCALGROUP_MEMBERS_INFO_0 gmember;
  851. SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
  852. PSID pEveryoneSID = NULL;
  853. //
  854. // add everyone to the group
  855. //
  856. if(AllocateAndInitializeSid( &SIDAuthWorld, 1,
  857. SECURITY_WORLD_RID,
  858. 0, 0, 0, 0, 0, 0, 0,
  859. &pEveryoneSID) )
  860. {
  861. gmember.lgrmi0_sid = pEveryoneSID;
  862. bAddEveryone = NetLocalGroupAddMembers(
  863. NULL,
  864. pszGroupName,
  865. 0,
  866. (PBYTE)&gmember,
  867. 1
  868. );
  869. if( ERROR_MEMBER_IN_ALIAS == netStatus )
  870. {
  871. // ignore this error
  872. netStatus = NERR_Success;
  873. }
  874. FreeSid( pEveryoneSID );
  875. }
  876. }
  877. return netStatus;
  878. }
  879. //---------------------------------------------------------
  880. DWORD
  881. RenameLocalAccount(
  882. IN LPWSTR pszOrgName,
  883. IN LPWSTR pszNewName
  884. )
  885. /*++
  886. Routine Description:
  887. Parameters:
  888. Returns:
  889. ERROR_SUCCESS or error code.
  890. --*/
  891. {
  892. NET_API_STATUS err;
  893. USER_INFO_0 UserInfo;
  894. UserInfo.usri0_name = pszNewName;
  895. err = NetUserSetInfo(
  896. NULL,
  897. pszOrgName,
  898. 0,
  899. (LPBYTE) &UserInfo,
  900. NULL
  901. );
  902. return err;
  903. }
  904. DWORD
  905. UpdateLocalAccountFullnameAndDesc(
  906. IN LPWSTR pszAccOrgName,
  907. IN LPWSTR pszAccFullName,
  908. IN LPWSTR pszAccDesc
  909. )
  910. /*++
  911. Routine Description:
  912. Update account full name and description.
  913. Parameters:
  914. pszAccName : Account name.
  915. pszAccFullName : new account full name.
  916. pszAccDesc : new account description.
  917. Returns:
  918. ERROR_SUCCESS or error code
  919. --*/
  920. {
  921. LPBYTE pbServer = NULL;
  922. BYTE *pBuffer;
  923. NET_API_STATUS netErr = NERR_Success;
  924. DWORD parm_err;
  925. netErr = NetUserGetInfo(
  926. NULL,
  927. pszAccOrgName,
  928. 3,
  929. &pBuffer
  930. );
  931. if( NERR_Success == netErr )
  932. {
  933. USER_INFO_3 *lpui3 = (USER_INFO_3 *)pBuffer;
  934. lpui3->usri3_comment = pszAccDesc;
  935. lpui3->usri3_full_name = pszAccFullName;
  936. netErr = NetUserSetInfo(
  937. NULL,
  938. pszAccOrgName,
  939. 3,
  940. (PBYTE)lpui3,
  941. &parm_err
  942. );
  943. NetApiBufferFree(pBuffer);
  944. }
  945. return netErr;
  946. }
  947. DWORD
  948. IsLocalAccountEnabled(
  949. IN LPWSTR pszUserName,
  950. IN BOOL* pEnabled
  951. )
  952. /*++
  953. Routine Description:
  954. Check if local account enabled
  955. Parameters:
  956. pszUserName : Name of user account.
  957. pEnabled : Return TRUE is account is enabled, FALSE otherwise.
  958. Returns:
  959. ERROR_SUCCESS or error code.
  960. --*/
  961. {
  962. DWORD dwResult;
  963. NET_API_STATUS err;
  964. LPBYTE pBuffer;
  965. USER_INFO_1 *pUserInfo;
  966. err = NetUserGetInfo(
  967. NULL,
  968. pszUserName,
  969. 1,
  970. &pBuffer
  971. );
  972. if( NERR_Success == err )
  973. {
  974. pUserInfo = (USER_INFO_1 *)pBuffer;
  975. if (pUserInfo != NULL)
  976. {
  977. if( pUserInfo->usri1_flags & UF_ACCOUNTDISABLE )
  978. {
  979. *pEnabled = FALSE;
  980. }
  981. else
  982. {
  983. *pEnabled = TRUE;
  984. }
  985. }
  986. NetApiBufferFree( pBuffer );
  987. }
  988. else if( NERR_UserNotFound == err )
  989. {
  990. *pEnabled = FALSE;
  991. //err = NERR_Success;
  992. }
  993. return err;
  994. }
  995. //---------------------------------------------------------
  996. DWORD
  997. EnableLocalAccount(
  998. IN LPWSTR pszUserName,
  999. IN BOOL bEnable
  1000. )
  1001. /*++
  1002. Routine Description:
  1003. Routine to enable/disable a local account.
  1004. Parameters:
  1005. pszUserName : Name of user account.
  1006. bEnable : TRUE if enabling account, FALSE if disabling account.
  1007. Returns:
  1008. ERROR_SUCCESS or error code.
  1009. --*/
  1010. {
  1011. DWORD dwResult;
  1012. NET_API_STATUS err;
  1013. LPBYTE pBuffer;
  1014. USER_INFO_1 *pUserInfo;
  1015. BOOL bChangeAccStatus = TRUE;
  1016. err = NetUserGetInfo(
  1017. NULL,
  1018. pszUserName,
  1019. 1,
  1020. &pBuffer
  1021. );
  1022. if( NERR_Success == err )
  1023. {
  1024. pUserInfo = (USER_INFO_1 *)pBuffer;
  1025. if(pUserInfo != NULL)
  1026. {
  1027. if( TRUE == bEnable && pUserInfo->usri1_flags & UF_ACCOUNTDISABLE )
  1028. {
  1029. pUserInfo->usri1_flags &= ~UF_ACCOUNTDISABLE;
  1030. }
  1031. else if( FALSE == bEnable && !(pUserInfo->usri1_flags & UF_ACCOUNTDISABLE) )
  1032. {
  1033. pUserInfo->usri1_flags |= UF_ACCOUNTDISABLE;
  1034. }
  1035. else
  1036. {
  1037. bChangeAccStatus = FALSE;
  1038. }
  1039. if( TRUE == bChangeAccStatus )
  1040. {
  1041. err = NetUserSetInfo(
  1042. NULL,
  1043. pszUserName,
  1044. 1,
  1045. pBuffer,
  1046. &dwResult
  1047. );
  1048. }
  1049. }
  1050. NetApiBufferFree( pBuffer );
  1051. }
  1052. return err;
  1053. }
  1054. //---------------------------------------------------------
  1055. BOOL
  1056. IsPersonalOrProMachine()
  1057. /*++
  1058. Routine Description:
  1059. Check if machine is PER or PRO sku.
  1060. Parameters:
  1061. None.
  1062. Return:
  1063. TRUE/FALSE
  1064. --*/
  1065. {
  1066. OSVERSIONINFOEX osVersionInfo;
  1067. DWORDLONG dwlConditionMask = 0;
  1068. BOOL bSuccess;
  1069. ZeroMemory(
  1070. &osVersionInfo,
  1071. sizeof(OSVERSIONINFOEX)
  1072. );
  1073. osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  1074. osVersionInfo.wProductType = VER_NT_SERVER;
  1075. VER_SET_CONDITION(dwlConditionMask, VER_PRODUCT_TYPE, VER_EQUAL);
  1076. bSuccess= VerifyVersionInfo(
  1077. &osVersionInfo,
  1078. VER_PRODUCT_TYPE,
  1079. dwlConditionMask
  1080. );
  1081. return !bSuccess;
  1082. }
  1083. DWORD
  1084. CreateLocalAccount(
  1085. IN LPWSTR pszUserName,
  1086. IN LPWSTR pszUserPwd,
  1087. IN LPWSTR pszFullName,
  1088. IN LPWSTR pszComment,
  1089. IN LPWSTR pszGroup,
  1090. IN LPWSTR pszScript,
  1091. OUT BOOL* pbAccountExist
  1092. )
  1093. /*++
  1094. Routine Description:
  1095. Create an user account on local machine.
  1096. Parameters:
  1097. pszUserName : Name of the user account.
  1098. pszUserPwd : User account password.
  1099. pszFullName : Account Full Name.
  1100. pszComment : Account comment.
  1101. pszGroup : Local group of the account.
  1102. pbAccountExist ; Return TRUE if account already exists, FALSE otherwise.
  1103. Returns:
  1104. ERROR_SUCCESS or error code.
  1105. --*/
  1106. {
  1107. LPBYTE pbServer = NULL;
  1108. BYTE *pBuffer;
  1109. NET_API_STATUS netErr = NERR_Success;
  1110. DWORD parm_err;
  1111. DWORD dwStatus;
  1112. netErr = NetUserGetInfo(
  1113. NULL,
  1114. pszUserName,
  1115. 3,
  1116. &pBuffer
  1117. );
  1118. if( NERR_Success == netErr )
  1119. {
  1120. //
  1121. // User account exists, if account is disabled,
  1122. // enable it and change password
  1123. //
  1124. USER_INFO_3 *lpui3 = (USER_INFO_3 *)pBuffer;
  1125. if( lpui3->usri3_flags & UF_ACCOUNTDISABLE ||
  1126. lpui3->usri3_flags & UF_LOCKOUT )
  1127. {
  1128. // enable the account
  1129. lpui3->usri3_flags &= ~ ~UF_LOCKOUT;;
  1130. if( lpui3->usri3_flags & UF_ACCOUNTDISABLE )
  1131. {
  1132. // we only reset password if account is disabled.
  1133. lpui3->usri3_flags &= ~ UF_ACCOUNTDISABLE;
  1134. }
  1135. //lpui3->usri3_password = pszUserPwd;
  1136. // reset password if account is disabled.
  1137. lpui3->usri3_name = pszUserName;
  1138. lpui3->usri3_comment = pszComment;
  1139. lpui3->usri3_full_name = pszFullName;
  1140. //lpui3->usri3_primary_group_id = dwGroupId;
  1141. netErr = NetUserSetInfo(
  1142. NULL,
  1143. pszUserName,
  1144. 3,
  1145. (PBYTE)lpui3,
  1146. &parm_err
  1147. );
  1148. }
  1149. *pbAccountExist = TRUE;
  1150. NetApiBufferFree(pBuffer);
  1151. }
  1152. else if( NERR_UserNotFound == netErr )
  1153. {
  1154. //
  1155. // Account does not exist, create and set it to our group
  1156. //
  1157. USER_INFO_1 UserInfo;
  1158. memset(&UserInfo, 0, sizeof(USER_INFO_1));
  1159. UserInfo.usri1_name = pszUserName;
  1160. UserInfo.usri1_password = pszUserPwd;
  1161. UserInfo.usri1_priv = USER_PRIV_USER; // see USER_INFO_1 for detail
  1162. UserInfo.usri1_comment = pszComment;
  1163. UserInfo.usri1_flags = UF_PASSWD_CANT_CHANGE | UF_DONT_EXPIRE_PASSWD;
  1164. netErr = NetUserAdd(
  1165. NULL,
  1166. 1,
  1167. (PBYTE)&UserInfo,
  1168. &parm_err
  1169. );
  1170. *pbAccountExist = FALSE;
  1171. }
  1172. return netErr;
  1173. }
  1174. ///////////////////////////////////////////////////////////////////////////////
  1175. DWORD
  1176. ChangeLocalAccountPassword(
  1177. IN LPWSTR pszAccName,
  1178. IN LPWSTR pszOldPwd,
  1179. IN LPWSTR pszNewPwd
  1180. )
  1181. /*++
  1182. Routine Description:
  1183. Change password of a local account.
  1184. Parameters:
  1185. pszAccName : Name of user account.
  1186. pszOldPwd : Old password.
  1187. pszNewPwd : New password.
  1188. Returns:
  1189. ERROR_SUCCESS or error code.
  1190. Notes:
  1191. User NetUserChangePassword(), must have priviledge
  1192. --*/
  1193. {
  1194. USER_INFO_1003 sUserInfo3;
  1195. NET_API_STATUS netErr;
  1196. UNREFERENCED_PARAMETER( pszOldPwd );
  1197. sUserInfo3.usri1003_password = pszNewPwd;
  1198. netErr = NetUserSetInfo(
  1199. NULL,
  1200. pszAccName,
  1201. 1003,
  1202. (BYTE *) &sUserInfo3,
  1203. 0
  1204. );
  1205. return netErr;
  1206. }
  1207. ///////////////////////////////////////////////////////////////////////////////
  1208. DWORD
  1209. RetrieveKeyFromLSA(
  1210. IN PWCHAR pwszKeyName,
  1211. OUT PBYTE * ppbKey,
  1212. OUT DWORD * pcbKey
  1213. )
  1214. /*++
  1215. Routine Description:
  1216. Retrieve private data previously stored with StoreKeyWithLSA().
  1217. Parameters:
  1218. pwszKeyName : Name of the key.
  1219. ppbKey : Pointer to PBYTE to receive binary data.
  1220. pcbKey : Size of binary data.
  1221. Returns:
  1222. ERROR_SUCCESS
  1223. ERROR_INVALID_PARAMETER.
  1224. ERROR_FILE_NOT_FOUND
  1225. LSA return code
  1226. Note:
  1227. Memory is allocated using LocalAlloc()
  1228. --*/
  1229. {
  1230. LSA_HANDLE PolicyHandle;
  1231. UNICODE_STRING SecretKeyName;
  1232. UNICODE_STRING *pSecretData;
  1233. DWORD Status;
  1234. if( ( NULL == pwszKeyName ) || ( NULL == ppbKey ) || ( NULL == pcbKey ) )
  1235. {
  1236. return( ERROR_INVALID_PARAMETER );
  1237. }
  1238. //
  1239. // setup the UNICODE_STRINGs for the call.
  1240. //
  1241. InitLsaString(
  1242. &SecretKeyName,
  1243. pwszKeyName
  1244. );
  1245. Status = OpenPolicy(
  1246. NULL,
  1247. POLICY_GET_PRIVATE_INFORMATION,
  1248. &PolicyHandle
  1249. );
  1250. if( Status != ERROR_SUCCESS )
  1251. {
  1252. return LsaNtStatusToWinError(Status);
  1253. }
  1254. Status = LsaRetrievePrivateData(
  1255. PolicyHandle,
  1256. &SecretKeyName,
  1257. &pSecretData
  1258. );
  1259. LsaClose( PolicyHandle );
  1260. if( Status != ERROR_SUCCESS )
  1261. {
  1262. return LsaNtStatusToWinError(Status);
  1263. }
  1264. if(pSecretData->Length)
  1265. {
  1266. *ppbKey = ( LPBYTE )LocalAlloc( LPTR, pSecretData->Length );
  1267. if( *ppbKey )
  1268. {
  1269. *pcbKey = pSecretData->Length;
  1270. CopyMemory( *ppbKey, pSecretData->Buffer, pSecretData->Length );
  1271. Status = ERROR_SUCCESS;
  1272. }
  1273. else
  1274. {
  1275. Status = GetLastError();
  1276. }
  1277. }
  1278. else
  1279. {
  1280. Status = ERROR_FILE_NOT_FOUND;
  1281. *pcbKey = 0;
  1282. *ppbKey = NULL;
  1283. }
  1284. ZeroMemory( pSecretData->Buffer, pSecretData->Length );
  1285. LsaFreeMemory( pSecretData );
  1286. return Status;
  1287. }
  1288. ///////////////////////////////////////////////////////////////////////////////
  1289. DWORD
  1290. StoreKeyWithLSA(
  1291. IN PWCHAR pwszKeyName,
  1292. IN BYTE * pbKey,
  1293. IN DWORD cbKey
  1294. )
  1295. /*++
  1296. Routine Description:
  1297. Save private data to LSA.
  1298. Parameters:
  1299. pwszKeyName : Name of the key this data going to be stored under.
  1300. pbKey : Binary data to be saved.
  1301. cbKey : Size of binary data.
  1302. Returns:
  1303. ERROR_SUCCESS
  1304. ERROR_INVALID_PARAMETER.
  1305. LSA return code
  1306. --*/
  1307. {
  1308. LSA_HANDLE PolicyHandle;
  1309. UNICODE_STRING SecretKeyName;
  1310. UNICODE_STRING SecretData;
  1311. DWORD Status;
  1312. if( ( NULL == pwszKeyName ) )
  1313. {
  1314. return( ERROR_INVALID_PARAMETER );
  1315. }
  1316. //
  1317. // setup the UNICODE_STRINGs for the call.
  1318. //
  1319. InitLsaString(
  1320. &SecretKeyName,
  1321. pwszKeyName
  1322. );
  1323. SecretData.Buffer = ( LPWSTR )pbKey;
  1324. SecretData.Length = ( USHORT )cbKey;
  1325. SecretData.MaximumLength = ( USHORT )cbKey;
  1326. Status = OpenPolicy(
  1327. NULL,
  1328. POLICY_CREATE_SECRET,
  1329. &PolicyHandle
  1330. );
  1331. if( Status != ERROR_SUCCESS )
  1332. {
  1333. return LsaNtStatusToWinError(Status);
  1334. }
  1335. Status = LsaStorePrivateData(
  1336. PolicyHandle,
  1337. &SecretKeyName,
  1338. &SecretData
  1339. );
  1340. LsaClose(PolicyHandle);
  1341. return LsaNtStatusToWinError(Status);
  1342. }
  1343. ///////////////////////////////////////////////////////////////////////////////
  1344. DWORD
  1345. OpenPolicy(
  1346. IN LPWSTR ServerName,
  1347. IN DWORD DesiredAccess,
  1348. OUT PLSA_HANDLE PolicyHandle
  1349. )
  1350. /*++
  1351. Routine Description:
  1352. Create/return a LSA policy handle.
  1353. Parameters:
  1354. ServerName : Name of server, refer to LsaOpenPolicy().
  1355. DesiredAccess : Desired access level, refer to LsaOpenPolicy().
  1356. PolicyHandle : Return PLSA_HANDLE.
  1357. Returns:
  1358. ERROR_SUCCESS or LSA error code
  1359. --*/
  1360. {
  1361. LSA_OBJECT_ATTRIBUTES ObjectAttributes;
  1362. LSA_UNICODE_STRING ServerString;
  1363. PLSA_UNICODE_STRING Server;
  1364. //
  1365. // Always initialize the object attributes to all zeroes.
  1366. //
  1367. ZeroMemory( &ObjectAttributes, sizeof( ObjectAttributes ) );
  1368. if( NULL != ServerName )
  1369. {
  1370. //
  1371. // Make a LSA_UNICODE_STRING out of the LPWSTR passed in
  1372. //
  1373. InitLsaString( &ServerString, ServerName );
  1374. Server = &ServerString;
  1375. }
  1376. else
  1377. {
  1378. Server = NULL;
  1379. }
  1380. //
  1381. // Attempt to open the policy.
  1382. //
  1383. return( LsaOpenPolicy(
  1384. Server,
  1385. &ObjectAttributes,
  1386. DesiredAccess,
  1387. PolicyHandle ) );
  1388. }
  1389. ///////////////////////////////////////////////////////////////////////////////
  1390. void
  1391. InitLsaString(
  1392. IN OUT PLSA_UNICODE_STRING LsaString,
  1393. IN LPWSTR String
  1394. )
  1395. /*++
  1396. Routine Description:
  1397. Initialize LSA unicode string.
  1398. Parameters:
  1399. LsaString : Pointer to LSA_UNICODE_STRING to be initialized.
  1400. String : String to initialize LsaString.
  1401. Returns:
  1402. None.
  1403. Note:
  1404. Refer to LSA_UNICODE_STRING
  1405. --*/
  1406. {
  1407. DWORD StringLength;
  1408. if( NULL == String )
  1409. {
  1410. LsaString->Buffer = NULL;
  1411. LsaString->Length = 0;
  1412. LsaString->MaximumLength = 0;
  1413. return;
  1414. }
  1415. StringLength = lstrlenW( String );
  1416. LsaString->Buffer = String;
  1417. LsaString->Length = ( USHORT ) StringLength * sizeof( WCHAR );
  1418. LsaString->MaximumLength=( USHORT )( StringLength + 1 ) * sizeof( WCHAR );
  1419. }
  1420. //-----------------------------------------------------
  1421. BOOL
  1422. ValidatePassword(
  1423. IN LPWSTR pszUserName,
  1424. IN LPWSTR pszDomain,
  1425. IN LPWSTR pszPassword
  1426. )
  1427. /*++
  1428. Routine Description:
  1429. Validate user account password.
  1430. Parameters:
  1431. pszUserName : Name of user account.
  1432. pszDomain : Domain name.
  1433. pszPassword : Password to be verified.
  1434. Returns:
  1435. TRUE or FALSE.
  1436. Note:
  1437. To debug this code, you will need to run process as service in order
  1438. for it to verify password. Refer to MSDN on LogonUser
  1439. --*/
  1440. {
  1441. HANDLE hToken;
  1442. BOOL bSuccess;
  1443. //
  1444. // To debug this code, you will need to run process as service in order
  1445. // for it to verify password. Refer to MSDN on LogonUser
  1446. //
  1447. bSuccess = LogonUser(
  1448. pszUserName,
  1449. pszDomain, //_TEXT("."), //pszDomain,
  1450. pszPassword,
  1451. LOGON32_LOGON_NETWORK_CLEARTEXT,
  1452. LOGON32_PROVIDER_DEFAULT,
  1453. &hToken
  1454. );
  1455. if( TRUE == bSuccess )
  1456. {
  1457. CloseHandle( hToken );
  1458. }
  1459. else
  1460. {
  1461. DWORD dwStatus = GetLastError();
  1462. DebugPrintf(
  1463. _TEXT("ValidatePassword() failed with %d\n"),
  1464. dwStatus
  1465. );
  1466. SetLastError(dwStatus);
  1467. }
  1468. return bSuccess;
  1469. }
  1470. //---------------------------------------------------------------
  1471. BOOL
  1472. GetTextualSid(
  1473. IN PSID pSid, // binary Sid
  1474. IN OUT LPTSTR TextualSid, // buffer for Textual representation of Sid
  1475. IN OUT LPDWORD lpdwBufferLen // required/provided TextualSid buffersize
  1476. )
  1477. /*++
  1478. Routine Description:
  1479. Conver a SID to string representation, code from MSDN
  1480. Parameters:
  1481. pSid : Pointer to SID to be converted to string.
  1482. TextualSid : On input, pointer to buffer to received converted string, on output,
  1483. converted SID in string form.
  1484. lpdwBufferLen : On input, size of the buffer, on output, length of converted string
  1485. or required buffer size in char.
  1486. Returns:
  1487. TRUE/FALSE, use GetLastError() to retrieve detail error code.
  1488. --*/
  1489. {
  1490. PSID_IDENTIFIER_AUTHORITY psia;
  1491. DWORD dwSubAuthorities;
  1492. DWORD dwSidRev=SID_REVISION;
  1493. DWORD dwCounter;
  1494. DWORD dwSidSize;
  1495. // Validate the binary SID.
  1496. if(!IsValidSid(pSid))
  1497. {
  1498. return FALSE;
  1499. }
  1500. // Get the identifier authority value from the SID.
  1501. psia = GetSidIdentifierAuthority(pSid);
  1502. // Get the number of subauthorities in the SID.
  1503. dwSubAuthorities = *GetSidSubAuthorityCount(pSid);
  1504. // Compute the buffer length.
  1505. // S-SID_REVISION- + IdentifierAuthority- + subauthorities- + NULL
  1506. dwSidSize=(15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR);
  1507. // Check input buffer length.
  1508. // If too small, indicate the proper size and set last error.
  1509. if (*lpdwBufferLen < dwSidSize)
  1510. {
  1511. *lpdwBufferLen = dwSidSize;
  1512. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1513. return FALSE;
  1514. }
  1515. // Add 'S' prefix and revision number to the string.
  1516. dwSidSize=wsprintf(TextualSid, TEXT("S-%lu-"), dwSidRev );
  1517. // Add SID identifier authority to the string.
  1518. if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) )
  1519. {
  1520. dwSidSize+=wsprintf(TextualSid + lstrlen(TextualSid),
  1521. TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
  1522. (USHORT)psia->Value[0],
  1523. (USHORT)psia->Value[1],
  1524. (USHORT)psia->Value[2],
  1525. (USHORT)psia->Value[3],
  1526. (USHORT)psia->Value[4],
  1527. (USHORT)psia->Value[5]);
  1528. }
  1529. else
  1530. {
  1531. dwSidSize+=wsprintf(TextualSid + lstrlen(TextualSid),
  1532. TEXT("%lu"),
  1533. (ULONG)(psia->Value[5] ) +
  1534. (ULONG)(psia->Value[4] << 8) +
  1535. (ULONG)(psia->Value[3] << 16) +
  1536. (ULONG)(psia->Value[2] << 24) );
  1537. }
  1538. // Add SID subauthorities to the string.
  1539. //
  1540. for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++)
  1541. {
  1542. dwSidSize+=wsprintf(TextualSid + dwSidSize, TEXT("-%lu"),
  1543. *GetSidSubAuthority(pSid, dwCounter) );
  1544. }
  1545. return TRUE;
  1546. }
  1547. #endif
  1548. long
  1549. GetUserTSLogonIdEx(
  1550. HANDLE hToken
  1551. )
  1552. /*++
  1553. --*/
  1554. {
  1555. BOOL Result;
  1556. LONG SessionId = -1;
  1557. ULONG ReturnLength;
  1558. #ifndef __WIN9XBUILD__
  1559. //
  1560. // Use the _HYDRA_ extension to GetTokenInformation to
  1561. // return the SessionId from the token.
  1562. //
  1563. Result = GetTokenInformation(
  1564. hToken,
  1565. TokenSessionId,
  1566. &SessionId,
  1567. sizeof(SessionId),
  1568. &ReturnLength
  1569. );
  1570. if( !Result ) {
  1571. DWORD dwStatus = GetLastError();
  1572. SessionId = -1;
  1573. }
  1574. #endif
  1575. return SessionId;
  1576. }
  1577. long
  1578. GetUserTSLogonId()
  1579. /*++
  1580. Routine Description:
  1581. Return client TS Session ID.
  1582. Parameters:
  1583. None.
  1584. Returns:
  1585. Client's TS session ID or 0 if not on TS.
  1586. Note:
  1587. Must have impersonate user first.
  1588. --*/
  1589. {
  1590. LONG lSessionId = -1;
  1591. #ifndef __WIN9XBUILD__
  1592. HANDLE hToken;
  1593. BOOL bSuccess;
  1594. bSuccess = OpenThreadToken(
  1595. GetCurrentThread(),
  1596. TOKEN_QUERY, //TOKEN_ALL_ACCESS,
  1597. FALSE,
  1598. &hToken
  1599. );
  1600. if( TRUE == bSuccess )
  1601. {
  1602. lSessionId = GetUserTSLogonIdEx(hToken);
  1603. CloseHandle(hToken);
  1604. }
  1605. #else
  1606. lSessionId = 0;
  1607. #endif
  1608. return lSessionId;
  1609. }
  1610. //
  1611. //
  1612. ////////////////////////////////////////////////////////////////
  1613. //
  1614. //
  1615. DWORD
  1616. RegEnumSubKeys(
  1617. IN HKEY hKey,
  1618. IN LPCTSTR pszSubKey,
  1619. IN RegEnumKeyCallback pFunc,
  1620. IN HANDLE userData
  1621. )
  1622. /*++
  1623. --*/
  1624. {
  1625. DWORD dwStatus;
  1626. HKEY hSubKey = NULL;
  1627. int index;
  1628. LONG dwNumSubKeys;
  1629. DWORD dwMaxSubKeyLength;
  1630. DWORD dwSubKeyLength;
  1631. LPTSTR pszSubKeyName = NULL;
  1632. DWORD dwMaxValueNameLen;
  1633. LPTSTR pszValueName = NULL;
  1634. DWORD dwValueNameLength;
  1635. if( NULL == hKey )
  1636. {
  1637. dwStatus = ERROR_INVALID_PARAMETER;
  1638. return dwStatus;
  1639. }
  1640. dwStatus = RegOpenKeyEx(
  1641. hKey,
  1642. pszSubKey,
  1643. 0,
  1644. KEY_ALL_ACCESS,
  1645. &hSubKey
  1646. );
  1647. if(dwStatus != ERROR_SUCCESS)
  1648. {
  1649. // key does not exist
  1650. return dwStatus;
  1651. }
  1652. //
  1653. // Query number of subkeys
  1654. //
  1655. dwStatus = RegQueryInfoKey(
  1656. hSubKey,
  1657. NULL,
  1658. NULL,
  1659. NULL,
  1660. (DWORD *)&dwNumSubKeys,
  1661. &dwMaxSubKeyLength,
  1662. NULL,
  1663. NULL,
  1664. &dwMaxValueNameLen,
  1665. NULL,
  1666. NULL,
  1667. NULL
  1668. );
  1669. if(dwStatus != ERROR_SUCCESS)
  1670. {
  1671. goto cleanup;
  1672. }
  1673. dwMaxValueNameLen++;
  1674. pszValueName = (LPTSTR)LocalAlloc(
  1675. LPTR,
  1676. dwMaxValueNameLen * sizeof(TCHAR)
  1677. );
  1678. if(pszValueName == NULL)
  1679. {
  1680. goto cleanup;
  1681. }
  1682. if(dwNumSubKeys > 0)
  1683. {
  1684. // allocate buffer for subkeys.
  1685. dwMaxSubKeyLength++;
  1686. pszSubKeyName = (LPTSTR)LocalAlloc(
  1687. LPTR,
  1688. dwMaxSubKeyLength * sizeof(TCHAR)
  1689. );
  1690. if(pszSubKeyName == NULL)
  1691. {
  1692. dwStatus = ERROR_OUTOFMEMORY;
  1693. goto cleanup;
  1694. }
  1695. for(;dwStatus == ERROR_SUCCESS && dwNumSubKeys >= 0;)
  1696. {
  1697. // delete this subkey.
  1698. dwSubKeyLength = dwMaxSubKeyLength;
  1699. memset(pszSubKeyName, 0, dwMaxSubKeyLength * sizeof(TCHAR));
  1700. // retrieve subkey name
  1701. dwStatus = RegEnumKeyEx(
  1702. hSubKey,
  1703. (DWORD)--dwNumSubKeys,
  1704. pszSubKeyName,
  1705. &dwSubKeyLength,
  1706. NULL,
  1707. NULL,
  1708. NULL,
  1709. NULL
  1710. );
  1711. if(dwStatus == ERROR_SUCCESS)
  1712. {
  1713. dwStatus = pFunc(
  1714. hSubKey,
  1715. pszSubKeyName,
  1716. userData
  1717. );
  1718. }
  1719. }
  1720. if( ERROR_NO_MORE_ITEMS == dwStatus )
  1721. {
  1722. dwStatus = ERROR_SUCCESS;
  1723. }
  1724. }
  1725. cleanup:
  1726. // close the key before trying to delete it.
  1727. if(hSubKey != NULL)
  1728. {
  1729. RegCloseKey(hSubKey);
  1730. }
  1731. if(pszValueName != NULL)
  1732. {
  1733. LocalFree(pszValueName);
  1734. }
  1735. if(pszSubKeyName != NULL)
  1736. {
  1737. LocalFree(pszSubKeyName);
  1738. }
  1739. return dwStatus;
  1740. }
  1741. DWORD
  1742. RegDelKey(
  1743. IN HKEY hRegKey,
  1744. IN LPCTSTR pszSubKey
  1745. )
  1746. /*++
  1747. Abstract:
  1748. Recursively delete entire registry key.
  1749. Parameter:
  1750. hKey : Handle to a curently open key.
  1751. pszSubKey : Pointer to NULL terminated string containing the key to be deleted.
  1752. Returns:
  1753. Error code from RegOpenKeyEx(), RegQueryInfoKey(),
  1754. RegEnumKeyEx().
  1755. ++*/
  1756. {
  1757. DWORD dwStatus;
  1758. HKEY hSubKey = NULL;
  1759. int index;
  1760. DWORD dwNumSubKeys;
  1761. DWORD dwMaxSubKeyLength;
  1762. DWORD dwSubKeyLength;
  1763. LPTSTR pszSubKeyName = NULL;
  1764. DWORD dwMaxValueNameLen;
  1765. LPTSTR pszValueName = NULL;
  1766. DWORD dwValueNameLength;
  1767. if( NULL == hRegKey )
  1768. {
  1769. dwStatus = ERROR_INVALID_PARAMETER;
  1770. return dwStatus;
  1771. }
  1772. dwStatus = RegOpenKeyEx(
  1773. hRegKey,
  1774. pszSubKey,
  1775. 0,
  1776. KEY_ALL_ACCESS,
  1777. &hSubKey
  1778. );
  1779. if(dwStatus != ERROR_SUCCESS)
  1780. {
  1781. // key does not exist
  1782. return dwStatus;
  1783. }
  1784. //
  1785. // Query number of subkeys
  1786. //
  1787. dwStatus = RegQueryInfoKey(
  1788. hSubKey,
  1789. NULL,
  1790. NULL,
  1791. NULL,
  1792. &dwNumSubKeys,
  1793. &dwMaxSubKeyLength,
  1794. NULL,
  1795. NULL,
  1796. &dwMaxValueNameLen,
  1797. NULL,
  1798. NULL,
  1799. NULL
  1800. );
  1801. if(dwStatus != ERROR_SUCCESS)
  1802. {
  1803. goto cleanup;
  1804. }
  1805. dwMaxValueNameLen++;
  1806. pszValueName = (LPTSTR)LocalAlloc(
  1807. LPTR,
  1808. dwMaxValueNameLen * sizeof(TCHAR)
  1809. );
  1810. if(pszValueName == NULL)
  1811. {
  1812. goto cleanup;
  1813. }
  1814. if(dwNumSubKeys > 0)
  1815. {
  1816. // allocate buffer for subkeys.
  1817. dwMaxSubKeyLength++;
  1818. pszSubKeyName = (LPTSTR)LocalAlloc(
  1819. LPTR,
  1820. dwMaxSubKeyLength * sizeof(TCHAR)
  1821. );
  1822. if(pszSubKeyName == NULL)
  1823. {
  1824. dwStatus = ERROR_OUTOFMEMORY;
  1825. goto cleanup;
  1826. }
  1827. //for(index = 0; index < dwNumSubKeys; index++)
  1828. for(;dwStatus == ERROR_SUCCESS;)
  1829. {
  1830. // delete this subkey.
  1831. dwSubKeyLength = dwMaxSubKeyLength;
  1832. memset(pszSubKeyName, 0, dwMaxSubKeyLength * sizeof(TCHAR));
  1833. // retrieve subkey name
  1834. dwStatus = RegEnumKeyEx(
  1835. hSubKey,
  1836. (DWORD)0,
  1837. pszSubKeyName,
  1838. &dwSubKeyLength,
  1839. NULL,
  1840. NULL,
  1841. NULL,
  1842. NULL
  1843. );
  1844. if(dwStatus == ERROR_SUCCESS)
  1845. {
  1846. dwStatus = RegDelKey( hSubKey, pszSubKeyName );
  1847. }
  1848. // ignore any error and continue on
  1849. }
  1850. }
  1851. cleanup:
  1852. for(dwStatus = ERROR_SUCCESS; pszValueName != NULL && dwStatus == ERROR_SUCCESS;)
  1853. {
  1854. dwValueNameLength = dwMaxValueNameLen;
  1855. memset(pszValueName, 0, dwMaxValueNameLen * sizeof(TCHAR));
  1856. dwStatus = RegEnumValue(
  1857. hSubKey,
  1858. 0,
  1859. pszValueName,
  1860. &dwValueNameLength,
  1861. NULL,
  1862. NULL,
  1863. NULL,
  1864. NULL
  1865. );
  1866. if(dwStatus == ERROR_SUCCESS)
  1867. {
  1868. RegDeleteValue(hSubKey, pszValueName);
  1869. }
  1870. }
  1871. // close the key before trying to delete it.
  1872. if(hSubKey != NULL)
  1873. {
  1874. RegCloseKey(hSubKey);
  1875. }
  1876. // try to delete this key, will fail if any of the subkey
  1877. // failed to delete in loop
  1878. dwStatus = RegDeleteKey(
  1879. hRegKey,
  1880. pszSubKey
  1881. );
  1882. if(pszValueName != NULL)
  1883. {
  1884. LocalFree(pszValueName);
  1885. }
  1886. if(pszSubKeyName != NULL)
  1887. {
  1888. LocalFree(pszSubKeyName);
  1889. }
  1890. return dwStatus;
  1891. }
  1892. //---------------------------------------------------------------
  1893. DWORD
  1894. GetUserSid(
  1895. OUT PBYTE* ppbSid,
  1896. OUT DWORD* pcbSid
  1897. )
  1898. /*++
  1899. Routine Description:
  1900. Retrieve user's SID , must impersonate client first.
  1901. Parameters:
  1902. ppbSid : Pointer to PBYTE to receive user's SID.
  1903. pcbSid : Pointer to DWORD to receive size of SID.
  1904. Returns:
  1905. ERROR_SUCCESS or error code.
  1906. Note:
  1907. Must have call ImpersonateClient(), funtion is NT specific,
  1908. Win9X will return internal error.
  1909. --*/
  1910. {
  1911. #ifndef __WIN9XBUILD__
  1912. BOOL bSuccess = TRUE;
  1913. DWORD dwStatus = ERROR_SUCCESS;
  1914. HANDLE hToken = NULL;
  1915. DWORD dwSize = 0;
  1916. TOKEN_USER* pToken = NULL;
  1917. *ppbSid = NULL;
  1918. *pcbSid = 0;
  1919. //
  1920. // Open current process token
  1921. //
  1922. bSuccess = OpenThreadToken(
  1923. GetCurrentThread(),
  1924. TOKEN_QUERY,
  1925. FALSE,
  1926. &hToken
  1927. );
  1928. if( TRUE == bSuccess )
  1929. {
  1930. //
  1931. // get user's token.
  1932. //
  1933. GetTokenInformation(
  1934. hToken,
  1935. TokenUser,
  1936. NULL,
  1937. 0,
  1938. &dwSize
  1939. );
  1940. pToken = (TOKEN_USER *)LocalAlloc( LPTR, dwSize );
  1941. if( NULL != pToken )
  1942. {
  1943. bSuccess = GetTokenInformation(
  1944. hToken,
  1945. TokenUser,
  1946. (LPVOID) pToken,
  1947. dwSize,
  1948. &dwSize
  1949. );
  1950. if( TRUE == bSuccess )
  1951. {
  1952. //
  1953. // GetLengthSid() return size of buffer require,
  1954. // must call IsValidSid() first
  1955. //
  1956. bSuccess = IsValidSid( pToken->User.Sid );
  1957. if( TRUE == bSuccess )
  1958. {
  1959. *pcbSid = GetLengthSid( (PBYTE)pToken->User.Sid );
  1960. *ppbSid = (PBYTE)LocalAlloc(LPTR, *pcbSid);
  1961. if( NULL != *ppbSid )
  1962. {
  1963. bSuccess = CopySid(
  1964. *pcbSid,
  1965. *ppbSid,
  1966. pToken->User.Sid
  1967. );
  1968. }
  1969. else // fail in LocalAlloc()
  1970. {
  1971. bSuccess = FALSE;
  1972. }
  1973. } // IsValidSid()
  1974. } // GetTokenInformation()
  1975. }
  1976. else // LocalAlloc() fail
  1977. {
  1978. bSuccess = FALSE;
  1979. }
  1980. }
  1981. if( TRUE != bSuccess )
  1982. {
  1983. dwStatus = GetLastError();
  1984. if( NULL != *ppbSid )
  1985. {
  1986. LocalFree(*ppbSid);
  1987. *ppbSid = NULL;
  1988. *pcbSid = 0;
  1989. }
  1990. }
  1991. //
  1992. // Free resources...
  1993. //
  1994. if( NULL != pToken )
  1995. {
  1996. LocalFree(pToken);
  1997. }
  1998. if( NULL != hToken )
  1999. {
  2000. CloseHandle(hToken);
  2001. }
  2002. return dwStatus;
  2003. #else
  2004. return E_UNEXPECTED;
  2005. #endif
  2006. }
  2007. //----------------------------------------------------------------
  2008. HRESULT
  2009. GetUserSidString(
  2010. OUT CComBSTR& bstrSid
  2011. )
  2012. /*++
  2013. Routine Description:
  2014. Retrieve user's SID in textual form, must impersonate client first.
  2015. Parameters:
  2016. bstrSID : Return users' SID in textual form.
  2017. Returns:
  2018. ERROR_SUCCESS or error code.
  2019. Note:
  2020. Must have call ImpersonateClient().
  2021. --*/
  2022. {
  2023. #ifndef __WIN9XBUILD__
  2024. DWORD dwStatus;
  2025. PBYTE pbSid = NULL;
  2026. DWORD cbSid = 0;
  2027. BOOL bSuccess = TRUE;
  2028. LPTSTR pszTextualSid = NULL;
  2029. DWORD dwTextualSid = 0;
  2030. dwStatus = GetUserSid( &pbSid, &cbSid );
  2031. if( ERROR_SUCCESS == dwStatus )
  2032. {
  2033. bSuccess = GetTextualSid(
  2034. pbSid,
  2035. NULL,
  2036. &dwTextualSid
  2037. );
  2038. if( FALSE == bSuccess && ERROR_INSUFFICIENT_BUFFER == GetLastError() )
  2039. {
  2040. pszTextualSid = (LPTSTR)LocalAlloc(
  2041. LPTR,
  2042. (dwTextualSid + 1) * sizeof(TCHAR)
  2043. );
  2044. if( NULL != pszTextualSid )
  2045. {
  2046. bSuccess = GetTextualSid(
  2047. pbSid,
  2048. pszTextualSid,
  2049. &dwTextualSid
  2050. );
  2051. if( TRUE == bSuccess )
  2052. {
  2053. bstrSid = pszTextualSid;
  2054. }
  2055. }
  2056. }
  2057. if( FALSE == bSuccess )
  2058. {
  2059. dwStatus = GetLastError();
  2060. }
  2061. }
  2062. if( NULL != pszTextualSid )
  2063. {
  2064. LocalFree(pszTextualSid);
  2065. }
  2066. if( NULL != pbSid )
  2067. {
  2068. LocalFree(pbSid);
  2069. }
  2070. return HRESULT_FROM_WIN32(dwStatus);
  2071. #else
  2072. bstrSid = WIN9X_USER_SID;
  2073. return S_OK;
  2074. #endif
  2075. }
  2076. BOOL
  2077. FileExists(
  2078. IN LPCTSTR FileName,
  2079. OUT PWIN32_FIND_DATA FindData OPTIONAL
  2080. )
  2081. /*++
  2082. Routine Description:
  2083. Determine if a file exists and is accessible.
  2084. Errormode is set (and then restored) so the user will not see
  2085. any pop-ups.
  2086. Arguments:
  2087. FileName - supplies full path of file to check for existance.
  2088. FindData - if specified, receives find data for the file.
  2089. Return Value:
  2090. TRUE if the file exists and is accessible.
  2091. FALSE if not. GetLastError() returns extended error info.
  2092. --*/
  2093. {
  2094. WIN32_FIND_DATA findData;
  2095. HANDLE FindHandle;
  2096. DWORD Error;
  2097. FindHandle = FindFirstFile(FileName,&findData);
  2098. if(FindHandle == INVALID_HANDLE_VALUE)
  2099. {
  2100. Error = GetLastError();
  2101. }
  2102. else
  2103. {
  2104. FindClose(FindHandle);
  2105. if(FindData)
  2106. {
  2107. *FindData = findData;
  2108. }
  2109. Error = NO_ERROR;
  2110. }
  2111. SetLastError(Error);
  2112. return (Error == NO_ERROR);
  2113. }
  2114. BOOL
  2115. AdjustPrivilege(
  2116. PWSTR Privilege
  2117. )
  2118. /*++
  2119. Routine Description:
  2120. This routine tries to adjust the priviliege of the current process.
  2121. Arguments:
  2122. Privilege - String with the name of the privilege to be adjusted.
  2123. Return Value:
  2124. Returns TRUE if the privilege could be adjusted.
  2125. Returns FALSE, otherwise.
  2126. --*/
  2127. {
  2128. HANDLE TokenHandle;
  2129. LUID_AND_ATTRIBUTES LuidAndAttributes;
  2130. TOKEN_PRIVILEGES TokenPrivileges;
  2131. if( !OpenProcessToken( GetCurrentProcess(),
  2132. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  2133. &TokenHandle ) ) {
  2134. return( FALSE );
  2135. }
  2136. if( !LookupPrivilegeValue( NULL,
  2137. Privilege, // (LPWSTR)SE_SECURITY_NAME,
  2138. &( LuidAndAttributes.Luid ) ) ) {
  2139. return( FALSE );
  2140. }
  2141. LuidAndAttributes.Attributes = SE_PRIVILEGE_ENABLED;
  2142. TokenPrivileges.PrivilegeCount = 1;
  2143. TokenPrivileges.Privileges[0] = LuidAndAttributes;
  2144. if( !AdjustTokenPrivileges( TokenHandle,
  2145. FALSE,
  2146. &TokenPrivileges,
  2147. 0,
  2148. NULL,
  2149. NULL ) ) {
  2150. return( FALSE );
  2151. }
  2152. if( GetLastError() != NO_ERROR ) {
  2153. return( FALSE );
  2154. }
  2155. return( TRUE );
  2156. }