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.

555 lines
14 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 2000-2000
  5. //
  6. // File: expperm.cpp
  7. //
  8. // Contents:
  9. //
  10. // History:
  11. //
  12. // Note:
  13. //---------------------------------------------------------------------------
  14. #include "pch.cpp"
  15. #include <tchar.h>
  16. #include <process.h>
  17. #include "lscommon.h"
  18. #include "debug.h"
  19. #include "globals.h"
  20. #include "db.h"
  21. #include "keypack.h"
  22. #include "clilic.h"
  23. #include "server.h"
  24. #define EXPIRE_THREAD_INITIAL_SLEEP (1000*60) /* 1 minute */
  25. #define EXPIRATION_DAYS 30
  26. #define DELETE_EXPIRED_TEMPORARY_IN_DAYS L"EffectiveDaysToDeleteTemporary"
  27. /*++
  28. Function:
  29. CalculateEffectiveTemporaryExpiration
  30. Description:
  31. Calculate the license expiration.
  32. Argument:
  33. pExpiration - The expiration date and time of the license.
  34. Return:
  35. TRUE if the expiration is calculated successfully or FALSE otherwise.
  36. --*/
  37. BOOL
  38. CalculateEffectiveTemporaryExpiration(
  39. PDWORD pdwExpiration )
  40. {
  41. DWORD dwDays = EXPIRATION_DAYS;
  42. DWORD dwStatus = ERROR_SUCCESS;
  43. HKEY hKey = NULL;
  44. time_t
  45. now = time( NULL );
  46. if( NULL == pdwExpiration )
  47. {
  48. return( FALSE );
  49. }
  50. //-------------------------------------------------------------------
  51. //
  52. // Open HKLM\system\currentcontrolset\sevices\termservlicensing\parameters
  53. //
  54. //-------------------------------------------------------------------
  55. dwStatus =RegCreateKeyEx(
  56. HKEY_LOCAL_MACHINE,
  57. LSERVER_REGISTRY_BASE _TEXT(SZSERVICENAME) _TEXT("\\") LSERVER_PARAMETERS,
  58. 0,
  59. NULL,
  60. REG_OPTION_NON_VOLATILE,
  61. KEY_READ,
  62. NULL,
  63. &hKey,
  64. NULL
  65. );
  66. if(dwStatus == ERROR_SUCCESS)
  67. {
  68. DWORD dwBuffer;
  69. DWORD cbBuffer = sizeof(DWORD);
  70. dwStatus = RegQueryValueEx(
  71. hKey,
  72. DELETE_EXPIRED_TEMPORARY_IN_DAYS,
  73. NULL,
  74. NULL,
  75. (LPBYTE)&dwBuffer,
  76. &cbBuffer
  77. );
  78. RegCloseKey(hKey);
  79. if(dwStatus == ERROR_SUCCESS)
  80. {
  81. dwDays = (dwBuffer <7) ? 30: (dwBuffer);
  82. }
  83. }
  84. DWORD dwTemp = (dwDays * 24 *60 *60);
  85. DWORD dwNow = (DWORD)now;
  86. if(dwNow > dwTemp)
  87. dwNow -= dwTemp;
  88. else
  89. dwNow -= (EXPIRATION_DAYS * 24 *60 *60);
  90. *pdwExpiration = dwNow;
  91. return( TRUE );
  92. }
  93. unsigned int WINAPI
  94. DeleteExpiredTemporaryLicenses()
  95. {
  96. DWORD dwStatus=ERROR_SUCCESS;
  97. LICENSEDCLIENT search_license;
  98. DWORD dwTempLicenseExpiration;
  99. memset(&search_license,0,sizeof(search_license));
  100. DBGPrintf(
  101. DBG_INFORMATION,
  102. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  103. DBG_ALL_LEVEL,
  104. _TEXT("ExpireTemporary : ready...\n")
  105. );
  106. PTLSDbWorkSpace pDbWkSpace = NULL;
  107. LICENSEDCLIENT found_license;
  108. TLSLICENSEPACK search_keypack;
  109. TLSLICENSEPACK found_keypack;
  110. if( !CalculateEffectiveTemporaryExpiration(&dwTempLicenseExpiration))
  111. return TLS_E_INTERNAL;
  112. search_license.ftExpireDate = dwTempLicenseExpiration;
  113. memset(&found_license,0,sizeof(found_license));
  114. memset(&search_keypack,0,sizeof(search_keypack));
  115. memset(&found_keypack,0,sizeof(found_keypack));
  116. if (!(ALLOCATEDBHANDLE(pDbWkSpace, g_EnumDbTimeout)))
  117. {
  118. dwStatus = TLS_E_ALLOCATE_HANDLE;
  119. return dwStatus;
  120. }
  121. TLSDBLockKeyPackTable();
  122. TLSDBLockLicenseTable();
  123. CLEANUPSTMT;
  124. dwStatus = TLSDBLicenseEnumBeginEx(
  125. USEHANDLE(pDbWkSpace),
  126. TRUE,
  127. LSLICENSE_SEARCH_EXPIREDATE,
  128. &search_license,
  129. JET_bitSeekLE
  130. );
  131. if (ERROR_SUCCESS != dwStatus)
  132. {
  133. TLSDBUnlockLicenseTable();
  134. TLSDBUnlockKeyPackTable();
  135. FREEDBHANDLE(pDbWkSpace);
  136. return TLS_E_INTERNAL;
  137. }
  138. while (1)
  139. {
  140. dwStatus = TLSDBLicenseEnumNextEx(
  141. USEHANDLE(pDbWkSpace),
  142. TRUE, // bReverse
  143. TRUE, // bAnyRecord
  144. &found_license
  145. );
  146. if(dwStatus != ERROR_SUCCESS)
  147. {
  148. goto next_time;
  149. }
  150. //
  151. // See if this is the right product type
  152. //
  153. search_keypack.dwKeyPackId = found_license.dwKeyPackId;
  154. dwStatus = TLSDBKeyPackFind(
  155. USEHANDLE(pDbWkSpace),
  156. TRUE,
  157. LSKEYPACK_EXSEARCH_DWINTERNAL,
  158. &search_keypack,
  159. &found_keypack
  160. );
  161. if(dwStatus != ERROR_SUCCESS)
  162. {
  163. continue;
  164. }
  165. //
  166. // Only check per-seat temporary
  167. //
  168. if (found_keypack.ucAgreementType != LSKEYPACKTYPE_TEMPORARY)
  169. {
  170. continue;
  171. }
  172. BEGIN_TRANSACTION(pDbWorkSpace);
  173. // Delete currently enumerated license.
  174. dwStatus = TLSDBDeleteEnumeratedLicense(USEHANDLE(pDbWkSpace));
  175. if (dwStatus == ERROR_SUCCESS)
  176. {
  177. dwStatus = TLSDBReturnLicenseToKeyPack(
  178. USEHANDLE(pDbWkSpace),
  179. found_license.dwKeyPackId,
  180. found_license.dwNumLicenses
  181. );
  182. }
  183. if(dwStatus == ERROR_SUCCESS)
  184. {
  185. COMMIT_TRANSACTION(pDbWkSpace);
  186. }
  187. else
  188. {
  189. ROLLBACK_TRANSACTION(pDbWkSpace);
  190. }
  191. }
  192. next_time:
  193. TLSDBLicenseEnumEnd(USEHANDLE(pDbWkSpace));
  194. TLSDBUnlockLicenseTable();
  195. TLSDBUnlockKeyPackTable();
  196. FREEDBHANDLE(pDbWkSpace);
  197. return dwStatus;
  198. }
  199. //---------------------------------------------------------------------
  200. unsigned int WINAPI
  201. ExpirePermanentThread(void* ptr)
  202. {
  203. HANDLE hEvent=(HANDLE) ptr;
  204. DWORD dwStatus=ERROR_SUCCESS;
  205. LICENSEDCLIENT search_license;
  206. memset(&search_license,0,sizeof(search_license));
  207. //
  208. // Signal initializer thread we are ready
  209. //
  210. SetEvent(hEvent);
  211. DBGPrintf(
  212. DBG_INFORMATION,
  213. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  214. DBG_ALL_LEVEL,
  215. _TEXT("ExpirePermanent : ready...\n")
  216. );
  217. //
  218. // Give service chance to initialize
  219. //
  220. Sleep(EXPIRE_THREAD_INITIAL_SLEEP);
  221. //
  222. // Forever loop
  223. //
  224. while(1)
  225. {
  226. DeleteExpiredTemporaryLicenses();
  227. PTLSDbWorkSpace pDbWkSpace = NULL;
  228. LICENSEDCLIENT found_license;
  229. TLSLICENSEPACK search_keypack;
  230. TLSLICENSEPACK found_keypack;
  231. search_license.ftExpireDate = time(NULL);
  232. memset(&found_license,0,sizeof(found_license));
  233. memset(&search_keypack,0,sizeof(search_keypack));
  234. memset(&found_keypack,0,sizeof(found_keypack));
  235. if (!(ALLOCATEDBHANDLE(pDbWkSpace, g_EnumDbTimeout)))
  236. {
  237. goto do_sleep;
  238. }
  239. TLSDBLockKeyPackTable();
  240. TLSDBLockLicenseTable();
  241. CLEANUPSTMT;
  242. dwStatus = TLSDBLicenseEnumBeginEx(
  243. USEHANDLE(pDbWkSpace),
  244. TRUE,
  245. LSLICENSE_SEARCH_EXPIREDATE,
  246. &search_license,
  247. JET_bitSeekLE
  248. );
  249. if (ERROR_SUCCESS != dwStatus)
  250. {
  251. TLSDBUnlockLicenseTable();
  252. TLSDBUnlockKeyPackTable();
  253. FREEDBHANDLE(pDbWkSpace);
  254. goto do_sleep;
  255. }
  256. while (1)
  257. {
  258. dwStatus = TLSDBLicenseEnumNextEx(
  259. USEHANDLE(pDbWkSpace),
  260. TRUE, // bReverse
  261. TRUE, // bAnyRecord
  262. &found_license
  263. );
  264. if(dwStatus != ERROR_SUCCESS)
  265. {
  266. goto next_time;
  267. }
  268. //
  269. // See if this is the right product type
  270. //
  271. search_keypack.dwKeyPackId = found_license.dwKeyPackId;
  272. dwStatus = TLSDBKeyPackFind(
  273. USEHANDLE(pDbWkSpace),
  274. TRUE,
  275. LSKEYPACK_EXSEARCH_DWINTERNAL,
  276. &search_keypack,
  277. &found_keypack
  278. );
  279. if(dwStatus != ERROR_SUCCESS)
  280. {
  281. continue;
  282. }
  283. //
  284. // only check licenses that we reissue
  285. //
  286. if(found_keypack.ucAgreementType != LSKEYPACKTYPE_RETAIL &&
  287. found_keypack.ucAgreementType != LSKEYPACKTYPE_SELECT &&
  288. found_keypack.ucAgreementType != LSKEYPACKTYPE_FREE &&
  289. found_keypack.ucAgreementType != LSKEYPACKTYPE_OPEN )
  290. {
  291. continue;
  292. }
  293. UCHAR ucKeyPackStatus = found_keypack.ucKeyPackStatus &
  294. ~LSKEYPACKSTATUS_RESERVED;
  295. //
  296. // Don't check pending activation key pack
  297. //
  298. if(ucKeyPackStatus != LSKEYPACKSTATUS_ACTIVE)
  299. {
  300. continue;
  301. }
  302. //
  303. // Only check per-seat and concurrent
  304. //
  305. if ((_tcsnicmp(found_keypack.szProductId,
  306. TERMSERV_PRODUCTID_SKU,
  307. _tcslen(TERMSERV_PRODUCTID_SKU)) != 0)
  308. && (_tcsnicmp(found_keypack.szProductId,
  309. TERMSERV_PRODUCTID_CONCURRENT_SKU,
  310. _tcslen(TERMSERV_PRODUCTID_CONCURRENT_SKU)) != 0))
  311. {
  312. continue;
  313. }
  314. BEGIN_TRANSACTION(pDbWorkSpace);
  315. //
  316. // Return currently enumerated license.
  317. //
  318. dwStatus = TLSDBDeleteEnumeratedLicense(USEHANDLE(pDbWkSpace));
  319. if (dwStatus == ERROR_SUCCESS)
  320. {
  321. //
  322. // Adjust available license number.
  323. //
  324. dwStatus = TLSDBReturnLicenseToKeyPack(
  325. USEHANDLE(pDbWkSpace),
  326. found_license.dwKeyPackId,
  327. found_license.dwNumLicenses
  328. );
  329. }
  330. if (dwStatus == ERROR_SUCCESS)
  331. {
  332. COMMIT_TRANSACTION(pDbWkSpace);
  333. InterlockedIncrement(&g_lPermanentLicensesReturned);
  334. }
  335. else
  336. {
  337. ROLLBACK_TRANSACTION(pDbWkSpace);
  338. }
  339. }
  340. next_time:
  341. TLSDBLicenseEnumEnd(USEHANDLE(pDbWkSpace));
  342. TLSDBUnlockLicenseTable();
  343. TLSDBUnlockKeyPackTable();
  344. FREEDBHANDLE(pDbWkSpace);
  345. do_sleep:
  346. if (WAIT_OBJECT_0 == WaitForSingleObject(GetServiceShutdownHandle(),g_dwReissueExpireThreadSleep))
  347. {
  348. break;
  349. }
  350. DBGPrintf(
  351. DBG_INFORMATION,
  352. DBG_FACILITY_RPC,
  353. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  354. _TEXT("ExpirePermanent : woke up\n")
  355. );
  356. }
  357. //
  358. // Initializer function will close the event handle
  359. //
  360. return dwStatus;
  361. }
  362. //---------------------------------------------------------------------
  363. DWORD
  364. InitExpirePermanentThread()
  365. /*++
  366. ++*/
  367. {
  368. HANDLE hThread = NULL;
  369. unsigned int dwThreadId;
  370. HANDLE hEvent = NULL;
  371. DWORD dwStatus = ERROR_SUCCESS;
  372. HANDLE waithandles[2];
  373. //
  374. // Create a event for namedpipe thread to signal it is ready.
  375. //
  376. hEvent = CreateEvent(
  377. NULL,
  378. FALSE,
  379. FALSE, // non-signal
  380. NULL
  381. );
  382. if(hEvent == NULL)
  383. {
  384. dwStatus = GetLastError();
  385. goto cleanup;
  386. }
  387. hThread = (HANDLE)_beginthreadex(
  388. NULL,
  389. 0,
  390. ExpirePermanentThread,
  391. hEvent,
  392. 0,
  393. &dwThreadId
  394. );
  395. if(hThread == NULL)
  396. {
  397. dwStatus = GetLastError();
  398. goto cleanup;
  399. }
  400. waithandles[0] = hEvent;
  401. waithandles[1] = hThread;
  402. //
  403. // Wait 30 second for thread to complete initialization
  404. //
  405. dwStatus = WaitForMultipleObjects(
  406. sizeof(waithandles)/sizeof(waithandles[0]),
  407. waithandles,
  408. FALSE,
  409. 30*1000
  410. );
  411. if(dwStatus == WAIT_OBJECT_0)
  412. {
  413. //
  414. // thread is ready
  415. //
  416. dwStatus = ERROR_SUCCESS;
  417. }
  418. else
  419. {
  420. if(dwStatus == (WAIT_OBJECT_0 + 1))
  421. {
  422. //
  423. // Thread terminate abnormally
  424. //
  425. GetExitCodeThread(
  426. hThread,
  427. &dwStatus
  428. );
  429. }
  430. else
  431. {
  432. dwStatus = TLS_E_SERVICE_STARTUP_CREATE_THREAD;
  433. }
  434. }
  435. cleanup:
  436. if(hEvent != NULL)
  437. {
  438. CloseHandle(hEvent);
  439. }
  440. if(hThread != NULL)
  441. {
  442. CloseHandle(hThread);
  443. }
  444. return dwStatus;
  445. }