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.

633 lines
15 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996-1998
  5. //
  6. // File: utils.cpp
  7. //
  8. // Contents: Hydra License Server Service Control Manager Interface
  9. //
  10. // History: 12-09-97 HueiWang Modified from MSDN RPC Service Sample
  11. //
  12. //---------------------------------------------------------------------------
  13. #include "pch.cpp"
  14. #include <lm.h>
  15. #include <time.h>
  16. #include "utils.h"
  17. /////////////////////////////////////////////////////////////////////////////
  18. BOOL
  19. FileExists(
  20. IN PCTSTR FileName,
  21. OUT PWIN32_FIND_DATA FindData OPTIONAL
  22. )
  23. /*++
  24. Routine Description:
  25. Determine if a file exists and is accessible.
  26. Errormode is set (and then restored) so the user will not see
  27. any pop-ups.
  28. Arguments:
  29. FileName - supplies full path of file to check for existance.
  30. FindData - if specified, receives find data for the file.
  31. Return Value:
  32. TRUE if the file exists and is accessible.
  33. FALSE if not. GetLastError() returns extended error info.
  34. --*/
  35. {
  36. WIN32_FIND_DATA findData;
  37. HANDLE FindHandle;
  38. DWORD Error;
  39. FindHandle = FindFirstFile(FileName,&findData);
  40. if(FindHandle == INVALID_HANDLE_VALUE)
  41. {
  42. Error = GetLastError();
  43. }
  44. else
  45. {
  46. FindClose(FindHandle);
  47. if(FindData)
  48. {
  49. *FindData = findData;
  50. }
  51. Error = NO_ERROR;
  52. }
  53. SetLastError(Error);
  54. return (Error == NO_ERROR);
  55. }
  56. /*----------------------------------------------------------------------------
  57. Routine Description:
  58. This function checks to see whether the specified sid is enabled in
  59. the specified token.
  60. Arguments:
  61. TokenHandle - If present, this token is checked for the sid. If not
  62. present then the current effective token will be used. This must
  63. be an impersonation token.
  64. SidToCheck - The sid to check for presence in the token
  65. IsMember - If the sid is enabled in the token, contains TRUE otherwise
  66. false.
  67. Return Value:
  68. TRUE - The API completed successfully. It does not indicate that the
  69. sid is a member of the token.
  70. FALSE - The API failed. A more detailed status code can be retrieved
  71. via GetLastError()
  72. Note : Code modified from 5.0 \\rastaman\ntwin\src\base\advapi\security.c
  73. ----------------------------------------------------------------------------*/
  74. BOOL
  75. TLSCheckTokenMembership(
  76. IN HANDLE TokenHandle OPTIONAL,
  77. IN PSID SidToCheck,
  78. OUT PBOOL IsMember
  79. )
  80. {
  81. HANDLE ProcessToken = NULL;
  82. HANDLE EffectiveToken = NULL;
  83. DWORD Status = ERROR_SUCCESS;
  84. PISECURITY_DESCRIPTOR SecDesc = NULL;
  85. ULONG SecurityDescriptorSize;
  86. GENERIC_MAPPING GenericMapping = { STANDARD_RIGHTS_READ,
  87. STANDARD_RIGHTS_EXECUTE,
  88. STANDARD_RIGHTS_WRITE,
  89. STANDARD_RIGHTS_ALL };
  90. //
  91. // The size of the privilege set needs to contain the set itself plus
  92. // any privileges that may be used. The privileges that are used
  93. // are SeTakeOwnership and SeSecurity, plus one for good measure
  94. //
  95. BYTE PrivilegeSetBuffer[sizeof(PRIVILEGE_SET) + 3*sizeof(LUID_AND_ATTRIBUTES)];
  96. PPRIVILEGE_SET PrivilegeSet = (PPRIVILEGE_SET) PrivilegeSetBuffer;
  97. ULONG PrivilegeSetLength = sizeof(PrivilegeSetBuffer);
  98. ACCESS_MASK AccessGranted = 0;
  99. BOOL AccessStatus = FALSE;
  100. PACL Dacl = NULL;
  101. #define MEMBER_ACCESS 1
  102. *IsMember = FALSE;
  103. //
  104. // Get a handle to the token
  105. //
  106. if (TokenHandle != NULL)
  107. {
  108. EffectiveToken = TokenHandle;
  109. }
  110. else
  111. {
  112. if(!OpenThreadToken(GetCurrentThread(),
  113. TOKEN_QUERY,
  114. FALSE, // don't open as self
  115. &EffectiveToken))
  116. {
  117. //
  118. // if there is no thread token, try the process token
  119. //
  120. if((Status=GetLastError()) == ERROR_NO_TOKEN)
  121. {
  122. if(!OpenProcessToken(GetCurrentProcess(),
  123. TOKEN_QUERY | TOKEN_DUPLICATE,
  124. &ProcessToken))
  125. {
  126. Status = GetLastError();
  127. }
  128. //
  129. // If we have a process token, we need to convert it to an
  130. // impersonation token
  131. //
  132. if (Status == ERROR_SUCCESS)
  133. {
  134. BOOL Result;
  135. Result = DuplicateToken(ProcessToken,
  136. SecurityImpersonation,
  137. &EffectiveToken);
  138. CloseHandle(ProcessToken);
  139. if (!Result)
  140. {
  141. return(FALSE);
  142. }
  143. }
  144. }
  145. if (Status != ERROR_SUCCESS)
  146. {
  147. goto Cleanup;
  148. }
  149. }
  150. }
  151. //
  152. // Construct a security descriptor to pass to access check
  153. //
  154. //
  155. // The size is equal to the size of an SD + twice the length of the SID
  156. // (for owner and group) + size of the DACL = sizeof ACL + size of the
  157. // ACE, which is an ACE + length of
  158. // ths SID.
  159. //
  160. SecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR) +
  161. sizeof(ACCESS_ALLOWED_ACE) +
  162. sizeof(ACL) +
  163. 3 * GetLengthSid(SidToCheck);
  164. SecDesc = (PISECURITY_DESCRIPTOR) LocalAlloc(LMEM_ZEROINIT, SecurityDescriptorSize );
  165. if (SecDesc == NULL)
  166. {
  167. Status = ERROR_OUTOFMEMORY;
  168. goto Cleanup;
  169. }
  170. Dacl = (PACL) (SecDesc + 1);
  171. InitializeSecurityDescriptor(SecDesc, SECURITY_DESCRIPTOR_REVISION);
  172. //
  173. // Fill in fields of security descriptor
  174. //
  175. SetSecurityDescriptorOwner(SecDesc, SidToCheck, FALSE);
  176. SetSecurityDescriptorGroup(SecDesc, SidToCheck, FALSE);
  177. if(!InitializeAcl( Dacl,
  178. SecurityDescriptorSize - sizeof(SECURITY_DESCRIPTOR),
  179. ACL_REVISION))
  180. {
  181. Status=GetLastError();
  182. goto Cleanup;
  183. }
  184. if(!AddAccessAllowedAce(Dacl, ACL_REVISION, MEMBER_ACCESS, SidToCheck))
  185. {
  186. Status=GetLastError();
  187. goto Cleanup;
  188. }
  189. if(!SetSecurityDescriptorDacl(SecDesc, TRUE, Dacl, FALSE))
  190. {
  191. Status=GetLastError();
  192. goto Cleanup;
  193. }
  194. if(!AccessCheck(SecDesc,
  195. EffectiveToken,
  196. MEMBER_ACCESS,
  197. &GenericMapping,
  198. PrivilegeSet,
  199. &PrivilegeSetLength,
  200. &AccessGranted,
  201. &AccessStatus))
  202. {
  203. Status=GetLastError();
  204. goto Cleanup;
  205. }
  206. //
  207. // if the access check failed, then the sid is not a member of the
  208. // token
  209. //
  210. if ((AccessStatus == TRUE) && (AccessGranted == MEMBER_ACCESS))
  211. {
  212. *IsMember = TRUE;
  213. }
  214. Cleanup:
  215. if (TokenHandle == NULL && EffectiveToken != NULL)
  216. {
  217. CloseHandle(EffectiveToken);
  218. }
  219. if (SecDesc != NULL)
  220. {
  221. LocalFree(SecDesc);
  222. }
  223. return (Status == ERROR_SUCCESS) ? TRUE : FALSE;
  224. }
  225. /*------------------------------------------------------------------------
  226. BOOL IsAdmin(void)
  227. returns TRUE if user is an admin
  228. FALSE if user is not an admin
  229. ------------------------------------------------------------------------*/
  230. DWORD
  231. IsAdmin(
  232. BOOL* bMember
  233. )
  234. {
  235. PSID psidAdministrators;
  236. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  237. DWORD dwStatus=ERROR_SUCCESS;
  238. do {
  239. if(!AllocateAndInitializeSid(&siaNtAuthority,
  240. 2,
  241. SECURITY_BUILTIN_DOMAIN_RID,
  242. DOMAIN_ALIAS_RID_ADMINS,
  243. 0, 0, 0, 0, 0, 0,
  244. &psidAdministrators))
  245. {
  246. dwStatus=GetLastError();
  247. continue;
  248. }
  249. // assume that we don't find the admin SID.
  250. if(!TLSCheckTokenMembership(NULL,
  251. psidAdministrators,
  252. bMember))
  253. {
  254. dwStatus=GetLastError();
  255. }
  256. FreeSid(psidAdministrators);
  257. } while(FALSE);
  258. return dwStatus;
  259. }
  260. /////////////////////////////////////////////////////////////////////////////
  261. BOOL
  262. LoadResourceString(
  263. DWORD dwId,
  264. LPTSTR szBuf,
  265. DWORD dwBufSize
  266. )
  267. {
  268. int dwRet;
  269. dwRet=LoadString(GetModuleHandle(NULL), dwId, szBuf, dwBufSize);
  270. return (dwRet != 0);
  271. }
  272. /////////////////////////////////////////////////////////////////////////////
  273. HRESULT
  274. LogEvent(
  275. LPTSTR lpszSource,
  276. DWORD dwEventType,
  277. DWORD dwIdEvent,
  278. WORD cStrings,
  279. TCHAR **apwszStrings
  280. )
  281. /*++
  282. --*/
  283. {
  284. HANDLE hAppLog=NULL;
  285. BOOL bSuccess=FALSE;
  286. WORD wElogType;
  287. wElogType = (WORD) dwEventType;
  288. if(hAppLog=RegisterEventSource(NULL, lpszSource))
  289. {
  290. bSuccess = ReportEvent(
  291. hAppLog,
  292. wElogType,
  293. 0,
  294. dwIdEvent,
  295. NULL,
  296. cStrings,
  297. 0,
  298. (const TCHAR **) apwszStrings,
  299. NULL
  300. );
  301. DeregisterEventSource(hAppLog);
  302. }
  303. return((bSuccess) ? ERROR_SUCCESS : GetLastError());
  304. }
  305. /////////////////////////////////////////////////////////////////////////////
  306. void
  307. TLSLogInfoEvent(
  308. IN DWORD code
  309. )
  310. /*++
  311. --*/
  312. {
  313. LogEvent(
  314. _TEXT(SZSERVICENAME),
  315. EVENTLOG_INFORMATION_TYPE,
  316. code,
  317. 0,
  318. NULL
  319. );
  320. }
  321. /////////////////////////////////////////////////////////////////////////////
  322. void
  323. TLSLogWarningEvent(
  324. IN DWORD code
  325. )
  326. /*++
  327. --*/
  328. {
  329. LogEvent(
  330. _TEXT(SZSERVICENAME),
  331. EVENTLOG_WARNING_TYPE,
  332. code,
  333. 0,
  334. NULL
  335. );
  336. }
  337. /////////////////////////////////////////////////////////////////////////////
  338. void
  339. TLSLogErrorEvent(
  340. IN DWORD errCode
  341. )
  342. /*++
  343. --*/
  344. {
  345. LogEvent(
  346. _TEXT(SZSERVICENAME),
  347. EVENTLOG_ERROR_TYPE,
  348. errCode,
  349. 0,
  350. NULL
  351. );
  352. }
  353. /////////////////////////////////////////////////////////////////////////////
  354. void
  355. TLSLogEventString(
  356. IN DWORD dwEventType,
  357. IN DWORD dwEventId,
  358. IN WORD wNumString,
  359. IN LPCTSTR* lpStrings
  360. )
  361. /*++
  362. --*/
  363. {
  364. HANDLE hAppLog=NULL;
  365. BOOL bSuccess=FALSE;
  366. WORD wElogType = (WORD) dwEventType;
  367. __try {
  368. if(hAppLog=RegisterEventSource(NULL, _TEXT(SZSERVICENAME)))
  369. {
  370. bSuccess = ReportEvent(
  371. hAppLog,
  372. wElogType,
  373. 0,
  374. dwEventId,
  375. NULL,
  376. wNumString,
  377. 0,
  378. (const TCHAR **) lpStrings,
  379. NULL
  380. );
  381. DeregisterEventSource(hAppLog);
  382. }
  383. }
  384. __except(EXCEPTION_EXECUTE_HANDLER) {
  385. }
  386. return;
  387. }
  388. /////////////////////////////////////////////////////////////////////////////
  389. void
  390. TLSLogEvent(
  391. IN DWORD type,
  392. IN DWORD EventId,
  393. IN DWORD code, ...
  394. )
  395. /*
  396. */
  397. {
  398. va_list marker;
  399. va_start( marker, code );
  400. DWORD dwRet;
  401. LPTSTR lpszTemp = NULL;
  402. __try {
  403. dwRet=FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE |
  404. FORMAT_MESSAGE_FROM_SYSTEM,
  405. NULL,
  406. code,
  407. LANG_NEUTRAL,
  408. (LPTSTR)&lpszTemp,
  409. 0,
  410. &marker);
  411. if(dwRet != 0)
  412. {
  413. LogEvent(_TEXT(SZSERVICENAME), type, EventId, 1, &lpszTemp);
  414. if(lpszTemp)
  415. {
  416. LocalFree((HLOCAL)lpszTemp);
  417. }
  418. }
  419. }
  420. __except(EXCEPTION_EXECUTE_HANDLER) {
  421. // this is only for putting a break point here
  422. SetLastError(GetLastError());
  423. }
  424. va_end( marker );
  425. return;
  426. }
  427. ///////////////////////////////////////////////////////////////////////
  428. BOOL
  429. TLSSystemTimeToFileTime(
  430. SYSTEMTIME* pSysTime,
  431. LPFILETIME pfTime
  432. )
  433. /*++
  434. --*/
  435. {
  436. DoConvert:
  437. if(SystemTimeToFileTime(pSysTime, pfTime) == FALSE)
  438. {
  439. if(GetLastError() != ERROR_INVALID_PARAMETER)
  440. {
  441. TLSASSERT(FALSE);
  442. return FALSE;
  443. }
  444. if(pSysTime->wMonth == 2)
  445. {
  446. if(pSysTime->wDay > 29)
  447. {
  448. pSysTime->wDay = 29;
  449. goto DoConvert;
  450. }
  451. else if(pSysTime->wDay == 29)
  452. {
  453. pSysTime->wDay = 28;
  454. goto DoConvert;
  455. }
  456. }
  457. else if ((pSysTime->wMonth == 9) ||
  458. (pSysTime->wMonth == 4) ||
  459. (pSysTime->wMonth == 6) ||
  460. (pSysTime->wMonth == 11))
  461. {
  462. if (pSysTime->wDay > 30)
  463. {
  464. pSysTime->wDay = 30;
  465. goto DoConvert;
  466. }
  467. }
  468. }
  469. return TRUE;
  470. }
  471. ///////////////////////////////////////////////////////////////////////
  472. BOOL
  473. FileTimeToLicenseDate(
  474. LPFILETIME pft,
  475. DWORD* t
  476. )
  477. /*++
  478. ++*/
  479. {
  480. SYSTEMTIME sysTime;
  481. struct tm gmTime;
  482. FILETIME localFt;
  483. time_t licenseTime;
  484. if(FileTimeToLocalFileTime(pft, &localFt) == FALSE)
  485. {
  486. return FALSE;
  487. }
  488. if(FileTimeToSystemTime(&localFt, &sysTime) == FALSE)
  489. {
  490. return FALSE;
  491. }
  492. if(sysTime.wYear >= 2038)
  493. {
  494. licenseTime = INT_MAX;
  495. }
  496. else
  497. {
  498. // Unix time support up to 2038/1/18
  499. // restrict any expiration data
  500. memset(&gmTime, 0, sizeof(gmTime));
  501. gmTime.tm_sec = sysTime.wSecond;
  502. gmTime.tm_min = sysTime.wMinute;
  503. gmTime.tm_hour = sysTime.wHour;
  504. gmTime.tm_year = sysTime.wYear - 1900;
  505. gmTime.tm_mon = sysTime.wMonth - 1;
  506. gmTime.tm_mday = sysTime.wDay;
  507. gmTime.tm_isdst = -1;
  508. if((licenseTime = mktime(&gmTime)) == (time_t)-1)
  509. {
  510. SetLastError(ERROR_INVALID_PARAMETER);
  511. }
  512. }
  513. *t = (DWORD)licenseTime;
  514. return licenseTime != (time_t)-1;
  515. }
  516. ///////////////////////////////////////////////////////////////////////
  517. void
  518. UnixTimeToFileTime(
  519. time_t t,
  520. LPFILETIME pft
  521. )
  522. {
  523. LARGE_INTEGER li;
  524. li.QuadPart = Int32x32To64(t, 10000000) + 116444736000000000;
  525. pft->dwHighDateTime = li.HighPart;
  526. pft->dwLowDateTime = li.LowPart;
  527. }