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.

892 lines
25 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996-1998
  5. //
  6. // File: permlic.cpp
  7. //
  8. // Contents:
  9. // Issue perm. license to client
  10. //
  11. // History:
  12. // Feb 4, 98 HueiWang Created
  13. //---------------------------------------------------------------------------
  14. #include "pch.cpp"
  15. #include "globals.h"
  16. #include "permlic.h"
  17. #include "misc.h"
  18. #include "db.h"
  19. #include "clilic.h"
  20. #include "findlost.h"
  21. #include <winsta.h>
  22. DWORD
  23. GenerateRandomNumber(
  24. IN DWORD Seed
  25. );
  26. void
  27. LicensedProductToDbLicensedProduct(
  28. PLICENSEDPRODUCT pSrc,
  29. PTLSDBLICENSEDPRODUCT pDest
  30. );
  31. void
  32. CopyDbLicensedProduct(
  33. PTLSDBLICENSEDPRODUCT pSrc,
  34. PTLSDBLICENSEDPRODUCT pDest
  35. );
  36. //-------------------------------------------------------------------------
  37. //
  38. // Memory leak at service shutdown time
  39. //
  40. typedef struct __LoggedLowLicenseProduct {
  41. LPTSTR pszCompanyName;
  42. LPTSTR pszProductId;
  43. DWORD dwProductVersion;
  44. __LoggedLowLicenseProduct() : pszProductId(NULL), pszCompanyName(NULL) {};
  45. friend bool
  46. operator<(
  47. const __LoggedLowLicenseProduct&,
  48. const __LoggedLowLicenseProduct&
  49. );
  50. } LoggedLowLicenseProduct;
  51. //-------------------------------------------------------------------------
  52. inline bool
  53. operator<(
  54. const __LoggedLowLicenseProduct& a,
  55. const __LoggedLowLicenseProduct& b
  56. )
  57. /*++
  58. --*/
  59. {
  60. bool bStatus;
  61. TLSASSERT(a.pszCompanyName != NULL && b.pszCompanyName != NULL);
  62. TLSASSERT(a.pszProductId != NULL && b.pszProductId != NULL);
  63. // in case we mess up...
  64. if(a.pszProductId == NULL || a.pszCompanyName == NULL)
  65. {
  66. bStatus = TRUE;
  67. }
  68. else if(b.pszProductId == NULL || b.pszCompanyName == NULL)
  69. {
  70. bStatus = FALSE;
  71. }
  72. else
  73. {
  74. bStatus = (_tcsicmp(a.pszCompanyName, b.pszCompanyName) < 0);
  75. if(bStatus == TRUE)
  76. {
  77. bStatus = (_tcsicmp(a.pszProductId, b.pszProductId) < 0);
  78. }
  79. if(bStatus == TRUE)
  80. {
  81. bStatus = (CompareTLSVersions(a.dwProductVersion, b.dwProductVersion) < 0);
  82. }
  83. }
  84. return bStatus;
  85. }
  86. //-------------------------------------------------------------------------
  87. typedef map<
  88. LoggedLowLicenseProduct,
  89. BOOL,
  90. less<LoggedLowLicenseProduct>
  91. > LOGLOWLICENSEMAP;
  92. static CCriticalSection LogLock;
  93. static LOGLOWLICENSEMAP LowLicenseLog;
  94. //---------------------------------------------------------------
  95. void
  96. TLSResetLogLowLicenseWarning(
  97. IN LPTSTR pszCompanyName,
  98. IN LPTSTR pszProductId,
  99. IN DWORD dwProductVersion,
  100. IN BOOL bLogged
  101. )
  102. /*++
  103. --*/
  104. {
  105. LOGLOWLICENSEMAP::iterator it;
  106. LoggedLowLicenseProduct product;
  107. product.pszCompanyName = pszCompanyName;
  108. product.pszProductId = pszProductId;
  109. product.dwProductVersion = dwProductVersion;
  110. LogLock.Lock();
  111. try {
  112. it = LowLicenseLog.find(product);
  113. if(it != LowLicenseLog.end())
  114. {
  115. // reset to not logged warning yet.
  116. (*it).second = bLogged;
  117. }
  118. else if(bLogged == TRUE)
  119. {
  120. memset(&product, 0, sizeof(product));
  121. // memory leak here at service stop.
  122. product.pszProductId = _tcsdup(pszProductId);
  123. product.pszCompanyName = _tcsdup(pszCompanyName);
  124. product.dwProductVersion = dwProductVersion;
  125. if(product.pszProductId != NULL && product.pszCompanyName != NULL)
  126. {
  127. LowLicenseLog[product] = TRUE;
  128. }
  129. else
  130. {
  131. // if unable to allocate any more memory, log message every time
  132. if(product.pszProductId != NULL)
  133. {
  134. free(product.pszProductId);
  135. }
  136. if(product.pszCompanyName != NULL)
  137. {
  138. free(product.pszCompanyName);
  139. }
  140. }
  141. }
  142. }
  143. catch(...) {
  144. }
  145. LogLock.UnLock();
  146. return;
  147. }
  148. //---------------------------------------------------------------
  149. void
  150. TLSLogLowLicenseWarning(
  151. IN PTLSDbWorkSpace pDbWkSpace,
  152. IN PTLSDBLICENSEREQUEST pRequest,
  153. IN BOOL bNoLicense
  154. )
  155. /*++
  156. Abstract:
  157. Log an low license count warning.
  158. Parameter:
  159. pDbWkSpace - Workspace handle.
  160. pRequest - License Request.
  161. Workspace - No license available.
  162. LicensePack - License pack that is out of license
  163. return:
  164. None
  165. --*/
  166. {
  167. LOGLOWLICENSEMAP::iterator it;
  168. BOOL bWarningLogged = FALSE;
  169. DWORD dwStatus;
  170. if( pRequest == NULL || pRequest->pClientLicenseRequest == NULL ||
  171. pRequest->pClientLicenseRequest->pszProductId == NULL )
  172. {
  173. TLSASSERT(FALSE);
  174. return;
  175. }
  176. LoggedLowLicenseProduct product;
  177. product.pszProductId = pRequest->pClientLicenseRequest->pszProductId;
  178. product.pszCompanyName = pRequest->pClientLicenseRequest->pszCompanyName;
  179. product.dwProductVersion = pRequest->pClientLicenseRequest->dwProductVersion;
  180. LogLock.Lock();
  181. try {
  182. // see if we already log this warning message
  183. it = LowLicenseLog.find(product);
  184. if(it == LowLicenseLog.end())
  185. {
  186. memset(&product, 0, sizeof(product));
  187. // memory leak here at service stop.
  188. product.pszProductId = _tcsdup(pRequest->pClientLicenseRequest->pszProductId);
  189. product.pszCompanyName = _tcsdup(pRequest->pClientLicenseRequest->pszCompanyName);
  190. product.dwProductVersion = pRequest->pClientLicenseRequest->dwProductVersion;
  191. if(product.pszProductId != NULL && product.pszCompanyName != NULL)
  192. {
  193. LowLicenseLog[product] = TRUE;
  194. }
  195. else
  196. {
  197. // if unable to allocate any more memory, log message every time
  198. if(product.pszProductId != NULL)
  199. {
  200. free(product.pszProductId);
  201. }
  202. if(product.pszCompanyName != NULL)
  203. {
  204. free(product.pszCompanyName);
  205. }
  206. }
  207. }
  208. else
  209. {
  210. bWarningLogged = (*it).second;
  211. (*it).second = TRUE;
  212. }
  213. }
  214. catch(...) {
  215. // assuming no message has been logged.
  216. bWarningLogged = FALSE;
  217. }
  218. LogLock.UnLock();
  219. if(bWarningLogged == TRUE)
  220. {
  221. return;
  222. }
  223. //
  224. // ask policy module if they have description
  225. //
  226. PMKEYPACKDESCREQ kpDescReq;
  227. PPMKEYPACKDESC pKpDesc;
  228. //
  229. // Ask for default system language ID
  230. //
  231. kpDescReq.pszProductId = pRequest->pszProductId;
  232. kpDescReq.dwLangId = GetSystemDefaultLangID();
  233. kpDescReq.dwVersion = pRequest->dwProductVersion;
  234. pKpDesc = NULL;
  235. dwStatus = pRequest->pPolicy->PMLicenseRequest(
  236. pRequest->hClient,
  237. REQUEST_KEYPACKDESC,
  238. (PVOID)&kpDescReq,
  239. (PVOID *)&pKpDesc
  240. );
  241. if(dwStatus != ERROR_SUCCESS || pKpDesc == NULL)
  242. {
  243. if(GetSystemDefaultLangID() != MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US))
  244. {
  245. // see if we have any US desc.
  246. kpDescReq.dwLangId = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
  247. pKpDesc = NULL;
  248. dwStatus = pRequest->pPolicy->PMLicenseRequest(
  249. pRequest->hClient,
  250. REQUEST_KEYPACKDESC,
  251. (PVOID)&kpDescReq,
  252. (PVOID *)&pKpDesc
  253. );
  254. }
  255. }
  256. LPCTSTR pString[2];
  257. pString[0] = g_szComputerName;
  258. pString[1] = (dwStatus == ERROR_SUCCESS && pKpDesc != NULL) ? pKpDesc->szProductDesc :
  259. pRequest->pClientLicenseRequest->pszProductId;
  260. TLSLogEventString(
  261. EVENTLOG_WARNING_TYPE,
  262. (bNoLicense == TRUE) ? TLS_W_NOPERMLICENSE : TLS_W_PRODUCTNOTINSTALL,
  263. sizeof(pString)/sizeof(pString[0]),
  264. pString
  265. );
  266. return;
  267. }
  268. //--------------------------------------------------------------------------------
  269. DWORD
  270. TLSDBIssuePermanentLicense(
  271. IN PTLSDbWorkSpace pDbWkSpace,
  272. IN PTLSDBLICENSEREQUEST pRequest,
  273. IN BOOL bLatestVersion,
  274. IN BOOL bAcceptFewerLicenses,
  275. IN OUT DWORD *pdwQuantity,
  276. IN OUT PTLSDBLICENSEDPRODUCT pLicensedProduct,
  277. IN DWORD dwSupportFlags
  278. )
  279. /*
  280. Abstract:
  281. Routine to allocate a perm. license.
  282. Parameters:
  283. pDbWkSpace - Workspace handle.
  284. pRequest - license request.
  285. bLatestVersion - Request latest version (unused)
  286. bAcceptFewerLicenses - TRUE if succeeding with fewer licenses than
  287. requested is acceptable
  288. pdwQuantity - on input, number of licenses to allocate. on output,
  289. number of licenses actually allocated
  290. IN OUT pLicensedProduct - licensed product
  291. dwSupportFlags - abilities supported by TS and LS.
  292. Returns:
  293. */
  294. {
  295. DWORD status=ERROR_SUCCESS;
  296. ULARGE_INTEGER ulSerialNumber;
  297. DWORD dwLicenseId;
  298. TLSLICENSEPACK LicensePack;
  299. UCHAR ucKeyPackStatus;
  300. LICENSEDCLIENT issuedLicense;
  301. DWORD CertSerialNumber;
  302. PMGENERATELICENSE PolModGenLicense;
  303. PPMCERTEXTENSION pPolModCertExtension=NULL;
  304. FILETIME notBefore, notAfter;
  305. UCHAR ucAgreementType;
  306. memset(&ulSerialNumber, 0, sizeof(ulSerialNumber));
  307. //----------------------------------------------------------------------
  308. //
  309. // this step require reduce available license by dwQuantity
  310. //
  311. status=TLSDBGetPermanentLicense(
  312. pDbWkSpace,
  313. pRequest,
  314. bAcceptFewerLicenses,
  315. pdwQuantity,
  316. bLatestVersion,
  317. &LicensePack
  318. );
  319. if(status != ERROR_SUCCESS)
  320. {
  321. if(status == TLS_E_NO_LICENSE || status == TLS_E_PRODUCT_NOTINSTALL)
  322. {
  323. TLSLogLowLicenseWarning(
  324. pDbWkSpace,
  325. pRequest,
  326. (status == TLS_E_NO_LICENSE)
  327. );
  328. }
  329. goto cleanup;
  330. }
  331. ucKeyPackStatus = (LicensePack.ucKeyPackStatus & ~LSKEYPACKSTATUS_RESERVED);
  332. if( ucKeyPackStatus != LSKEYPACKSTATUS_PENDING &&
  333. ucKeyPackStatus != LSKEYPACKSTATUS_ACTIVE )
  334. {
  335. SetLastError(status = TLS_E_INTERNAL);
  336. goto cleanup;
  337. }
  338. ucAgreementType = (LicensePack.ucAgreementType & ~ LSKEYPACK_RESERVED_TYPE);
  339. if( ucAgreementType != LSKEYPACKTYPE_SELECT &&
  340. ucAgreementType != LSKEYPACKTYPE_RETAIL &&
  341. ucAgreementType != LSKEYPACKTYPE_FREE &&
  342. ucAgreementType != LSKEYPACKTYPE_OPEN )
  343. {
  344. SetLastError(status = TLS_E_INTERNAL);
  345. goto cleanup;
  346. }
  347. //
  348. // for pending activation keypack, we still
  349. // issue permanent license and rely
  350. // on revoke key pack list to invalidate licenses.
  351. //
  352. dwLicenseId=TLSDBGetNextLicenseId();
  353. //
  354. // Reset status
  355. //
  356. status = ERROR_SUCCESS;
  357. //
  358. // Formuate license serial number
  359. //
  360. ulSerialNumber.LowPart = dwLicenseId;
  361. ulSerialNumber.HighPart = LicensePack.dwKeyPackId;
  362. // Update License Table Here
  363. memset(&issuedLicense, 0, sizeof(LICENSEDCLIENT));
  364. issuedLicense.dwLicenseId = dwLicenseId;
  365. issuedLicense.dwKeyPackId = LicensePack.dwKeyPackId;
  366. issuedLicense.dwKeyPackLicenseId = LicensePack.dwNextSerialNumber;
  367. issuedLicense.dwSystemBiosChkSum = pRequest->hWid.dwPlatformID;
  368. issuedLicense.dwVideoBiosChkSum = pRequest->hWid.Data1;
  369. issuedLicense.dwFloppyBiosChkSum = pRequest->hWid.Data2;
  370. issuedLicense.dwHardDiskSize = pRequest->hWid.Data3;
  371. issuedLicense.dwRamSize = pRequest->hWid.Data4;
  372. issuedLicense.dwNumLicenses = *pdwQuantity;
  373. issuedLicense.ftIssueDate = time(NULL);
  374. _tcscpy(issuedLicense.szMachineName, pRequest->szMachineName);
  375. _tcscpy(issuedLicense.szUserName, pRequest->szUserName);
  376. if ((dwSupportFlags & SUPPORT_PER_SEAT_REISSUANCE) &&
  377. ((_tcsnicmp(LicensePack.szProductId, TERMSERV_PRODUCTID_SKU,
  378. _tcslen(TERMSERV_PRODUCTID_SKU)) == 0) ||
  379. (_tcsnicmp(LicensePack.szProductId, TERMSERV_PRODUCTID_CONCURRENT_SKU,
  380. _tcslen(TERMSERV_PRODUCTID_CONCURRENT_SKU)) == 0)) &&
  381. ((LicensePack.ucAgreementType == LSKEYPACKTYPE_SELECT) ||
  382. (LicensePack.ucAgreementType == LSKEYPACKTYPE_RETAIL) ||
  383. (LicensePack.ucAgreementType == LSKEYPACKTYPE_OPEN)))
  384. {
  385. DWORD dwRange;
  386. dwRange = GenerateRandomNumber(GetCurrentThreadId()) %
  387. g_dwReissueLeaseRange;
  388. issuedLicense.ftExpireDate = ((DWORD)time(NULL)) +
  389. g_dwReissueLeaseMinimum + dwRange;
  390. }
  391. else
  392. {
  393. issuedLicense.ftExpireDate = PERMANENT_LICENSE_EXPIRE_DATE;
  394. }
  395. issuedLicense.ucLicenseStatus =
  396. (LicensePack.ucKeyPackStatus == LSKEYPACKSTATUS_PENDING) ?
  397. LSLICENSE_STATUS_PENDING : LSLICENSE_STATUS_ACTIVE;
  398. UnixTimeToFileTime(LicensePack.dwActivateDate, &notBefore);
  399. UnixTimeToFileTime(issuedLicense.ftExpireDate, &notAfter);
  400. //
  401. // Inform Policy Module of license issued.
  402. //
  403. if(pRequest->pPolicy)
  404. {
  405. PolModGenLicense.dwKeyPackType = LicensePack.ucAgreementType;
  406. PolModGenLicense.pLicenseRequest = pRequest->pPolicyLicenseRequest;
  407. PolModGenLicense.dwKeyPackId = LicensePack.dwKeyPackId;;
  408. PolModGenLicense.dwKeyPackLicenseId = LicensePack.dwNextSerialNumber;
  409. PolModGenLicense.ClientLicenseSerialNumber = ulSerialNumber;
  410. PolModGenLicense.ftNotBefore = notBefore;
  411. PolModGenLicense.ftNotAfter = notAfter;
  412. status = pRequest->pPolicy->PMLicenseRequest(
  413. pRequest->hClient,
  414. REQUEST_GENLICENSE,
  415. (PVOID)&PolModGenLicense,
  416. (PVOID *)&pPolModCertExtension
  417. );
  418. if(status != ERROR_SUCCESS)
  419. {
  420. //
  421. // Error in policy module
  422. //
  423. goto cleanup;
  424. }
  425. }
  426. //
  427. // Check error return from policy module
  428. //
  429. if(pPolModCertExtension != NULL)
  430. {
  431. if(pPolModCertExtension->pbData != NULL &&
  432. pPolModCertExtension->cbData == 0 ||
  433. pPolModCertExtension->pbData == NULL &&
  434. pPolModCertExtension->cbData != 0 )
  435. {
  436. // assuming no extension data
  437. pPolModCertExtension->cbData = 0;
  438. pPolModCertExtension->pbData = NULL;
  439. }
  440. if(CompareFileTime( &(pPolModCertExtension->ftNotBefore),
  441. &(pPolModCertExtension->ftNotAfter)) > 0)
  442. {
  443. //
  444. // invalid data return from policy module
  445. //
  446. TLSLogEvent(
  447. EVENTLOG_ERROR_TYPE,
  448. TLS_E_GENERATECLIENTELICENSE,
  449. status = TLS_E_POLICYMODULEERROR,
  450. pRequest->pPolicy->GetCompanyName(),
  451. pRequest->pPolicy->GetProductId()
  452. );
  453. goto cleanup;
  454. }
  455. if( FileTimeToLicenseDate(&(pPolModCertExtension->ftNotBefore), &issuedLicense.ftIssueDate) == FALSE ||
  456. FileTimeToLicenseDate(&(pPolModCertExtension->ftNotAfter), &issuedLicense.ftExpireDate) == FALSE )
  457. {
  458. //
  459. // Invalid data return from policy module
  460. //
  461. TLSLogEvent(
  462. EVENTLOG_ERROR_TYPE,
  463. TLS_E_GENERATECLIENTELICENSE,
  464. status = TLS_E_POLICYMODULEERROR,
  465. pRequest->pPolicy->GetCompanyName(),
  466. pRequest->pPolicy->GetProductId()
  467. );
  468. goto cleanup;
  469. }
  470. notBefore = pPolModCertExtension->ftNotBefore;
  471. notAfter = pPolModCertExtension->ftNotAfter;
  472. }
  473. //
  474. // Add license into license table
  475. //
  476. status=TLSDBLicenseAdd(
  477. pDbWkSpace,
  478. &issuedLicense,
  479. 0,
  480. NULL
  481. );
  482. if(status != ERROR_SUCCESS)
  483. {
  484. goto cleanup;
  485. }
  486. //
  487. // Return licensed product
  488. //
  489. pLicensedProduct->pSubjectPublicKeyInfo = NULL;
  490. pLicensedProduct->dwQuantity = *pdwQuantity;
  491. pLicensedProduct->ulSerialNumber = ulSerialNumber;
  492. pLicensedProduct->dwKeyPackId = LicensePack.dwKeyPackId;
  493. pLicensedProduct->dwLicenseId = dwLicenseId;
  494. pLicensedProduct->dwKeyPackLicenseId = LicensePack.dwNextSerialNumber;
  495. pLicensedProduct->dwNumLicenseLeft = LicensePack.dwNumberOfLicenses;
  496. pLicensedProduct->ClientHwid = pRequest->hWid;
  497. pLicensedProduct->bTemp = FALSE;
  498. pLicensedProduct->NotBefore = notBefore;
  499. pLicensedProduct->NotAfter = notAfter;
  500. pLicensedProduct->dwProductVersion = MAKELONG(LicensePack.wMinorVersion, LicensePack.wMajorVersion);
  501. _tcscpy(pLicensedProduct->szUserName, pRequest->szUserName);
  502. _tcscpy(pLicensedProduct->szMachineName, pRequest->szMachineName);
  503. _tcscpy(pLicensedProduct->szCompanyName, LicensePack.szCompanyName);
  504. _tcscpy(pLicensedProduct->szLicensedProductId, LicensePack.szProductId);
  505. _tcscpy(pLicensedProduct->szRequestProductId, pRequest->pClientLicenseRequest->pszProductId);
  506. pLicensedProduct->dwLanguageID = pRequest->dwLanguageID;
  507. pLicensedProduct->dwPlatformID = pRequest->dwPlatformID;
  508. pLicensedProduct->pbPolicyData = (pPolModCertExtension) ? pPolModCertExtension->pbData : NULL;
  509. pLicensedProduct->cbPolicyData = (pPolModCertExtension) ? pPolModCertExtension->cbData : 0;
  510. cleanup:
  511. return status;
  512. }
  513. DWORD
  514. TLSDBReissuePermanentLicense(
  515. IN PTLSDbWorkSpace pDbWkSpace,
  516. IN PLICENSEDPRODUCT pExpiredLicense,
  517. IN OUT PTLSDBLICENSEDPRODUCT pReissuedLicense
  518. )
  519. /*++
  520. Abstract:
  521. Searches for the expired license in the database and, if found, resets
  522. the expiration and returns the modified license.
  523. Parameters:
  524. Returns:
  525. --*/
  526. {
  527. TLSDBLICENSEDPRODUCT LicensedProduct;
  528. LicensedProductToDbLicensedProduct(pExpiredLicense,&LicensedProduct);
  529. return TLSDBReissueFoundPermanentLicense(pDbWkSpace,
  530. &LicensedProduct,
  531. pReissuedLicense);
  532. }
  533. DWORD
  534. TLSDBReissueFoundPermanentLicense(
  535. IN PTLSDbWorkSpace pDbWkSpace,
  536. IN PTLSDBLICENSEDPRODUCT pExpiredLicense,
  537. IN OUT PTLSDBLICENSEDPRODUCT pReissuedLicense
  538. )
  539. /*++
  540. Abstract:
  541. Searches for the expired license in the database and, if found, resets
  542. the expiration and returns the modified license.
  543. Parameters:
  544. Returns:
  545. --*/
  546. {
  547. DWORD dwStatus;
  548. LICENSEDCLIENT License;
  549. ASSERT(pDbWkSpace != NULL);
  550. ASSERT(pExpiredLicense != NULL);
  551. ASSERT(pReissuedLicense != NULL);
  552. dwStatus = TLSFindDbLicensedProduct(pExpiredLicense, &License);
  553. if (dwStatus == ERROR_SUCCESS)
  554. {
  555. DWORD dwRange;
  556. dwRange = GenerateRandomNumber(GetCurrentThreadId()) %
  557. g_dwReissueLeaseRange;
  558. License.ftExpireDate = ((DWORD)time(NULL)) +
  559. g_dwReissueLeaseMinimum + dwRange;
  560. TLSDBLockLicenseTable();
  561. try
  562. {
  563. dwStatus = TLSDBLicenseUpdateEntry(
  564. USEHANDLE(pDbWkSpace),
  565. LSLICENSE_SEARCH_EXPIREDATE,
  566. &License,
  567. FALSE
  568. );
  569. }
  570. catch(...)
  571. {
  572. dwStatus = TLS_E_INTERNAL;
  573. }
  574. TLSDBUnlockLicenseTable();
  575. }
  576. if (dwStatus == ERROR_SUCCESS)
  577. {
  578. CopyDbLicensedProduct(pExpiredLicense, pReissuedLicense);
  579. UnixTimeToFileTime(License.ftExpireDate, &(pReissuedLicense->NotAfter));
  580. pReissuedLicense->pSubjectPublicKeyInfo = NULL;
  581. }
  582. return(dwStatus);
  583. }
  584. //+------------------------------------------------------------------------
  585. DWORD
  586. TLSDBGetPermanentLicense(
  587. IN PTLSDbWorkSpace pDbWkSpace,
  588. IN PTLSDBLICENSEREQUEST pRequest,
  589. IN BOOL bAcceptFewerLicenses,
  590. IN OUT DWORD *pdwQuantity,
  591. IN BOOL bLatestVersion,
  592. IN OUT PTLSLICENSEPACK pLicensePack
  593. )
  594. /*++
  595. Abstract:
  596. Allocate a permanent license from database.
  597. Parameters:
  598. pDbWkSpace : workspace handle.
  599. pRequest : product to be request.
  600. bAcceptFewerLicenses - TRUE if succeeding with fewer licenses than
  601. requested is acceptable
  602. pdwQuantity - on input, number of licenses to allocate. on output,
  603. number of licenses actually allocated
  604. bLatestversion : latest version (unused).
  605. pLicensePack : license pack where license is allocated.
  606. Returns:
  607. ++*/
  608. {
  609. DWORD dwStatus = ERROR_SUCCESS;
  610. TLSDBLicenseAllocation allocated;
  611. TLSDBAllocateRequest AllocateRequest;
  612. TLSLICENSEPACK LicenseKeyPack;
  613. DWORD dwTotalAllocated = 0;
  614. DWORD dwSearchedType = 0;
  615. DWORD dwSuggestType;
  616. DWORD dwPMAdjustedType = LSKEYPACKTYPE_UNKNOWN;
  617. DWORD dwLocalType = LSKEYPACKTYPE_UNKNOWN;
  618. POLICY_TS_MACHINE groupPolicy;
  619. RegGetMachinePolicy(&groupPolicy);
  620. #define NUM_KEYPACKS 5
  621. DWORD dwAllocation[NUM_KEYPACKS];
  622. TLSLICENSEPACK keypack[NUM_KEYPACKS];
  623. for (int i=0; i < NUM_KEYPACKS; i++)
  624. {
  625. keypack[i].pbDomainSid = NULL;
  626. }
  627. AllocateRequest.szCompanyName = (LPTSTR)pRequest->pszCompanyName;
  628. AllocateRequest.szProductId = (LPTSTR)pRequest->pszProductId;
  629. AllocateRequest.dwVersion = pRequest->dwProductVersion;
  630. AllocateRequest.dwPlatformId = pRequest->dwPlatformID;
  631. AllocateRequest.dwLangId = pRequest->dwLanguageID;
  632. AllocateRequest.dwNumLicenses = *pdwQuantity;
  633. if( groupPolicy.fPolicyPreventLicenseUpgrade == 1 && groupPolicy.fPreventLicenseUpgrade == 1)
  634. {
  635. AllocateRequest.dwScheme = ALLOCATE_EXACT_VERSION;
  636. }
  637. else
  638. {
  639. AllocateRequest.dwScheme = ALLOCATE_ANY_GREATER_VERSION;
  640. }
  641. memset(&allocated, 0, sizeof(allocated));
  642. do {
  643. allocated.dwBufSize = NUM_KEYPACKS;
  644. allocated.pdwAllocationVector = dwAllocation;
  645. allocated.lpAllocateKeyPack = keypack;
  646. dwSuggestType = dwLocalType;
  647. dwStatus = pRequest->pPolicy->PMLicenseRequest(
  648. pRequest->hClient,
  649. REQUEST_KEYPACKTYPE,
  650. UlongToPtr(dwSuggestType),
  651. (PVOID *)&dwPMAdjustedType
  652. );
  653. if(dwStatus != ERROR_SUCCESS)
  654. break;
  655. dwLocalType = (dwPMAdjustedType & ~LSKEYPACK_RESERVED_TYPE);
  656. if(dwLocalType > LSKEYPACKTYPE_LAST)
  657. {
  658. TLSLogEvent(
  659. EVENTLOG_ERROR_TYPE,
  660. TLS_E_GENERATECLIENTELICENSE,
  661. dwStatus = TLS_E_POLICYMODULEERROR,
  662. pRequest->pPolicy->GetCompanyName(),
  663. pRequest->pPolicy->GetProductId()
  664. );
  665. break;
  666. }
  667. if(dwSearchedType & (0x1 << dwLocalType))
  668. {
  669. //
  670. // we already went thru this license pack, policy module error
  671. //
  672. TLSLogEvent(
  673. EVENTLOG_ERROR_TYPE,
  674. TLS_E_GENERATECLIENTELICENSE,
  675. dwStatus = TLS_E_POLICYMODULERECURSIVE,
  676. pRequest->pPolicy->GetCompanyName(),
  677. pRequest->pPolicy->GetProductId()
  678. );
  679. break;
  680. }
  681. dwSearchedType |= (0x1 << dwLocalType);
  682. AllocateRequest.ucAgreementType = dwPMAdjustedType;
  683. dwStatus = AllocateLicensesFromDB(
  684. pDbWkSpace,
  685. &AllocateRequest,
  686. TRUE, // fCheckAgreementType
  687. &allocated
  688. );
  689. if(dwStatus == ERROR_SUCCESS)
  690. {
  691. //
  692. // successfully allocate a license
  693. //
  694. dwTotalAllocated += allocated.dwTotalAllocated;
  695. if (dwTotalAllocated >= *pdwQuantity)
  696. {
  697. break;
  698. }
  699. else
  700. {
  701. AllocateRequest.dwNumLicenses -= allocated.dwTotalAllocated;
  702. continue;
  703. }
  704. }
  705. if(dwStatus != TLS_I_NO_MORE_DATA && dwStatus != TLS_E_PRODUCT_NOTINSTALL)
  706. {
  707. //
  708. // error occurred in AllocateLicenseFromDB()
  709. //
  710. break;
  711. }
  712. } while(dwLocalType != LSKEYPACKTYPE_UNKNOWN);
  713. if ((dwTotalAllocated == 0)
  714. || (!bAcceptFewerLicenses &&
  715. ((dwTotalAllocated < *pdwQuantity))))
  716. {
  717. // Failing to commit will return all licenses allocated so far
  718. SetLastError(dwStatus = TLS_E_NO_LICENSE);
  719. }
  720. else if ((dwTotalAllocated != 0) && bAcceptFewerLicenses)
  721. {
  722. dwStatus = ERROR_SUCCESS;
  723. }
  724. if(dwStatus == ERROR_SUCCESS)
  725. {
  726. //
  727. // LicenseKeyPack return via TLSDBLicenseAllocation structure
  728. //
  729. *pLicensePack = keypack[0];
  730. *pdwQuantity = dwTotalAllocated;
  731. }
  732. return dwStatus;
  733. }