Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1964 lines
50 KiB

  1. /*
  2. * Concurrent.cpp
  3. *
  4. * Author: RobLeit
  5. *
  6. * The Concurrent (renamed to Per Session) licensing policy.
  7. */
  8. /*
  9. * Includes
  10. */
  11. #include "precomp.h"
  12. #include "lscore.h"
  13. #include "session.h"
  14. #include "concurrent.h"
  15. #include "util.h"
  16. #include "lctrace.h"
  17. #include <icaevent.h>
  18. #define STRSAFE_NO_DEPRECATE
  19. #include "strsafe.h"
  20. /*
  21. * Typedefs
  22. */
  23. #define CONCURRENTLICENSEINFO_TYPE_V1 (1)
  24. typedef struct {
  25. DWORD dwStructVer;
  26. DWORD dwLicenseVer;
  27. LONG lLicenseCount;
  28. HWID hwid;
  29. } CONCURRENTLICENSEINFO_V1, *PCONCURRENTLICENSEINFO_V1;
  30. typedef struct {
  31. ULARGE_INTEGER ulSerialNumber;
  32. FILETIME ftNotAfter;
  33. DWORD cchServerName;
  34. WCHAR szServerName[MAX_COMPUTERNAME_LENGTH + 2];
  35. } LSERVERINFO, *PLSERVERINFO;
  36. /*
  37. * Function declarations
  38. */
  39. NTSTATUS
  40. ReturnLicenseToLS(
  41. LONG nNum
  42. );
  43. LICENSE_STATUS
  44. GetLicenseFromStore(
  45. PLONG LicenseCount,
  46. PHWID phwid,
  47. DWORD dwLicenseVer
  48. );
  49. LICENSE_STATUS
  50. SetLicenseInStore(
  51. LONG LicenseCount,
  52. HWID hwid,
  53. DWORD dwLicenseVer
  54. );
  55. /*
  56. * extern globals
  57. */
  58. extern "C"
  59. extern HANDLE hModuleWin;
  60. /*
  61. * globals
  62. */
  63. FILETIME g_ftNotAfter = {0,0};
  64. HANDLE g_hOkayToAdd = NULL;
  65. DWORD g_dwWaitTimeAdd;
  66. DWORD g_dwWaitTimeRemove;
  67. DWORD g_dwIncrement;
  68. HANDLE g_rgWaitEvents[4] = {NULL,NULL,NULL,NULL};
  69. CRITICAL_SECTION g_csAddLicenses;
  70. RTL_RESOURCE g_rwLockLicense;
  71. BOOL g_fLockLicenseInitialized = FALSE;
  72. LONG g_lSessionCount = 0;
  73. LONG g_lSessionMax;
  74. /*
  75. * Constants
  76. */
  77. //
  78. // Dynamic licensing parameters
  79. //
  80. #define LC_POLICY_CONCURRENT_LICENSE_COUNT_INCREMENT 1
  81. #define LC_POLICY_CONCURRENT_WAIT_TIME_ADD (60)
  82. #define LC_POLICY_CONCURRENT_WAIT_TIME_REMOVE (60*30)
  83. //
  84. // The LSA secret store for the Concurrent licenses
  85. //
  86. // L$ means only readable from the local machine
  87. #define CONCURRENT_LICENSE_STORE_5_1 L"L$CONCURRENT_LICENSE_STORE_AFF8D0DE-BF56-49e2-89F8-1F188C0ACEDD"
  88. #define CONCURRENT_LICENSE_STORE_LATEST_VERSION CONCURRENT_LICENSE_STORE_5_1
  89. //
  90. // The LSA secret store for the license server info
  91. //
  92. #define CONCURRENT_LSERVER_STORE L"L$CONCURRENT_LSERVER_STORE_AFF8D0DE-BF56-49e2-89F8-1F188C0ACEDD"
  93. //
  94. // Registry keys
  95. //
  96. #define LCREG_CONCURRENTKEY L"System\\CurrentControlSet\\Control\\Terminal Server\\Licensing Core\\Policies\\Concurrent"
  97. #define LCREG_INCREMENT L"Increment"
  98. #define LCREG_WAIT_TIME_ADD L"WaitTimeAdd"
  99. #define LCREG_WAIT_TIME_REMOVE L"WaitTimeRemove"
  100. //
  101. // Events used to trigger license returns
  102. //
  103. #define RETURN_LICENSE_START_WAITING 0
  104. #define RETURN_LICENSE_IMMEDIATELY 1
  105. #define RETURN_LICENSE_EXIT 2
  106. #define RETURN_LICENSE_WAITING_DONE 3
  107. /*
  108. * Class Implementation
  109. */
  110. /*
  111. * Creation Functions
  112. */
  113. CConcurrentPolicy::CConcurrentPolicy(
  114. ) : CPolicy()
  115. {
  116. }
  117. CConcurrentPolicy::~CConcurrentPolicy(
  118. )
  119. {
  120. }
  121. /*
  122. * Administrative Functions
  123. */
  124. ULONG
  125. CConcurrentPolicy::GetFlags(
  126. )
  127. {
  128. return(LC_FLAG_INTERNAL_POLICY | LC_FLAG_REQUIRE_APP_COMPAT);
  129. }
  130. ULONG
  131. CConcurrentPolicy::GetId(
  132. )
  133. {
  134. return(5);
  135. }
  136. NTSTATUS
  137. CConcurrentPolicy::GetInformation(
  138. LPLCPOLICYINFOGENERIC lpPolicyInfo
  139. )
  140. {
  141. NTSTATUS Status;
  142. ASSERT(lpPolicyInfo != NULL);
  143. if (lpPolicyInfo->ulVersion == LCPOLICYINFOTYPE_V1)
  144. {
  145. int retVal;
  146. LPLCPOLICYINFO_V1 lpPolicyInfoV1 = (LPLCPOLICYINFO_V1)lpPolicyInfo;
  147. LPWSTR pName;
  148. LPWSTR pDescription;
  149. ASSERT(lpPolicyInfoV1->lpPolicyName == NULL);
  150. ASSERT(lpPolicyInfoV1->lpPolicyDescription == NULL);
  151. //
  152. // The strings loaded in this fashion are READ-ONLY. They are also
  153. // NOT NULL terminated. Allocate and zero out a buffer, then copy the
  154. // string over.
  155. //
  156. retVal = LoadString(
  157. (HINSTANCE)hModuleWin,
  158. IDS_LSCORE_CONCURRENT_NAME,
  159. (LPWSTR)(&pName),
  160. 0
  161. );
  162. if (retVal != 0)
  163. {
  164. lpPolicyInfoV1->lpPolicyName = (LPWSTR)LocalAlloc(LPTR, (retVal + 1) * sizeof(WCHAR));
  165. if (lpPolicyInfoV1->lpPolicyName != NULL)
  166. {
  167. StringCbCopyN(lpPolicyInfoV1->lpPolicyName, (retVal+1) * sizeof(WCHAR), pName, (retVal+1) * sizeof(WCHAR));
  168. }
  169. else
  170. {
  171. Status = STATUS_NO_MEMORY;
  172. goto V1error;
  173. }
  174. }
  175. else
  176. {
  177. Status = STATUS_INTERNAL_ERROR;
  178. goto V1error;
  179. }
  180. retVal = LoadString(
  181. (HINSTANCE)hModuleWin,
  182. IDS_LSCORE_CONCURRENT_DESC,
  183. (LPWSTR)(&pDescription),
  184. 0
  185. );
  186. if (retVal != 0)
  187. {
  188. lpPolicyInfoV1->lpPolicyDescription = (LPWSTR)LocalAlloc(LPTR, (retVal + 1) * sizeof(WCHAR));
  189. if (lpPolicyInfoV1->lpPolicyDescription != NULL)
  190. {
  191. StringCbCopyN(lpPolicyInfoV1->lpPolicyDescription, (retVal+1) * sizeof(WCHAR), pDescription, (retVal+1) * sizeof(WCHAR));
  192. }
  193. else
  194. {
  195. Status = STATUS_NO_MEMORY;
  196. goto V1error;
  197. }
  198. }
  199. else
  200. {
  201. Status = STATUS_INTERNAL_ERROR;
  202. goto V1error;
  203. }
  204. Status = STATUS_SUCCESS;
  205. goto exit;
  206. V1error:
  207. //
  208. // An error occurred loading/copying the strings.
  209. //
  210. if (lpPolicyInfoV1->lpPolicyName != NULL)
  211. {
  212. LocalFree(lpPolicyInfoV1->lpPolicyName);
  213. lpPolicyInfoV1->lpPolicyName = NULL;
  214. }
  215. if (lpPolicyInfoV1->lpPolicyDescription != NULL)
  216. {
  217. LocalFree(lpPolicyInfoV1->lpPolicyDescription);
  218. lpPolicyInfoV1->lpPolicyDescription = NULL;
  219. }
  220. }
  221. else
  222. {
  223. Status = STATUS_REVISION_MISMATCH;
  224. }
  225. exit:
  226. return(Status);
  227. }
  228. DWORD WINAPI ReturnLicenseWorker(
  229. LPVOID lpParameter
  230. )
  231. {
  232. DWORD dwWait;
  233. HANDLE * rgWaitEvents = (HANDLE *) lpParameter;
  234. LONG lLicensesToReturn, lLastBlock;
  235. for (;;)
  236. {
  237. //
  238. // wait for events signalling when to return licenses
  239. // or start waiting to return licenses
  240. //
  241. dwWait = WaitForMultipleObjects(4, // nCount
  242. rgWaitEvents,
  243. FALSE, // fWaitAll
  244. INFINITE
  245. );
  246. switch (dwWait)
  247. {
  248. case WAIT_OBJECT_0+RETURN_LICENSE_START_WAITING:
  249. LARGE_INTEGER liWait;
  250. // relative wait, in 100 nanosecond intervals
  251. liWait.QuadPart = (__int64) g_dwWaitTimeRemove * (-10 * 1000 * 1000);
  252. SetWaitableTimer(rgWaitEvents[RETURN_LICENSE_WAITING_DONE],
  253. &liWait,
  254. 0, // lPeriod
  255. NULL, // pfnCompletionRoutine
  256. NULL, // lpArgToCompletionRoutine
  257. FALSE // fResume (from suspended)
  258. );
  259. break;
  260. case WAIT_OBJECT_0+RETURN_LICENSE_WAITING_DONE:
  261. RtlAcquireResourceShared(&g_rwLockLicense,TRUE);
  262. lLastBlock = g_lSessionMax - ((g_lSessionMax / g_dwIncrement) * g_dwIncrement);
  263. if (lLastBlock == 0)
  264. lLastBlock = g_dwIncrement;
  265. if (g_lSessionCount + lLastBlock <= g_lSessionMax )
  266. {
  267. lLicensesToReturn = lLastBlock + (((g_lSessionMax - g_lSessionCount - lLastBlock) / g_dwIncrement) * g_dwIncrement);
  268. (VOID)ReturnLicenseToLS(lLicensesToReturn);
  269. }
  270. RtlReleaseResource(&g_rwLockLicense);
  271. break;
  272. case WAIT_OBJECT_0+RETURN_LICENSE_IMMEDIATELY:
  273. RtlAcquireResourceShared(&g_rwLockLicense,TRUE);
  274. lLastBlock = g_lSessionMax - ((g_lSessionMax / g_dwIncrement) * g_dwIncrement);
  275. if (lLastBlock == 0)
  276. lLastBlock = g_dwIncrement;
  277. if (g_lSessionCount + lLastBlock + g_dwIncrement <= (DWORD)g_lSessionMax )
  278. {
  279. lLicensesToReturn = ((g_lSessionMax - g_lSessionCount - lLastBlock) / g_dwIncrement) * g_dwIncrement;
  280. (VOID)ReturnLicenseToLS(lLicensesToReturn);
  281. }
  282. RtlReleaseResource(&g_rwLockLicense);
  283. break;
  284. case WAIT_OBJECT_0+RETURN_LICENSE_EXIT:
  285. if (NULL != rgWaitEvents[RETURN_LICENSE_START_WAITING])
  286. {
  287. CloseHandle(rgWaitEvents[RETURN_LICENSE_START_WAITING]);
  288. rgWaitEvents[RETURN_LICENSE_START_WAITING] = NULL;
  289. }
  290. if (NULL != rgWaitEvents[RETURN_LICENSE_IMMEDIATELY])
  291. {
  292. CloseHandle(rgWaitEvents[RETURN_LICENSE_IMMEDIATELY]);
  293. rgWaitEvents[RETURN_LICENSE_IMMEDIATELY] = NULL;
  294. }
  295. if (NULL != rgWaitEvents[RETURN_LICENSE_EXIT])
  296. {
  297. CloseHandle(rgWaitEvents[RETURN_LICENSE_EXIT]);
  298. rgWaitEvents[RETURN_LICENSE_EXIT] = NULL;
  299. }
  300. if (NULL != rgWaitEvents[RETURN_LICENSE_WAITING_DONE])
  301. {
  302. CloseHandle(rgWaitEvents[RETURN_LICENSE_WAITING_DONE]);
  303. rgWaitEvents[RETURN_LICENSE_WAITING_DONE] = NULL;
  304. }
  305. if (g_fLockLicenseInitialized)
  306. {
  307. // make sure no one else is using it
  308. RtlAcquireResourceExclusive(&g_rwLockLicense,TRUE);
  309. RtlDeleteResource(&g_rwLockLicense);
  310. g_fLockLicenseInitialized = FALSE;
  311. }
  312. return STATUS_SUCCESS;
  313. break;
  314. default:
  315. {
  316. DWORD dwRet = 0;
  317. DWORD dwErr = GetLastError();
  318. LPTSTR lpszError;
  319. BOOL fFree = TRUE;
  320. dwRet=FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  321. NULL,
  322. dwErr,
  323. LANG_NEUTRAL,
  324. (LPTSTR)&lpszError,
  325. 0,
  326. NULL);
  327. if (dwRet == 0)
  328. {
  329. lpszError = (LPTSTR) LocalAlloc(LPTR,12 * sizeof(WCHAR));
  330. if (NULL != lpszError)
  331. {
  332. wsprintf(lpszError,L"%#lX",dwErr);
  333. }
  334. else
  335. {
  336. lpszError = L"";
  337. fFree = FALSE;
  338. }
  339. }
  340. LicenseLogEvent(EVENTLOG_ERROR_TYPE,
  341. EVENT_LICENSING_CONCURRENT_NOT_DYNAMIC,
  342. 1,
  343. &lpszError );
  344. if (fFree)
  345. {
  346. LocalFree(lpszError);
  347. }
  348. return dwErr;
  349. break;
  350. }
  351. }
  352. }
  353. }
  354. /*
  355. * Loading and Activation Functions
  356. */
  357. NTSTATUS
  358. CConcurrentPolicy::Load(
  359. )
  360. {
  361. NTSTATUS Status;
  362. g_rgWaitEvents[RETURN_LICENSE_START_WAITING] = NULL;
  363. g_rgWaitEvents[RETURN_LICENSE_IMMEDIATELY] = NULL;
  364. g_rgWaitEvents[RETURN_LICENSE_EXIT] = NULL;
  365. g_rgWaitEvents[RETURN_LICENSE_WAITING_DONE] = NULL;
  366. Status = RtlInitializeCriticalSection(&g_csAddLicenses);
  367. if (STATUS_SUCCESS != Status)
  368. {
  369. return Status;
  370. }
  371. __try
  372. {
  373. RtlInitializeResource(&g_rwLockLicense);
  374. g_fLockLicenseInitialized = TRUE;
  375. Status = STATUS_SUCCESS;
  376. }
  377. __except(EXCEPTION_EXECUTE_HANDLER)
  378. {
  379. Status = GetExceptionCode();
  380. }
  381. if (STATUS_SUCCESS != Status)
  382. {
  383. RtlDeleteCriticalSection(&g_csAddLicenses);
  384. return Status;
  385. }
  386. g_hOkayToAdd = CreateWaitableTimer(NULL, // SecurityAttributes,
  387. TRUE, // bManualReset
  388. NULL // lpName
  389. );
  390. if (NULL == g_hOkayToAdd)
  391. {
  392. RtlDeleteCriticalSection(&g_csAddLicenses);
  393. g_fLockLicenseInitialized = FALSE;
  394. RtlDeleteResource(&g_rwLockLicense);
  395. return GetLastError();
  396. }
  397. return(STATUS_SUCCESS);
  398. }
  399. NTSTATUS
  400. CConcurrentPolicy::Unload(
  401. )
  402. {
  403. // signal worker thread to cleanup and exit
  404. if (NULL != g_rgWaitEvents[RETURN_LICENSE_EXIT])
  405. {
  406. SetEvent(g_rgWaitEvents[RETURN_LICENSE_EXIT]);
  407. }
  408. return(STATUS_SUCCESS);
  409. }
  410. NTSTATUS
  411. CConcurrentPolicy::Activate(
  412. BOOL fStartup,
  413. ULONG *pulAlternatePolicy
  414. )
  415. {
  416. NTSTATUS Status = STATUS_SUCCESS;
  417. HANDLE hThread;
  418. HWID hwidEncrypted;
  419. LICENSE_STATUS LsStatus;
  420. LARGE_INTEGER liWait;
  421. BOOL fRet;
  422. if (NULL != pulAlternatePolicy)
  423. {
  424. // don't set an explicit alternate policy
  425. *pulAlternatePolicy = ULONG_MAX;
  426. }
  427. ReadLicensingParameters();
  428. liWait.QuadPart = -1;
  429. // Ensure that timer is set
  430. fRet = SetWaitableTimer(g_hOkayToAdd,
  431. &liWait, // pDueTime
  432. 1, // lPeriod
  433. NULL, // pfnCompletionRoutine
  434. NULL, // lpArgToCompletionRoutine
  435. FALSE // fResume (from suspended)
  436. );
  437. if (!fRet)
  438. {
  439. Status = GetLastError();
  440. goto check_status;
  441. }
  442. //
  443. // Read number of licenses from LSA secret
  444. //
  445. LsStatus = GetLicenseFromStore(&g_lSessionMax,
  446. &hwidEncrypted,
  447. CURRENT_TERMINAL_SERVER_VERSION
  448. );
  449. if (LsStatus != LICENSE_STATUS_OK)
  450. {
  451. g_lSessionMax = 0;
  452. }
  453. Status = StartCheckingGracePeriod();
  454. if (Status == STATUS_SUCCESS)
  455. {
  456. g_rgWaitEvents[RETURN_LICENSE_START_WAITING]
  457. = CreateEvent(NULL, // SecurityAttributes,
  458. FALSE, // bManualReset
  459. FALSE, // bInitialState
  460. NULL // lpName
  461. );
  462. if (NULL == g_rgWaitEvents[RETURN_LICENSE_START_WAITING])
  463. {
  464. Status = GetLastError();
  465. goto check_status;
  466. }
  467. g_rgWaitEvents[RETURN_LICENSE_IMMEDIATELY]
  468. = CreateEvent(NULL, // SecurityAttributes,
  469. FALSE, // bManualReset
  470. FALSE, // bInitialState
  471. NULL // lpName
  472. );
  473. if (NULL == g_rgWaitEvents[RETURN_LICENSE_IMMEDIATELY])
  474. {
  475. Status = GetLastError();
  476. CloseHandle(g_rgWaitEvents[RETURN_LICENSE_START_WAITING]);
  477. g_rgWaitEvents[RETURN_LICENSE_START_WAITING] = NULL;
  478. goto check_status;
  479. }
  480. g_rgWaitEvents[RETURN_LICENSE_EXIT]
  481. = CreateEvent(NULL, // SecurityAttributes,
  482. FALSE, // bManualReset
  483. FALSE, // bInitialState
  484. NULL // lpName
  485. );
  486. if (NULL == g_rgWaitEvents[RETURN_LICENSE_EXIT])
  487. {
  488. Status = GetLastError();
  489. CloseHandle(g_rgWaitEvents[RETURN_LICENSE_START_WAITING]);
  490. g_rgWaitEvents[RETURN_LICENSE_START_WAITING] = NULL;
  491. CloseHandle(g_rgWaitEvents[RETURN_LICENSE_IMMEDIATELY]);
  492. g_rgWaitEvents[RETURN_LICENSE_IMMEDIATELY] = NULL;
  493. goto check_status;
  494. }
  495. g_rgWaitEvents[RETURN_LICENSE_WAITING_DONE]
  496. = CreateWaitableTimer(NULL, // SecurityAttributes,
  497. FALSE, // bManualReset
  498. NULL // lpName
  499. );
  500. if (NULL == g_rgWaitEvents[RETURN_LICENSE_WAITING_DONE])
  501. {
  502. Status = GetLastError();
  503. CloseHandle(g_rgWaitEvents[RETURN_LICENSE_START_WAITING]);
  504. g_rgWaitEvents[RETURN_LICENSE_START_WAITING] = NULL;
  505. CloseHandle(g_rgWaitEvents[RETURN_LICENSE_IMMEDIATELY]);
  506. g_rgWaitEvents[RETURN_LICENSE_IMMEDIATELY] = NULL;
  507. CloseHandle(g_rgWaitEvents[RETURN_LICENSE_EXIT]);
  508. g_rgWaitEvents[RETURN_LICENSE_EXIT] = NULL;
  509. goto check_status;
  510. }
  511. hThread = CreateThread( NULL, // SecurityAttributes
  512. 0, // StackSize
  513. ReturnLicenseWorker,
  514. (LPVOID)g_rgWaitEvents,
  515. 0, // CreationFlags
  516. NULL // ThreadId
  517. );
  518. if (NULL != hThread)
  519. {
  520. CloseHandle(hThread);
  521. }
  522. else
  523. {
  524. Status = STATUS_BAD_INITIAL_PC;
  525. CloseHandle(g_rgWaitEvents[RETURN_LICENSE_START_WAITING]);
  526. g_rgWaitEvents[RETURN_LICENSE_START_WAITING] = NULL;
  527. CloseHandle(g_rgWaitEvents[RETURN_LICENSE_IMMEDIATELY]);
  528. g_rgWaitEvents[RETURN_LICENSE_IMMEDIATELY] = NULL;
  529. CloseHandle(g_rgWaitEvents[RETURN_LICENSE_EXIT]);
  530. g_rgWaitEvents[RETURN_LICENSE_EXIT] = NULL;
  531. CloseHandle(g_rgWaitEvents[RETURN_LICENSE_WAITING_DONE]);
  532. g_rgWaitEvents[RETURN_LICENSE_WAITING_DONE] = NULL;
  533. goto check_status;
  534. }
  535. }
  536. check_status:
  537. if (Status != STATUS_SUCCESS)
  538. {
  539. StopCheckingGracePeriod();
  540. if (!fStartup)
  541. {
  542. DWORD dwRet = 0;
  543. LPTSTR lpszError;
  544. BOOL fFree = TRUE;
  545. dwRet=FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  546. NULL,
  547. RtlNtStatusToDosError(Status),
  548. LANG_NEUTRAL,
  549. (LPTSTR)&lpszError,
  550. 0,
  551. NULL);
  552. if (dwRet == 0)
  553. {
  554. lpszError = (LPTSTR) LocalAlloc(LPTR,12 * sizeof(WCHAR));
  555. if (NULL != lpszError)
  556. {
  557. wsprintf(lpszError,L"%#lX",RtlNtStatusToDosError(Status));
  558. }
  559. else
  560. {
  561. lpszError = L"";
  562. fFree = FALSE;
  563. }
  564. }
  565. LicenseLogEvent(EVENTLOG_ERROR_TYPE,
  566. EVENT_LICENSING_CONCURRENT_CANT_START,
  567. 1,
  568. &lpszError
  569. );
  570. if (fFree)
  571. {
  572. LocalFree(lpszError);
  573. }
  574. }
  575. }
  576. return Status;
  577. }
  578. NTSTATUS
  579. CConcurrentPolicy::Deactivate(
  580. BOOL fShutdown
  581. )
  582. {
  583. NTSTATUS Status;
  584. if (fShutdown)
  585. {
  586. Status = STATUS_SUCCESS;
  587. }
  588. else
  589. {
  590. RtlAcquireResourceShared(&g_rwLockLicense,TRUE);
  591. Status = ReturnLicenseToLS(0);
  592. RtlReleaseResource(&g_rwLockLicense);
  593. if (Status != STATUS_SUCCESS)
  594. {
  595. LPTSTR lpszError;
  596. DWORD dwRet = 0;
  597. BOOL fFree = TRUE;
  598. dwRet=FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  599. NULL,
  600. RtlNtStatusToDosError(Status),
  601. LANG_NEUTRAL,
  602. (LPTSTR)&lpszError,
  603. 0,
  604. NULL);
  605. if (dwRet == 0)
  606. {
  607. lpszError = (LPTSTR) LocalAlloc(LPTR,12 * sizeof(WCHAR));
  608. if (NULL != lpszError)
  609. {
  610. wsprintf(lpszError,L"%#lX",RtlNtStatusToDosError(Status));
  611. }
  612. else
  613. {
  614. lpszError = L"";
  615. fFree = FALSE;
  616. }
  617. }
  618. LicenseLogEvent(EVENTLOG_ERROR_TYPE,
  619. EVENT_LICENSING_CONCURRENT_NOT_RETURNED,
  620. 1,
  621. &lpszError
  622. );
  623. if (fFree)
  624. {
  625. LocalFree(lpszError);
  626. }
  627. }
  628. StopCheckingGracePeriod();
  629. }
  630. return(Status);
  631. }
  632. /*
  633. * Licensing Functions
  634. */
  635. NTSTATUS
  636. CConcurrentPolicy::Logon(
  637. CSession& Session
  638. )
  639. {
  640. if (!Session.IsSessionZero()
  641. && !Session.IsUserHelpAssistant())
  642. {
  643. return LicenseClient(Session);
  644. }
  645. else
  646. {
  647. return STATUS_SUCCESS;
  648. }
  649. }
  650. NTSTATUS
  651. CConcurrentPolicy::Reconnect(
  652. CSession& Session,
  653. CSession& TemporarySession
  654. )
  655. {
  656. UNREFERENCED_PARAMETER(Session);
  657. if (!Session.IsSessionZero()
  658. && !Session.IsUserHelpAssistant()
  659. && !Session.GetLicenseContext()->fTsLicense)
  660. {
  661. return LicenseClient(TemporarySession);
  662. }
  663. else
  664. {
  665. return STATUS_SUCCESS;
  666. }
  667. }
  668. NTSTATUS
  669. CConcurrentPolicy::Logoff(
  670. CSession& Session
  671. )
  672. {
  673. if (!Session.IsSessionZero() && !Session.IsUserHelpAssistant())
  674. {
  675. LONG lSessions, lLastBlock;
  676. ASSERT(Session.GetLicenseContext()->fTsLicense == TRUE);
  677. lSessions = InterlockedDecrement(&g_lSessionCount);
  678. ASSERT(lSessions >= 0);
  679. RtlAcquireResourceShared(&g_rwLockLicense,TRUE);
  680. lLastBlock = g_lSessionMax - ((g_lSessionMax / g_dwIncrement) * g_dwIncrement);
  681. if (lLastBlock == 0)
  682. lLastBlock = g_dwIncrement;
  683. if (lSessions + lLastBlock <= g_lSessionMax)
  684. {
  685. TryToReturnLicenses(g_lSessionMax-lSessions);
  686. }
  687. RtlReleaseResource(&g_rwLockLicense);
  688. }
  689. return(STATUS_SUCCESS);
  690. }
  691. /*
  692. * Private License Functions
  693. */
  694. NTSTATUS
  695. CConcurrentPolicy::LicenseClient(
  696. CSession& Session
  697. )
  698. {
  699. NTSTATUS Status;
  700. LONG lSessions;
  701. lSessions = InterlockedIncrement(&g_lSessionCount);
  702. RtlAcquireResourceShared(&g_rwLockLicense,TRUE);
  703. if (lSessions > g_lSessionMax)
  704. {
  705. DWORD cBlocks = (lSessions - g_lSessionMax) / g_dwIncrement;
  706. DWORD nLeftover = (lSessions - g_lSessionMax) % g_dwIncrement;
  707. if (nLeftover > 0)
  708. {
  709. cBlocks++;
  710. }
  711. TryToAddLicenses(cBlocks * g_dwIncrement + g_lSessionMax);
  712. if (lSessions > g_lSessionMax)
  713. {
  714. if (!AllowLicensingGracePeriodConnection())
  715. {
  716. InterlockedDecrement(&g_lSessionCount);
  717. RtlReleaseResource(&g_rwLockLicense);
  718. return STATUS_CTX_LICENSE_NOT_AVAILABLE;
  719. }
  720. }
  721. }
  722. Status = CheckExpiration();
  723. RtlReleaseResource(&g_rwLockLicense);
  724. if (Status == STATUS_SUCCESS)
  725. {
  726. Status = GetLlsLicense(Session);
  727. if (Status == STATUS_SUCCESS)
  728. {
  729. Session.GetLicenseContext()->fTsLicense = TRUE;
  730. }
  731. else
  732. {
  733. InterlockedDecrement(&g_lSessionCount);
  734. }
  735. }
  736. else
  737. {
  738. InterlockedDecrement(&g_lSessionCount);
  739. }
  740. if (Status != STATUS_SUCCESS)
  741. {
  742. //
  743. // Gina doesn't understand many error codes
  744. //
  745. Status = STATUS_CTX_LICENSE_NOT_AVAILABLE;
  746. }
  747. return(Status);
  748. }
  749. LONG
  750. CConcurrentPolicy::CheckInstalledLicenses(
  751. DWORD dwWanted
  752. )
  753. {
  754. CONCURRENTLICENSEINFO_V1 LicenseInfo;
  755. LICENSE_STATUS LsStatus;
  756. ULONG cbSecretLen;
  757. cbSecretLen = sizeof(LicenseInfo);
  758. ZeroMemory(&LicenseInfo, cbSecretLen);
  759. //
  760. // Get the concurrent license count from the LSA secret
  761. //
  762. LsStatus = LsCsp_RetrieveSecret(
  763. CONCURRENT_LICENSE_STORE_LATEST_VERSION,
  764. (LPBYTE)&LicenseInfo,
  765. &cbSecretLen
  766. );
  767. if ((LsStatus != LICENSE_STATUS_OK) ||
  768. (cbSecretLen < sizeof(CONCURRENTLICENSEINFO_V1)) ||
  769. (LicenseInfo.dwLicenseVer != CURRENT_TERMINAL_SERVER_VERSION))
  770. {
  771. //
  772. // We determine that the license pack for this version is
  773. // not installed if:
  774. //
  775. // (1) we cannot retrieve the license info from the LSA secret
  776. // (2) we cannot read at least the size of version 1 of the license
  777. // info structure, or
  778. // (3) the license pack version is different from that requested.
  779. //
  780. return dwWanted;
  781. }
  782. else
  783. {
  784. LSERVERINFO LServerInfo;
  785. ULONG cbLServerInfo;
  786. cbLServerInfo = sizeof(LSERVERINFO);
  787. LsStatus = LsCsp_RetrieveSecret(
  788. CONCURRENT_LSERVER_STORE,
  789. (LPBYTE)&LServerInfo,
  790. &cbLServerInfo
  791. );
  792. if (LsStatus == LICENSE_STATUS_OK)
  793. {
  794. g_ftNotAfter = LServerInfo.ftNotAfter;
  795. if (0 == TimeToHardExpiration())
  796. {
  797. return dwWanted;
  798. }
  799. }
  800. return (dwWanted - LicenseInfo.lLicenseCount);
  801. }
  802. }
  803. VOID
  804. CConcurrentPolicy::TryToReturnLicenses(
  805. DWORD dwReturnCount
  806. )
  807. {
  808. ASSERT(dwReturnCount != 0);
  809. if (dwReturnCount > g_dwIncrement)
  810. {
  811. // Immediately return all but one block
  812. if (NULL != g_rgWaitEvents[RETURN_LICENSE_IMMEDIATELY])
  813. SetEvent(g_rgWaitEvents[RETURN_LICENSE_IMMEDIATELY]);
  814. }
  815. // Wait before returning one block
  816. if (NULL != g_rgWaitEvents[RETURN_LICENSE_START_WAITING])
  817. SetEvent(g_rgWaitEvents[RETURN_LICENSE_START_WAITING]);
  818. }
  819. //
  820. // Must have shared lock to call this
  821. //
  822. NTSTATUS
  823. ReturnLicenseToLS(
  824. LONG nNum
  825. )
  826. {
  827. HANDLE hProtocol = NULL;
  828. HWID hwid;
  829. LICENSEREQUEST LicenseRequest;
  830. LICENSE_STATUS LsStatus;
  831. LONG CurrentCount;
  832. LSERVERINFO LServerInfo;
  833. ULONG cbLServerInfo;
  834. Product_Info ProductInfo;
  835. LsStatus = InitProductInfo(
  836. &ProductInfo,
  837. PRODUCT_INFO_CONCURRENT_SKU_PRODUCT_ID
  838. );
  839. if (LsStatus != LICENSE_STATUS_OK)
  840. {
  841. return(LsStatusToNtStatus(LsStatus));
  842. }
  843. //
  844. // Get the current license count and HWID from the store.
  845. //
  846. LsStatus = GetLicenseFromStore(
  847. &CurrentCount,
  848. &hwid,
  849. CURRENT_TERMINAL_SERVER_VERSION
  850. );
  851. if (LsStatus == LICENSE_STATUS_OK)
  852. {
  853. if ((0 == nNum) || (nNum > CurrentCount))
  854. {
  855. nNum = CurrentCount;
  856. }
  857. if (CurrentCount == 0)
  858. {
  859. // We don't check for status from the following calls as we don't want to fail.
  860. LsCsp_StoreSecret( CONCURRENT_LICENSE_STORE_LATEST_VERSION, NULL, 0 );
  861. LsCsp_StoreSecret( CONCURRENT_LSERVER_STORE, NULL, 0 );
  862. return(STATUS_SUCCESS);
  863. }
  864. }
  865. else
  866. {
  867. return(LsStatusToNtStatus(LsStatus));
  868. }
  869. //
  870. // Initialize the license request structure.
  871. //
  872. ZeroMemory(&LicenseRequest, sizeof(LICENSEREQUEST));
  873. LicenseRequest.pProductInfo = &ProductInfo;
  874. LicenseRequest.dwLanguageID = GetSystemDefaultLCID();
  875. LicenseRequest.dwPlatformID = CURRENT_TERMINAL_SERVER_VERSION;
  876. LicenseRequest.cbEncryptedHwid = sizeof(HWID);
  877. LicenseRequest.pbEncryptedHwid = (PBYTE)&hwid;
  878. cbLServerInfo = sizeof(LSERVERINFO);
  879. LsStatus = LsCsp_RetrieveSecret(
  880. CONCURRENT_LSERVER_STORE,
  881. (LPBYTE)&LServerInfo,
  882. &cbLServerInfo
  883. );
  884. if (LsStatus == LICENSE_STATUS_OK)
  885. {
  886. LsStatus = CreateProtocolContext(NULL, &hProtocol);
  887. }
  888. else
  889. {
  890. goto done;
  891. }
  892. if (LsStatus == LICENSE_STATUS_OK)
  893. {
  894. LsStatus = ReturnInternetLicense(
  895. hProtocol,
  896. LServerInfo.szServerName,
  897. &LicenseRequest,
  898. LServerInfo.ulSerialNumber,
  899. nNum
  900. );
  901. }
  902. else
  903. {
  904. goto done;
  905. }
  906. if (LsStatus == LICENSE_STATUS_OK)
  907. {
  908. if( (CurrentCount-nNum) > 0 )
  909. {
  910. LsStatus = SetLicenseInStore(
  911. CurrentCount-nNum,
  912. hwid,
  913. CURRENT_TERMINAL_SERVER_VERSION
  914. );
  915. }
  916. else
  917. {
  918. // We don't check for status from the following calls as we don't want to fail.
  919. LsCsp_StoreSecret( CONCURRENT_LICENSE_STORE_LATEST_VERSION, NULL, 0 );
  920. LsCsp_StoreSecret( CONCURRENT_LSERVER_STORE, NULL, 0 );
  921. }
  922. RtlConvertSharedToExclusive(&g_rwLockLicense);
  923. g_lSessionMax = CurrentCount - nNum;
  924. RtlConvertExclusiveToShared(&g_rwLockLicense);
  925. }
  926. done:
  927. if (hProtocol != NULL)
  928. {
  929. DeleteProtocolContext(hProtocol);
  930. }
  931. if (ProductInfo.pbCompanyName)
  932. {
  933. LocalFree(ProductInfo.pbCompanyName);
  934. }
  935. if (ProductInfo.pbProductID)
  936. {
  937. LocalFree(ProductInfo.pbProductID);
  938. }
  939. return(LsStatusToNtStatus(LsStatus));
  940. }
  941. DWORD
  942. CConcurrentPolicy::GenerateHwidFromComputerName(
  943. HWID *hwid
  944. )
  945. {
  946. MD5_CTX HashState;
  947. WCHAR wszName[MAX_COMPUTERNAME_LENGTH * 9]; // buffer we hope is big enough
  948. DWORD cbName = sizeof(wszName) / sizeof(TCHAR);
  949. BOOL fRet;
  950. //
  951. // get computer name
  952. //
  953. fRet = GetComputerNameEx(ComputerNamePhysicalDnsFullyQualified,
  954. wszName,
  955. &cbName);
  956. if (!fRet)
  957. {
  958. return GetLastError();
  959. }
  960. //
  961. // generate the hash on the data.
  962. //
  963. MD5Init( &HashState );
  964. MD5Update( &HashState, (LPBYTE)wszName, cbName );
  965. MD5Final( &HashState );
  966. memcpy((LPBYTE)hwid,HashState.digest,sizeof(HashState.digest));
  967. // fill in the rest with characters from computer name
  968. lstrcpyn((LPWSTR)(((LPBYTE)hwid)+sizeof(HashState.digest)),
  969. wszName,
  970. (sizeof(HWID)-sizeof(HashState.digest))/sizeof(WCHAR));
  971. return ERROR_SUCCESS;
  972. }
  973. //
  974. // Must have shared lock to call this
  975. //
  976. VOID
  977. CConcurrentPolicy::TryToAddLicenses(
  978. DWORD dwTotalWanted
  979. )
  980. {
  981. NTSTATUS Status;
  982. BOOL fRetrievedAll;
  983. // Releasing g_rwLockLicense that other threads may be sharing, avoiding
  984. // possibility of deadlock if a thread calls RtlConvertSharedToExclusive
  985. // while holding g_csAddLicenses
  986. RtlReleaseResource(&g_rwLockLicense);
  987. RtlEnterCriticalSection(&g_csAddLicenses);
  988. // Reacquiring the shared lock that was released
  989. RtlAcquireResourceShared(&g_rwLockLicense,TRUE);
  990. if (WAIT_TIMEOUT == WaitForSingleObject(g_hOkayToAdd,0))
  991. {
  992. // We're in waiting period
  993. RtlLeaveCriticalSection(&g_csAddLicenses);
  994. return;
  995. }
  996. if (g_lSessionMax >= (LONG) dwTotalWanted)
  997. {
  998. // we already have enough
  999. RtlLeaveCriticalSection(&g_csAddLicenses);
  1000. return;
  1001. }
  1002. Status = GetLicenseFromLS(dwTotalWanted - g_lSessionMax,
  1003. FALSE, // fIgnoreCurrentCount
  1004. &fRetrievedAll);
  1005. if ((Status != STATUS_SUCCESS) || (!fRetrievedAll))
  1006. {
  1007. LARGE_INTEGER liWait;
  1008. // wait before adding more
  1009. liWait.QuadPart = (__int64) g_dwWaitTimeAdd * (-10 * 1000 * 1000);
  1010. SetWaitableTimer(g_hOkayToAdd,
  1011. &liWait, // pDueTime
  1012. g_dwWaitTimeAdd * 1000, // lPeriod
  1013. NULL, // pfnCompletionRoutine
  1014. NULL, // lpArgToCompletionRoutine
  1015. FALSE // fResume (from suspended)
  1016. );
  1017. }
  1018. RtlLeaveCriticalSection(&g_csAddLicenses);
  1019. }
  1020. //
  1021. // Must have shared lock to call this
  1022. //
  1023. NTSTATUS
  1024. CConcurrentPolicy::GetLicenseFromLS(
  1025. LONG nNumToAdd,
  1026. BOOL fIgnoreCurrentCount,
  1027. BOOL *pfRetrievedAll
  1028. )
  1029. {
  1030. BOOL fHwidSet;
  1031. BOOL fRet;
  1032. DWORD cbLicense;
  1033. DWORD cbSecretKey;
  1034. DWORD cchComputerName = MAX_COMPUTERNAME_LENGTH + 1;
  1035. DWORD dwNumLicensedProduct = 0;
  1036. DWORD dwStatus;
  1037. HANDLE hProtocol;
  1038. HWID hwid;
  1039. HWID hwidEncrypted;
  1040. LICENSE_STATUS LsStatus;
  1041. LICENSEREQUEST LicenseRequest;
  1042. LONG CurrentCount;
  1043. LSERVERINFO LServerInfo;
  1044. ULONG cbLServerInfo;
  1045. NTSTATUS Status;
  1046. PBYTE pbLicense;
  1047. PBYTE pbSecretKey;
  1048. PLICENSEDPRODUCT pLicensedProduct;
  1049. Product_Info ProductInfo;
  1050. WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  1051. TCHAR *pszLicenseServerName = LServerInfo.szServerName;
  1052. DWORD dwNumLicensesRetrieved = 0;
  1053. if (nNumToAdd < 0)
  1054. {
  1055. return STATUS_INVALID_PARAMETER;
  1056. }
  1057. if (nNumToAdd == 0)
  1058. {
  1059. if (NULL != pfRetrievedAll)
  1060. *pfRetrievedAll = TRUE;
  1061. return STATUS_SUCCESS;
  1062. }
  1063. if (NULL != pfRetrievedAll)
  1064. *pfRetrievedAll = FALSE;
  1065. //
  1066. // These variables must be initialized here, or else any of the gotos
  1067. // below may cause them to be used without initialization.
  1068. //
  1069. hProtocol = NULL;
  1070. pbLicense = NULL;
  1071. pbSecretKey = NULL;
  1072. pLicensedProduct = NULL;
  1073. Status = STATUS_SUCCESS;
  1074. ZeroMemory(&ProductInfo, sizeof(Product_Info));
  1075. //
  1076. // Get the current license count and HWID from the store. Failure is not
  1077. // fatal.
  1078. //
  1079. LsStatus = GetLicenseFromStore(
  1080. &CurrentCount,
  1081. &hwidEncrypted,
  1082. CURRENT_TERMINAL_SERVER_VERSION
  1083. );
  1084. if (LsStatus == LICENSE_STATUS_OK)
  1085. {
  1086. fHwidSet = TRUE;
  1087. if (fIgnoreCurrentCount)
  1088. {
  1089. CurrentCount = 0;
  1090. }
  1091. }
  1092. else
  1093. {
  1094. CurrentCount = 0;
  1095. fHwidSet = FALSE;
  1096. }
  1097. //
  1098. // Initialize the product info.
  1099. //
  1100. LsStatus = InitProductInfo(
  1101. &ProductInfo,
  1102. PRODUCT_INFO_CONCURRENT_SKU_PRODUCT_ID
  1103. );
  1104. if (LsStatus == LICENSE_STATUS_OK)
  1105. {
  1106. //
  1107. // Initialize the license request structure.
  1108. //
  1109. ZeroMemory(&LicenseRequest, sizeof(LicenseRequest));
  1110. LicenseRequest.pProductInfo = &ProductInfo;
  1111. LicenseRequest.dwLanguageID = GetSystemDefaultLCID();
  1112. LicenseRequest.dwPlatformID = CURRENT_TERMINAL_SERVER_VERSION;
  1113. LicenseRequest.cbEncryptedHwid = sizeof(HWID);
  1114. }
  1115. else
  1116. {
  1117. goto done;
  1118. }
  1119. if (!fHwidSet)
  1120. {
  1121. //
  1122. // No hardware ID yet - create one
  1123. //
  1124. dwStatus = GenerateHwidFromComputerName(&hwid);
  1125. if (dwStatus == ERROR_SUCCESS)
  1126. {
  1127. LsStatus = LsCsp_EncryptHwid(
  1128. &hwid,
  1129. (PBYTE)&hwidEncrypted,
  1130. &(LicenseRequest.cbEncryptedHwid)
  1131. );
  1132. if (LsStatus == LICENSE_STATUS_OK)
  1133. {
  1134. fHwidSet = TRUE;
  1135. }
  1136. else
  1137. {
  1138. goto done;
  1139. }
  1140. }
  1141. else
  1142. {
  1143. Status = STATUS_BUFFER_TOO_SMALL;
  1144. goto done;
  1145. }
  1146. }
  1147. LicenseRequest.pbEncryptedHwid = (PBYTE)&hwidEncrypted;
  1148. //
  1149. // get our computer name
  1150. //
  1151. fRet = GetComputerName(szComputerName, &cchComputerName);
  1152. if (fRet)
  1153. {
  1154. LsStatus = CreateProtocolContext(NULL, &hProtocol);
  1155. }
  1156. else
  1157. {
  1158. Status = STATUS_UNSUCCESSFUL;
  1159. goto done;
  1160. }
  1161. if (0 == CurrentCount)
  1162. {
  1163. // any license server will do
  1164. pszLicenseServerName = NULL;
  1165. }
  1166. else
  1167. {
  1168. cbLServerInfo = sizeof(LSERVERINFO);
  1169. LsStatus = LsCsp_RetrieveSecret(
  1170. CONCURRENT_LSERVER_STORE,
  1171. (LPBYTE)&LServerInfo,
  1172. &cbLServerInfo
  1173. );
  1174. if (LsStatus != LICENSE_STATUS_OK)
  1175. {
  1176. // no license server known; any will do
  1177. pszLicenseServerName = NULL;
  1178. }
  1179. }
  1180. cbLicense = 0;
  1181. if (LsStatus == LICENSE_STATUS_OK)
  1182. {
  1183. //
  1184. // NB: even if CurrentCount>0, license server will know about
  1185. // existing licenses, and do a proper upgrade
  1186. //
  1187. dwNumLicensesRetrieved = nNumToAdd+CurrentCount;
  1188. LsStatus = RequestNewLicense(
  1189. hProtocol,
  1190. pszLicenseServerName,
  1191. &LicenseRequest,
  1192. szComputerName,
  1193. szComputerName,
  1194. FALSE, // bAcceptTemporaryLicense
  1195. TRUE, // bAcceptFewerLicenses
  1196. &dwNumLicensesRetrieved,
  1197. &cbLicense,
  1198. &pbLicense
  1199. );
  1200. if ((NULL != pfRetrievedAll)
  1201. && (LsStatus == LICENSE_STATUS_OK)
  1202. && ((LONG)dwNumLicensesRetrieved == nNumToAdd+CurrentCount))
  1203. {
  1204. *pfRetrievedAll = TRUE;
  1205. }
  1206. }
  1207. else
  1208. {
  1209. goto done;
  1210. }
  1211. if (LsStatus == LICENSE_STATUS_OK)
  1212. {
  1213. //
  1214. // Get the secret key that is used to decode the license
  1215. //
  1216. cbSecretKey = 0;
  1217. LicenseGetSecretKey(&cbSecretKey, NULL);
  1218. pbSecretKey = (PBYTE)LocalAlloc(LPTR, cbSecretKey);
  1219. if (pbSecretKey != NULL)
  1220. {
  1221. LsStatus = LicenseGetSecretKey(&cbSecretKey, pbSecretKey);
  1222. }
  1223. else
  1224. {
  1225. Status = STATUS_NO_MEMORY;
  1226. goto done;
  1227. }
  1228. }
  1229. else
  1230. {
  1231. goto done;
  1232. }
  1233. //
  1234. // Decode license issued by hydra license server certificate engine.
  1235. //
  1236. __try
  1237. {
  1238. //
  1239. // Check size of decoded licenses.
  1240. //
  1241. LsStatus = LSVerifyDecodeClientLicense(
  1242. pbLicense,
  1243. cbLicense,
  1244. pbSecretKey,
  1245. cbSecretKey,
  1246. &dwNumLicensedProduct,
  1247. NULL
  1248. );
  1249. if (LsStatus == LICENSE_STATUS_OK)
  1250. {
  1251. pLicensedProduct = (PLICENSEDPRODUCT)LocalAlloc(
  1252. LPTR,
  1253. sizeof(LICENSEDPRODUCT) * dwNumLicensedProduct
  1254. );
  1255. }
  1256. else
  1257. {
  1258. goto done;
  1259. }
  1260. if (pLicensedProduct != NULL)
  1261. {
  1262. //
  1263. // Decode the license.
  1264. //
  1265. LsStatus = LSVerifyDecodeClientLicense(
  1266. pbLicense,
  1267. cbLicense,
  1268. pbSecretKey,
  1269. cbSecretKey,
  1270. &dwNumLicensedProduct,
  1271. pLicensedProduct
  1272. );
  1273. }
  1274. else
  1275. {
  1276. Status = STATUS_NO_MEMORY;
  1277. goto done;
  1278. }
  1279. }
  1280. __except( EXCEPTION_EXECUTE_HANDLER )
  1281. {
  1282. LsStatus = LICENSE_STATUS_CANNOT_DECODE_LICENSE;
  1283. }
  1284. if (LsStatus == LICENSE_STATUS_OK)
  1285. {
  1286. ReceivedPermanentLicense();
  1287. LServerInfo.cchServerName = lstrlen(pLicensedProduct->szIssuer);
  1288. lstrcpynW(
  1289. LServerInfo.szServerName,
  1290. pLicensedProduct->szIssuer,
  1291. sizeof(LServerInfo.szServerName) / sizeof(WCHAR)
  1292. );
  1293. LServerInfo.ulSerialNumber = pLicensedProduct->ulSerialNumber;
  1294. LServerInfo.ftNotAfter = pLicensedProduct->NotAfter;
  1295. g_ftNotAfter = LServerInfo.ftNotAfter;
  1296. LsStatus = LsCsp_StoreSecret(
  1297. CONCURRENT_LSERVER_STORE,
  1298. (LPBYTE)&LServerInfo,
  1299. sizeof(LServerInfo)
  1300. );
  1301. }
  1302. else
  1303. {
  1304. goto done;
  1305. }
  1306. if (LsStatus == LICENSE_STATUS_OK)
  1307. {
  1308. //
  1309. // Adjust the license count in the local LSA store.
  1310. //
  1311. LsStatus = SetLicenseInStore(
  1312. dwNumLicensesRetrieved,
  1313. hwidEncrypted,
  1314. CURRENT_TERMINAL_SERVER_VERSION
  1315. );
  1316. RtlConvertSharedToExclusive(&g_rwLockLicense);
  1317. g_lSessionMax = dwNumLicensesRetrieved;
  1318. RtlConvertExclusiveToShared(&g_rwLockLicense);
  1319. }
  1320. done:
  1321. if (hProtocol != NULL)
  1322. {
  1323. DeleteProtocolContext(hProtocol);
  1324. }
  1325. if (pbLicense != NULL)
  1326. {
  1327. LocalFree(pbLicense);
  1328. }
  1329. if (pbSecretKey != NULL)
  1330. {
  1331. LocalFree(pbSecretKey);
  1332. }
  1333. if (pLicensedProduct != NULL)
  1334. {
  1335. for (DWORD dwCount = 0; dwCount < dwNumLicensedProduct; dwCount++)
  1336. {
  1337. LSFreeLicensedProduct(pLicensedProduct+dwCount);
  1338. }
  1339. }
  1340. if (ProductInfo.pbCompanyName != NULL)
  1341. {
  1342. LocalFree(ProductInfo.pbCompanyName);
  1343. }
  1344. if (ProductInfo.pbProductID != NULL)
  1345. {
  1346. LocalFree(ProductInfo.pbProductID);
  1347. }
  1348. if (Status == STATUS_SUCCESS)
  1349. {
  1350. return(LsStatusToNtStatus(LsStatus));
  1351. }
  1352. else
  1353. {
  1354. return(Status);
  1355. }
  1356. }
  1357. LICENSE_STATUS
  1358. GetLicenseFromStore(
  1359. PLONG pLicenseCount,
  1360. PHWID phwid,
  1361. DWORD dwLicenseVer
  1362. )
  1363. {
  1364. CONCURRENTLICENSEINFO_V1 LicenseInfo;
  1365. LICENSE_STATUS LsStatus;
  1366. ULONG cbSecretLen;
  1367. ASSERT(pLicenseCount != NULL);
  1368. ASSERT(phwid != NULL);
  1369. cbSecretLen = sizeof(CONCURRENTLICENSEINFO_V1);
  1370. ZeroMemory(&LicenseInfo, cbSecretLen);
  1371. //
  1372. // Get the license count from the LSA secret
  1373. //
  1374. LsStatus = LsCsp_RetrieveSecret(
  1375. CONCURRENT_LICENSE_STORE_LATEST_VERSION,
  1376. (LPBYTE)&LicenseInfo,
  1377. &cbSecretLen
  1378. );
  1379. if ((LsStatus != LICENSE_STATUS_OK) ||
  1380. (cbSecretLen < sizeof(CONCURRENTLICENSEINFO_V1)) ||
  1381. (LicenseInfo.dwLicenseVer != dwLicenseVer))
  1382. {
  1383. //
  1384. // We determine that the license pack for this version is
  1385. // not installed if we:
  1386. //
  1387. // (1) cannot retrieve the license info from the LSA secret
  1388. // (2) cannot read at least the size of version 1 of the license info
  1389. // structure.
  1390. // (3) the license pack version is different from that requested.
  1391. //
  1392. LsStatus = LICENSE_STATUS_NO_LICENSE_ERROR;
  1393. // We don't check for status from the following as we don't want to fail.
  1394. LsCsp_StoreSecret( CONCURRENT_LICENSE_STORE_LATEST_VERSION, NULL, 0 );
  1395. LsCsp_StoreSecret( CONCURRENT_LSERVER_STORE, NULL, 0 );
  1396. }
  1397. else
  1398. {
  1399. *pLicenseCount = LicenseInfo.lLicenseCount;
  1400. *phwid = LicenseInfo.hwid;
  1401. }
  1402. return(LsStatus);
  1403. }
  1404. LICENSE_STATUS
  1405. SetLicenseInStore(
  1406. LONG LicenseCount,
  1407. HWID hwid,
  1408. DWORD dwLicenseVer
  1409. )
  1410. {
  1411. CONCURRENTLICENSEINFO_V1 LicenseInfo;
  1412. LICENSE_STATUS LsStatus;
  1413. //
  1414. // verify that the license count to set is not negative.
  1415. //
  1416. ASSERT(LicenseCount >= 0);
  1417. //
  1418. // initialize the license information to store
  1419. //
  1420. LicenseInfo.dwStructVer = CONCURRENTLICENSEINFO_TYPE_V1;
  1421. LicenseInfo.dwLicenseVer = dwLicenseVer;
  1422. LicenseInfo.hwid = hwid;
  1423. LicenseInfo.lLicenseCount = LicenseCount;
  1424. //
  1425. // store the new license count
  1426. //
  1427. LsStatus = LsCsp_StoreSecret(
  1428. CONCURRENT_LICENSE_STORE_LATEST_VERSION,
  1429. (LPBYTE)&LicenseInfo,
  1430. sizeof(CONCURRENTLICENSEINFO_V1)
  1431. );
  1432. return(LsStatus);
  1433. }
  1434. /*
  1435. * Private Functions
  1436. */
  1437. //
  1438. // Must have shared lock to call this
  1439. //
  1440. NTSTATUS
  1441. CConcurrentPolicy::CheckExpiration(
  1442. )
  1443. {
  1444. DWORD dwWait = TimeToSoftExpiration();
  1445. NTSTATUS Status = STATUS_SUCCESS;
  1446. if (0 == dwWait)
  1447. {
  1448. // Soft expiration reached, time to renew
  1449. Status = GetLicenseFromLS(g_lSessionMax,
  1450. TRUE, // fIgnoreCurrentCount
  1451. NULL);
  1452. if ((STATUS_SUCCESS != Status) && (0 == TimeToHardExpiration()))
  1453. {
  1454. // Couldn't renew and we're past hard expiration
  1455. LicenseLogEvent(EVENTLOG_ERROR_TYPE,
  1456. EVENT_LICENSING_CONCURRENT_EXPIRED,
  1457. 0,
  1458. NULL
  1459. );
  1460. RtlConvertSharedToExclusive(&g_rwLockLicense);
  1461. g_lSessionMax = 0;
  1462. RtlConvertExclusiveToShared(&g_rwLockLicense);
  1463. }
  1464. else
  1465. {
  1466. Status = STATUS_SUCCESS;
  1467. }
  1468. }
  1469. return Status;
  1470. }
  1471. /*
  1472. * Global Static Functions
  1473. */
  1474. DWORD
  1475. CConcurrentPolicy::TimeToSoftExpiration(
  1476. )
  1477. {
  1478. SYSTEMTIME stNow;
  1479. FILETIME ftNow;
  1480. ULARGE_INTEGER ullNotAfterLeeway;
  1481. ULARGE_INTEGER ullNow;
  1482. ULARGE_INTEGER ullDiff;
  1483. DWORD dwDiff = 0;
  1484. GetSystemTime(&stNow);
  1485. SystemTimeToFileTime(&stNow,&ftNow);
  1486. ullNow.LowPart = ftNow.dwLowDateTime;
  1487. ullNow.HighPart = ftNow.dwHighDateTime;
  1488. ullNotAfterLeeway.LowPart = g_ftNotAfter.dwLowDateTime;
  1489. ullNotAfterLeeway.HighPart = g_ftNotAfter.dwHighDateTime;
  1490. ullNotAfterLeeway.QuadPart -= (__int64) LC_POLICY_CONCURRENT_EXPIRATION_LEEWAY * 10 * 1000;
  1491. if (ullNotAfterLeeway.QuadPart > ullNow.QuadPart)
  1492. {
  1493. ullDiff.QuadPart = ullNotAfterLeeway.QuadPart - ullNow.QuadPart;
  1494. ullDiff.QuadPart /= (10 * 1000);
  1495. if (ullDiff.HighPart == 0)
  1496. {
  1497. dwDiff = ullDiff.LowPart;
  1498. }
  1499. else
  1500. {
  1501. // too big, return max
  1502. dwDiff = ULONG_MAX;
  1503. }
  1504. }
  1505. return dwDiff;
  1506. }
  1507. DWORD
  1508. CConcurrentPolicy::TimeToHardExpiration(
  1509. )
  1510. {
  1511. SYSTEMTIME stNow;
  1512. FILETIME ftNow;
  1513. ULARGE_INTEGER ullNotAfterLeeway;
  1514. ULARGE_INTEGER ullNow;
  1515. ULARGE_INTEGER ullDiff;
  1516. DWORD dwDiff = 0;
  1517. GetSystemTime(&stNow);
  1518. SystemTimeToFileTime(&stNow,&ftNow);
  1519. ullNow.LowPart = ftNow.dwLowDateTime;
  1520. ullNow.HighPart = ftNow.dwHighDateTime;
  1521. ullNotAfterLeeway.LowPart = g_ftNotAfter.dwLowDateTime;
  1522. ullNotAfterLeeway.HighPart = g_ftNotAfter.dwHighDateTime;
  1523. if (ullNotAfterLeeway.QuadPart > ullNow.QuadPart)
  1524. {
  1525. ullDiff.QuadPart = ullNotAfterLeeway.QuadPart - ullNow.QuadPart;
  1526. ullDiff.QuadPart /= (10 * 1000);
  1527. if (ullDiff.HighPart == 0)
  1528. {
  1529. dwDiff = ullDiff.LowPart;
  1530. }
  1531. else
  1532. {
  1533. // too big, return max
  1534. dwDiff = ULONG_MAX;
  1535. }
  1536. }
  1537. return dwDiff;
  1538. }
  1539. VOID
  1540. CConcurrentPolicy::ReadLicensingParameters(
  1541. )
  1542. {
  1543. HKEY hKey = NULL;
  1544. DWORD dwStatus = ERROR_SUCCESS;
  1545. DWORD dwBuffer;
  1546. DWORD cbBuffer;
  1547. g_dwIncrement = LC_POLICY_CONCURRENT_LICENSE_COUNT_INCREMENT;
  1548. g_dwWaitTimeAdd = LC_POLICY_CONCURRENT_WAIT_TIME_ADD;
  1549. g_dwWaitTimeRemove = LC_POLICY_CONCURRENT_WAIT_TIME_REMOVE;
  1550. dwStatus =RegOpenKeyEx(
  1551. HKEY_LOCAL_MACHINE,
  1552. LCREG_CONCURRENTKEY,
  1553. 0,
  1554. KEY_READ,
  1555. &hKey
  1556. );
  1557. if(dwStatus == ERROR_SUCCESS)
  1558. {
  1559. cbBuffer = sizeof(dwBuffer);
  1560. dwStatus = RegQueryValueEx(
  1561. hKey,
  1562. LCREG_INCREMENT,
  1563. NULL,
  1564. NULL,
  1565. (LPBYTE)&dwBuffer,
  1566. &cbBuffer
  1567. );
  1568. if (dwStatus == ERROR_SUCCESS)
  1569. {
  1570. g_dwIncrement = max(dwBuffer, 1);
  1571. }
  1572. cbBuffer = sizeof(dwBuffer);
  1573. dwStatus = RegQueryValueEx(
  1574. hKey,
  1575. LCREG_WAIT_TIME_ADD,
  1576. NULL,
  1577. NULL,
  1578. (LPBYTE)&dwBuffer,
  1579. &cbBuffer
  1580. );
  1581. if (dwStatus == ERROR_SUCCESS)
  1582. {
  1583. g_dwWaitTimeAdd = max(dwBuffer, 1);
  1584. }
  1585. cbBuffer = sizeof(dwBuffer);
  1586. dwStatus = RegQueryValueEx(
  1587. hKey,
  1588. LCREG_WAIT_TIME_REMOVE,
  1589. NULL,
  1590. NULL,
  1591. (LPBYTE)&dwBuffer,
  1592. &cbBuffer
  1593. );
  1594. if (dwStatus == ERROR_SUCCESS)
  1595. {
  1596. g_dwWaitTimeRemove = max(dwBuffer, 1);
  1597. }
  1598. RegCloseKey(hKey);
  1599. }
  1600. }