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.

439 lines
12 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999
  5. //
  6. // File: lsreport.cpp
  7. //
  8. // Contents: LSReport engine - complete back end
  9. //
  10. // History: 06-10-99 t-BStern Created
  11. //
  12. //---------------------------------------------------------------------------
  13. #include "lsreport.h"
  14. #include "lsrepdef.h"
  15. #include <time.h>
  16. #include <oleauto.h>
  17. TCHAR noExpire[NOEXPIRE_LENGTH] = { 0 };
  18. TCHAR header[HEADER_LENGTH] = { 0 };
  19. TCHAR szTemp[TYPESTR_LENGTH] = { 0 };
  20. TCHAR szActive[TYPESTR_LENGTH] = { 0 };
  21. TCHAR szUpgrade[TYPESTR_LENGTH] = { 0 };
  22. TCHAR szRevoked[TYPESTR_LENGTH] = { 0 };
  23. TCHAR szPending[TYPESTR_LENGTH] = { 0 };
  24. TCHAR szConcur[TYPESTR_LENGTH] = { 0 };
  25. TCHAR szUnknown[TYPESTR_LENGTH] = { 0 };
  26. // Returns TRUE on success.
  27. BOOL
  28. InitLSReportStrings(VOID)
  29. {
  30. return (
  31. LoadString(NULL, IDS_HEADER_TEXT, header, HEADER_LENGTH) &&
  32. LoadString(NULL, IDS_NO_EXPIRE, noExpire, NOEXPIRE_LENGTH) &&
  33. LoadString(NULL, IDS_TEMPORARY_LICENSE, szTemp, TYPESTR_LENGTH) &&
  34. LoadString(NULL, IDS_ACTIVE_LICENSE, szActive, TYPESTR_LENGTH) &&
  35. LoadString(NULL, IDS_UPGRADED_LICENSE, szUpgrade, TYPESTR_LENGTH) &&
  36. LoadString(NULL, IDS_REVOKED_LICENSE, szRevoked, TYPESTR_LENGTH) &&
  37. LoadString(NULL, IDS_PENDING_LICENSE, szPending, TYPESTR_LENGTH) &&
  38. LoadString(NULL, IDS_CONCURRENT_LICENSE, szConcur, TYPESTR_LENGTH) &&
  39. LoadString(NULL, IDS_UNKNOWN_LICENSE, szUnknown, TYPESTR_LENGTH)
  40. );
  41. }
  42. // Given a keypack and a machine to connect to, read every license in that kp.
  43. // Is not called directly.
  44. DWORD
  45. LicenseLoop(
  46. IN FILE *OutFile,
  47. IN LPWSTR szName, // who owns this keypack?
  48. IN DWORD kpID, // which keypack
  49. IN LPCTSTR szProductDesc,
  50. IN BOOL bTempOnly,
  51. IN const PSYSTEMTIME stStart,
  52. IN const PSYSTEMTIME stEnd,
  53. IN BOOL fUseLimits) // are the above 2 parms valid
  54. {
  55. TLS_HANDLE subHand;
  56. DWORD dwStatus;
  57. DWORD dwErrCode = ERROR_SUCCESS;
  58. WCHAR msg[TLS_ERROR_LENGTH];
  59. LSLicense lsl;
  60. subHand = TLSConnectToLsServer(szName);
  61. if (subHand == NULL)
  62. {
  63. // The machine suddenly went away.
  64. ShowError(GetLastError(), NULL, TRUE);
  65. dwErrCode = ERROR_BAD_CONNECT;
  66. }
  67. else
  68. {
  69. lsl.dwKeyPackId = kpID;
  70. dwStatus = TLSLicenseEnumBegin(
  71. subHand,
  72. LSLICENSE_SEARCH_KEYPACKID,
  73. TRUE,
  74. &lsl,
  75. &dwErrCode);
  76. if (dwErrCode != ERROR_SUCCESS)
  77. {
  78. TLSGetLastError(subHand, TLS_ERROR_LENGTH, msg, &dwStatus);
  79. _fputts(msg, stderr);
  80. return dwErrCode;
  81. }
  82. else if (dwStatus)
  83. {
  84. return dwStatus;
  85. }
  86. do {
  87. dwStatus = TLSLicenseEnumNext(subHand, &lsl, &dwErrCode);
  88. if ((dwStatus == RPC_S_OK) && (dwErrCode == ERROR_SUCCESS)) {
  89. if ((lsl.ucLicenseStatus == LSLICENSE_STATUS_TEMPORARY) ||
  90. !bTempOnly) { // Does it fit the temp. requirements?
  91. // We want to print if at any of the following are true:
  92. // a) There are no limits
  93. // b) Issued between stStart and stEnd
  94. // c) Expired between stStart and stEnd
  95. // d) issued before stStart and expired after stEnd
  96. if (!fUseLimits // case a
  97. || ((CompDate(lsl.ftIssueDate, stStart) >= 0) &&
  98. (CompDate(lsl.ftIssueDate, stEnd) <= 0)) // case b
  99. || ((CompDate(lsl.ftExpireDate, stStart) >= 0) &&
  100. (CompDate(lsl.ftExpireDate, stEnd) <= 0)) // case c
  101. || ((CompDate(lsl.ftIssueDate, stStart) <= 0) &&
  102. (CompDate(lsl.ftExpireDate, stEnd) >= 0))) // case d
  103. {
  104. PrintLicense(szName, // print it.
  105. &lsl,
  106. szProductDesc,
  107. OutFile);
  108. } // end check cases
  109. } // end check for temp license
  110. } // end good getnext
  111. } while ((dwStatus == RPC_S_OK) && (dwErrCode == ERROR_SUCCESS));
  112. if (dwStatus != RPC_S_OK)
  113. {
  114. return ShowError(dwStatus, NULL, TRUE);
  115. }
  116. if (dwErrCode != LSERVER_I_NO_MORE_DATA)
  117. {
  118. TLSGetLastError(subHand, TLS_ERROR_LENGTH, msg, &dwStatus);
  119. _fputts(msg, stderr);
  120. }
  121. TLSLicenseEnumEnd(subHand, &dwErrCode);
  122. if (dwErrCode != ERROR_SUCCESS)
  123. {
  124. TLSGetLastError(subHand, TLS_ERROR_LENGTH, msg, &dwStatus);
  125. _fputts(msg, stderr);
  126. }
  127. TLSDisconnectFromServer(subHand);
  128. }
  129. return dwErrCode;
  130. }
  131. // Given a machine to connect to, iterate through the keypacks.
  132. // Is not called directly.
  133. DWORD
  134. KeyPackLoop(
  135. IN FILE *OutFile,
  136. IN LPWSTR szName, // machine to connect to
  137. IN BOOL bTempOnly,
  138. IN const PSYSTEMTIME stStart,
  139. IN const PSYSTEMTIME stEnd,
  140. IN BOOL fUseLimits) // do we care about the previous 2 parms?
  141. {
  142. TLS_HANDLE hand;
  143. DWORD dwStatus, dwErrCode;
  144. LSKeyPack lskpKeyPack;
  145. TCHAR msg[TLS_ERROR_LENGTH];
  146. hand = TLSConnectToLsServer(szName);
  147. if (hand == NULL)
  148. {
  149. return GetLastError();
  150. }
  151. lskpKeyPack.dwLanguageId = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
  152. dwStatus = TLSKeyPackEnumBegin(hand,
  153. LSKEYPACK_SEARCH_ALL,
  154. FALSE,
  155. &lskpKeyPack,
  156. &dwErrCode);
  157. if (dwErrCode != ERROR_SUCCESS)
  158. {
  159. return dwErrCode;
  160. }
  161. if (dwStatus != RPC_S_OK)
  162. {
  163. return dwStatus;
  164. }
  165. do {
  166. dwStatus = TLSKeyPackEnumNext(hand, &lskpKeyPack, &dwErrCode);
  167. if ((dwStatus == RPC_S_OK) && (dwErrCode == ERROR_SUCCESS))
  168. {
  169. LicenseLoop(OutFile,
  170. szName,
  171. lskpKeyPack.dwKeyPackId,
  172. lskpKeyPack.szProductDesc,
  173. bTempOnly,
  174. stStart,
  175. stEnd,
  176. fUseLimits);
  177. }
  178. } while ((dwStatus == RPC_S_OK) && (dwErrCode == ERROR_SUCCESS));
  179. if (dwStatus != RPC_S_OK)
  180. {
  181. return ShowError(dwStatus, NULL, TRUE);
  182. }
  183. if (dwErrCode != LSERVER_I_NO_MORE_DATA)
  184. {
  185. TLSGetLastError(hand, TLS_ERROR_LENGTH, msg, &dwStatus);
  186. _fputts(msg, stderr);
  187. }
  188. TLSKeyPackEnumEnd(hand, &dwErrCode);
  189. if (dwErrCode != ERROR_SUCCESS)
  190. {
  191. TLSGetLastError(hand, TLS_ERROR_LENGTH, msg, &dwStatus);
  192. _fputts(msg, stderr);
  193. }
  194. TLSDisconnectFromServer(hand);
  195. return dwErrCode;
  196. }
  197. // If bTempOnly is FALSE, all licenses will be dumped to the file. Otherwise,
  198. // only Temporary licenses will be written. This is the one function to call
  199. // to do all of the program's magic.
  200. DWORD
  201. ExportLicenses(
  202. IN FILE *OutFile, // must be opened for writing first
  203. IN PServerHolder pshServers,
  204. IN BOOL fTempOnly,
  205. IN const PSYSTEMTIME stStart,
  206. IN const PSYSTEMTIME stEnd,
  207. IN BOOL fUseLimits) // are the above 2 parms valid?
  208. {
  209. DWORD i;
  210. DWORD dwStatus;
  211. DWORD dwRetVal = ERROR_SUCCESS;
  212. _fputts(header, OutFile);
  213. for (i = 0; i < pshServers->dwCount; i++) {
  214. dwStatus = KeyPackLoop(OutFile,
  215. pshServers->pszNames[i],
  216. fTempOnly,
  217. stStart,
  218. stEnd,
  219. fUseLimits);
  220. if (dwStatus != ERROR_SUCCESS)
  221. {
  222. INT_PTR arg;
  223. dwRetVal = dwStatus;
  224. arg = (INT_PTR)pshServers->pszNames[i];
  225. ShowError(IDS_BAD_LOOP, &arg, FALSE);
  226. ShowError(dwStatus, NULL, TRUE);
  227. }
  228. }
  229. if (dwRetVal == ERROR_SUCCESS)
  230. {
  231. // Show a success banner.
  232. ShowError(ERROR_SUCCESS, NULL, TRUE);
  233. }
  234. return dwRetVal;
  235. }
  236. // Performs actual output. of must be open.
  237. // Not called directly.
  238. VOID
  239. PrintLicense(
  240. IN LPCWSTR szName, // server allocating this license
  241. IN const LPLSLicense p,
  242. IN LPCTSTR szProductDesc,
  243. IN FILE *of)
  244. {
  245. // All of these are used solely to convert a time_t to a short date.
  246. BSTR bszDate;
  247. UDATE uDate;
  248. DATE Date;
  249. HRESULT hr;
  250. LPTSTR szType;
  251. // server name
  252. _fputts(szName, of);
  253. // license ID and keypack ID
  254. _ftprintf(of, _T("\t%d\t%d\t"),
  255. p->dwLicenseId,
  256. p->dwKeyPackId);
  257. // license holder (machine)
  258. _fputts(p->szMachineName, of);
  259. _fputtc('\t', of);
  260. // license requestor (username)
  261. _fputts(p->szUserName, of);
  262. _fputtc('\t', of);
  263. // Print issue date in locale-appropriate way
  264. UnixTimeToSystemTime((const time_t)p->ftIssueDate, &uDate.st);
  265. hr = VarDateFromUdate(&uDate, 0, &Date);
  266. if (S_OK != hr)
  267. {
  268. return;
  269. }
  270. hr = VarBstrFromDate(Date, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), VAR_DATEVALUEONLY, &bszDate);
  271. if (S_OK != hr)
  272. {
  273. return;
  274. }
  275. _fputts(bszDate, of);
  276. SysFreeString(bszDate);
  277. _fputtc('\t', of);
  278. // print either "No Expiration" or locale-nice expiration date
  279. if (0x7FFFFFFF != p->ftExpireDate)
  280. {
  281. _fputts(noExpire, of);
  282. }
  283. else
  284. {
  285. UnixTimeToSystemTime((const time_t)p->ftExpireDate, &uDate.st);
  286. hr = VarDateFromUdate(&uDate, 0, &Date);
  287. if (S_OK != hr)
  288. {
  289. return;
  290. }
  291. hr = VarBstrFromDate(Date, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), VAR_DATEVALUEONLY, &bszDate);
  292. if (S_OK != hr)
  293. {
  294. return;
  295. }
  296. _fputts(bszDate, of);
  297. SysFreeString(bszDate);
  298. }
  299. _fputtc('\t', of);
  300. // Assign the right kind of text for the type of license,
  301. // and then print the license type.
  302. switch (p->ucLicenseStatus) {
  303. case LSLICENSE_STATUS_TEMPORARY:
  304. szType = szTemp;
  305. break;
  306. case LSLICENSE_STATUS_ACTIVE:
  307. szType = szActive;
  308. break;
  309. case LSLICENSE_STATUS_UPGRADED:
  310. szType = szUpgrade;
  311. break;
  312. case LSLICENSE_STATUS_REVOKE:
  313. szType = szRevoked;
  314. break;
  315. case LSLICENSE_STATUS_PENDING:
  316. szType = szPending;
  317. break;
  318. case LSLICENSE_STATUS_CONCURRENT:
  319. szType = szConcur;
  320. break;
  321. case LSLICENSE_STATUS_UNKNOWN:
  322. // Fall through
  323. default:
  324. szType = szUnknown;
  325. }
  326. _fputts(szType, of);
  327. _fputtc('\t', of);
  328. // Print the description
  329. _fputts(szProductDesc, of);
  330. _fputtc('\n', of);
  331. }
  332. // returns <0 if when is before st, ==0 if they are the same date, and
  333. // >0 if when is after st.
  334. int CompDate(
  335. IN DWORD when, // treated as a time_t
  336. IN const PSYSTEMTIME st)
  337. {
  338. time_t when_t;
  339. //
  340. // time_t is 64 bits in win64. Convert, being careful to sign extend.
  341. //
  342. when_t = (time_t)((LONG)(when));
  343. struct tm *t = localtime(&when_t);
  344. if ((t->tm_year+1900) < st->wYear) {
  345. return -1;
  346. }
  347. if ((t->tm_year+1900) > st->wYear) {
  348. return 1;
  349. }
  350. if ((t->tm_mon+1) < st->wMonth) {
  351. return -1;
  352. }
  353. if ((t->tm_mon+1) > st->wMonth) {
  354. return 1;
  355. }
  356. if (t->tm_mday < st->wDay) {
  357. return -1;
  358. }
  359. if (t->tm_mday > st->wDay) {
  360. return 1;
  361. }
  362. return 0;
  363. }
  364. // From the Platform SDK.
  365. void
  366. UnixTimeToFileTime(
  367. IN time_t t,
  368. OUT LPFILETIME pft)
  369. {
  370. // Note that LONGLONG is a 64-bit value
  371. LONGLONG ll;
  372. ll = Int32x32To64(t, 10000000) + 116444736000000000;
  373. pft->dwLowDateTime = (DWORD)ll;
  374. pft->dwHighDateTime = (DWORD)(ll >> 32);
  375. }
  376. // Also from the Platform SDK.
  377. void
  378. UnixTimeToSystemTime(
  379. IN time_t t,
  380. OUT LPSYSTEMTIME pst)
  381. {
  382. FILETIME ft;
  383. UnixTimeToFileTime(t, &ft);
  384. FileTimeToSystemTime(&ft, pst);
  385. }