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.

707 lines
18 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. //-----------------------------
  27. DWORD
  28. GetPageSize( VOID ) {
  29. static DWORD dwPageSize = 0;
  30. if ( !dwPageSize ) {
  31. SYSTEM_INFO sysInfo = { 0 };
  32. GetSystemInfo( &sysInfo ); // cannot fail.
  33. dwPageSize = sysInfo.dwPageSize;
  34. }
  35. return dwPageSize;
  36. }
  37. /*++**************************************************************
  38. NAME: MyVirtualAlloc
  39. as Malloc, but automatically protects the last page of the
  40. allocation. This simulates pageheap behavior without requiring
  41. it.
  42. MODIFIES: ppvData -- receives memory
  43. TAKES: dwSize -- minimum amount of data to get
  44. RETURNS: TRUE when the function succeeds.
  45. FALSE otherwise.
  46. LASTERROR: not set
  47. Free with MyVirtualFree
  48. **************************************************************--*/
  49. BOOL
  50. MyVirtualAlloc( IN DWORD dwSize,
  51. OUT PVOID *ppvData )
  52. {
  53. PBYTE pbData;
  54. DWORD dwTotalSize;
  55. PVOID pvLastPage;
  56. // ensure that we allocate one extra page
  57. dwTotalSize = dwSize / GetPageSize();
  58. if( dwSize % GetPageSize() ) {
  59. dwTotalSize ++;
  60. }
  61. // this is the guard page
  62. dwTotalSize++;
  63. dwTotalSize *= GetPageSize();
  64. // do the alloc
  65. pbData = (PBYTE) VirtualAlloc( NULL, // don't care where
  66. dwTotalSize,
  67. MEM_COMMIT |
  68. MEM_TOP_DOWN,
  69. PAGE_READWRITE );
  70. if ( pbData ) {
  71. pbData += dwTotalSize;
  72. // find the LAST page.
  73. pbData -= GetPageSize();
  74. pvLastPage = pbData;
  75. // now, carve out a chunk for the caller:
  76. pbData -= dwSize;
  77. // last, protect the last page:
  78. if ( VirtualProtect( pvLastPage,
  79. 1, // protect the page containing the last byte
  80. PAGE_NOACCESS,
  81. &dwSize ) ) {
  82. *ppvData = pbData;
  83. return TRUE;
  84. }
  85. VirtualFree( pbData, 0, MEM_RELEASE );
  86. }
  87. return FALSE;
  88. }
  89. VOID
  90. MyVirtualFree( IN PVOID pvData )
  91. {
  92. VirtualFree( pvData, 0, MEM_RELEASE );
  93. }
  94. // Returns TRUE on success.
  95. BOOL
  96. InitLSReportStrings(VOID)
  97. {
  98. return (
  99. LoadString(NULL, IDS_HEADER_TEXT, header, HEADER_LENGTH) &&
  100. LoadString(NULL, IDS_NO_EXPIRE, noExpire, NOEXPIRE_LENGTH) &&
  101. LoadString(NULL, IDS_TEMPORARY_LICENSE, szTemp, TYPESTR_LENGTH) &&
  102. LoadString(NULL, IDS_ACTIVE_LICENSE, szActive, TYPESTR_LENGTH) &&
  103. LoadString(NULL, IDS_UPGRADED_LICENSE, szUpgrade, TYPESTR_LENGTH) &&
  104. LoadString(NULL, IDS_REVOKED_LICENSE, szRevoked, TYPESTR_LENGTH) &&
  105. LoadString(NULL, IDS_PENDING_LICENSE, szPending, TYPESTR_LENGTH) &&
  106. LoadString(NULL, IDS_CONCURRENT_LICENSE, szConcur, TYPESTR_LENGTH) &&
  107. LoadString(NULL, IDS_UNKNOWN_LICENSE, szUnknown, TYPESTR_LENGTH)
  108. );
  109. }
  110. typedef DWORD (WINAPI* PTLSGETLASTERRORFIXED) (
  111. TLS_HANDLE hHandle,
  112. LPTSTR *pszBuffer,
  113. PDWORD pdwErrCode
  114. );
  115. RPC_STATUS
  116. TryGetLastError(PCONTEXT_HANDLE hBinding,
  117. LPTSTR *pszBuffer)
  118. {
  119. RPC_STATUS status;
  120. DWORD dwErrCode;
  121. HINSTANCE hModule = LoadLibrary(L"mstlsapi.dll");
  122. if (hModule)
  123. {
  124. PTLSGETLASTERRORFIXED pfnGetLastErrorFixed = (PTLSGETLASTERRORFIXED) GetProcAddress(hModule,"TLSGetLastErrorFixed");
  125. if (pfnGetLastErrorFixed)
  126. {
  127. status = pfnGetLastErrorFixed(hBinding,pszBuffer,&dwErrCode);
  128. if(status == RPC_S_OK && dwErrCode == ERROR_SUCCESS && pszBuffer != NULL)
  129. {
  130. FreeLibrary(hModule);
  131. return status;
  132. }
  133. }
  134. FreeLibrary(hModule);
  135. }
  136. {
  137. LPTSTR lpszError = NULL;
  138. status = ERROR_NOACCESS;
  139. try
  140. {
  141. if ( !MyVirtualAlloc( ( TLS_ERROR_LENGTH ) * sizeof( TCHAR ),
  142. (PVOID*) &lpszError ) )
  143. {
  144. return RPC_S_OUT_OF_MEMORY;
  145. }
  146. DWORD uSize = TLS_ERROR_LENGTH ;
  147. memset(lpszError, 0, ( TLS_ERROR_LENGTH ) * sizeof( TCHAR ));
  148. status = TLSGetLastError(hBinding,uSize,lpszError,&dwErrCode);
  149. if(status == RPC_S_OK && dwErrCode == ERROR_SUCCESS)
  150. {
  151. *pszBuffer = (LPTSTR)MIDL_user_allocate((TLS_ERROR_LENGTH+1)*sizeof(TCHAR));
  152. if (NULL != *pszBuffer)
  153. {
  154. _tcscpy(*pszBuffer,lpszError);
  155. }
  156. }
  157. }
  158. catch (...)
  159. {
  160. status = ERROR_NOACCESS;
  161. }
  162. if(lpszError)
  163. MyVirtualFree(lpszError);
  164. }
  165. return status;
  166. }
  167. // Given a keypack and a machine to connect to, read every license in that kp.
  168. // Is not called directly.
  169. DWORD
  170. LicenseLoop(
  171. IN FILE *OutFile,
  172. IN LPWSTR szName, // who owns this keypack?
  173. IN DWORD kpID, // which keypack
  174. IN LPCTSTR szProductDesc,
  175. IN BOOL bTempOnly,
  176. IN const PSYSTEMTIME stStart,
  177. IN const PSYSTEMTIME stEnd,
  178. IN BOOL fUseLimits,
  179. IN BOOL fHwid) // are the above 2 parms valid
  180. {
  181. TLS_HANDLE subHand;
  182. DWORD dwStatus;
  183. DWORD dwErrCode = ERROR_SUCCESS;
  184. WCHAR *msg = NULL;
  185. LSLicense lsl;
  186. subHand = TLSConnectToLsServer(szName);
  187. if (subHand == NULL)
  188. {
  189. // The machine suddenly went away.
  190. ShowError(GetLastError(), NULL, TRUE);
  191. dwErrCode = ERROR_BAD_CONNECT;
  192. }
  193. else
  194. {
  195. lsl.dwKeyPackId = kpID;
  196. dwStatus = TLSLicenseEnumBegin(
  197. subHand,
  198. LSLICENSE_SEARCH_KEYPACKID,
  199. TRUE,
  200. &lsl,
  201. &dwErrCode);
  202. if (dwErrCode != ERROR_SUCCESS)
  203. {
  204. TryGetLastError(subHand, &msg);
  205. if (NULL != msg)
  206. {
  207. _fputts(msg, stderr);
  208. MIDL_user_free(msg);
  209. }
  210. return dwErrCode;
  211. }
  212. else if (dwStatus)
  213. {
  214. return dwStatus;
  215. }
  216. do {
  217. dwStatus = TLSLicenseEnumNext(subHand, &lsl, &dwErrCode);
  218. if ((dwStatus == RPC_S_OK) && (dwErrCode == ERROR_SUCCESS)) {
  219. if ((lsl.ucLicenseStatus == LSLICENSE_STATUS_TEMPORARY) ||
  220. !bTempOnly) { // Does it fit the temp. requirements?
  221. // We want to print if at any of the following are true:
  222. // a) There are no limits
  223. // b) Issued between stStart and stEnd
  224. // c) Expired between stStart and stEnd
  225. // d) issued before stStart and expired after stEnd
  226. if (!fUseLimits // case a
  227. || ((CompDate(lsl.ftIssueDate, stStart) >= 0) &&
  228. (CompDate(lsl.ftIssueDate, stEnd) <= 0)) // case b
  229. || ((CompDate(lsl.ftExpireDate, stStart) >= 0) &&
  230. (CompDate(lsl.ftExpireDate, stEnd) <= 0)) // case c
  231. || ((CompDate(lsl.ftIssueDate, stStart) <= 0) &&
  232. (CompDate(lsl.ftExpireDate, stEnd) >= 0))) // case d
  233. {
  234. PrintLicense(szName, // print it.
  235. &lsl,
  236. szProductDesc,
  237. OutFile,
  238. fHwid);
  239. } // end check cases
  240. } // end check for temp license
  241. } // end good getnext
  242. } while ((dwStatus == RPC_S_OK) && (dwErrCode == ERROR_SUCCESS));
  243. if (dwStatus != RPC_S_OK)
  244. {
  245. return ShowError(dwStatus, NULL, TRUE);
  246. }
  247. if (dwErrCode != LSERVER_I_NO_MORE_DATA)
  248. {
  249. TryGetLastError(subHand, &msg);
  250. if (NULL != msg)
  251. {
  252. _fputts(msg, stderr);
  253. MIDL_user_free(msg);
  254. msg = NULL;
  255. }
  256. }
  257. TLSLicenseEnumEnd(subHand, &dwErrCode);
  258. if (dwErrCode != ERROR_SUCCESS)
  259. {
  260. TryGetLastError(subHand, &msg);
  261. if (NULL != msg)
  262. {
  263. _fputts(msg, stderr);
  264. MIDL_user_free(msg);
  265. }
  266. }
  267. TLSDisconnectFromServer(subHand);
  268. }
  269. return dwErrCode;
  270. }
  271. // Given a machine to connect to, iterate through the keypacks.
  272. // Is not called directly.
  273. DWORD
  274. KeyPackLoop(
  275. IN FILE *OutFile,
  276. IN LPWSTR szName, // machine to connect to
  277. IN BOOL bTempOnly,
  278. IN const PSYSTEMTIME stStart,
  279. IN const PSYSTEMTIME stEnd,
  280. IN BOOL fUseLimits,
  281. IN BOOL fHwid) // do we care about the previous 2 parms?
  282. {
  283. TLS_HANDLE hand;
  284. DWORD dwStatus, dwErrCode;
  285. LSKeyPack lskpKeyPack;
  286. TCHAR *msg = NULL;
  287. hand = TLSConnectToLsServer(szName);
  288. if (hand == NULL)
  289. {
  290. return GetLastError();
  291. }
  292. memset(&lskpKeyPack, 0, sizeof(lskpKeyPack));
  293. lskpKeyPack.dwLanguageId = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
  294. dwStatus = TLSKeyPackEnumBegin(hand,
  295. LSKEYPACK_SEARCH_ALL,
  296. FALSE,
  297. &lskpKeyPack,
  298. &dwErrCode);
  299. if (dwErrCode != ERROR_SUCCESS)
  300. {
  301. return dwErrCode;
  302. }
  303. if (dwStatus != RPC_S_OK)
  304. {
  305. return dwStatus;
  306. }
  307. do {
  308. dwStatus = TLSKeyPackEnumNext(hand, &lskpKeyPack, &dwErrCode);
  309. if ((dwStatus == RPC_S_OK) && (dwErrCode == ERROR_SUCCESS))
  310. {
  311. LicenseLoop(OutFile,
  312. szName,
  313. lskpKeyPack.dwKeyPackId,
  314. lskpKeyPack.szProductDesc,
  315. bTempOnly,
  316. stStart,
  317. stEnd,
  318. fUseLimits,
  319. fHwid);
  320. }
  321. } while ((dwStatus == RPC_S_OK) && (dwErrCode == ERROR_SUCCESS));
  322. if (dwStatus != RPC_S_OK)
  323. {
  324. return ShowError(dwStatus, NULL, TRUE);
  325. }
  326. if (dwErrCode != LSERVER_I_NO_MORE_DATA)
  327. {
  328. TryGetLastError(hand, &msg);
  329. if (NULL != msg)
  330. {
  331. _fputts(msg, stderr);
  332. MIDL_user_free(msg);
  333. msg = NULL;
  334. }
  335. }
  336. TLSKeyPackEnumEnd(hand, &dwErrCode);
  337. if (dwErrCode != ERROR_SUCCESS)
  338. {
  339. TryGetLastError(hand, &msg);
  340. if (NULL != msg)
  341. {
  342. _fputts(msg, stderr);
  343. MIDL_user_free(msg);
  344. }
  345. }
  346. TLSDisconnectFromServer(hand);
  347. return dwErrCode;
  348. }
  349. // If bTempOnly is FALSE, all licenses will be dumped to the file. Otherwise,
  350. // only Temporary licenses will be written. This is the one function to call
  351. // to do all of the program's magic.
  352. DWORD
  353. ExportLicenses(
  354. IN FILE *OutFile, // must be opened for writing first
  355. IN PServerHolder pshServers,
  356. IN BOOL fTempOnly,
  357. IN const PSYSTEMTIME stStart,
  358. IN const PSYSTEMTIME stEnd,
  359. IN BOOL fUseLimits,
  360. IN BOOL fHwid) // are the above 2 parms valid?
  361. {
  362. DWORD i;
  363. DWORD dwStatus;
  364. DWORD dwRetVal = ERROR_SUCCESS;
  365. _fputts(header, OutFile);
  366. for (i = 0; i < pshServers->dwCount; i++) {
  367. dwStatus = KeyPackLoop(OutFile,
  368. pshServers->pszNames[i],
  369. fTempOnly,
  370. stStart,
  371. stEnd,
  372. fUseLimits,
  373. fHwid);
  374. if (dwStatus != ERROR_SUCCESS)
  375. {
  376. INT_PTR arg;
  377. dwRetVal = dwStatus;
  378. arg = (INT_PTR)pshServers->pszNames[i];
  379. ShowError(IDS_BAD_LOOP, &arg, FALSE);
  380. ShowError(dwStatus, NULL, TRUE);
  381. }
  382. }
  383. if (dwRetVal == ERROR_SUCCESS)
  384. {
  385. // Show a success banner.
  386. ShowError(ERROR_SUCCESS, NULL, TRUE);
  387. }
  388. return dwRetVal;
  389. }
  390. // Performs actual output. of must be open.
  391. // Not called directly.
  392. VOID
  393. PrintLicense(
  394. IN LPCWSTR szName, // server allocating this license
  395. IN const LPLSLicense p,
  396. IN LPCTSTR szProductDesc,
  397. IN FILE *of,
  398. IN BOOL fHwid)
  399. {
  400. // All of these are used solely to convert a time_t to a short date.
  401. BSTR bszDate;
  402. UDATE uDate;
  403. DATE Date;
  404. HRESULT hr;
  405. LPTSTR szType;
  406. TCHAR tc;
  407. // server name
  408. _fputts(szName, of);
  409. // license ID and keypack ID
  410. _ftprintf(of, _T("\t%d\t%d\t"),
  411. p->dwLicenseId,
  412. p->dwKeyPackId);
  413. // license holder (machine)
  414. _fputts(p->szMachineName, of);
  415. _fputtc('\t', of);
  416. // license requestor (username)
  417. _fputts(p->szUserName, of);
  418. _fputtc('\t', of);
  419. // Print issue date in locale-appropriate way
  420. UnixTimeToSystemTime((const time_t)p->ftIssueDate, &uDate.st);
  421. hr = VarDateFromUdate(&uDate, 0, &Date);
  422. if (S_OK != hr)
  423. {
  424. return;
  425. }
  426. hr = VarBstrFromDate(Date, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), VAR_DATEVALUEONLY, &bszDate);
  427. if (S_OK != hr)
  428. {
  429. return;
  430. }
  431. _fputts(bszDate, of);
  432. SysFreeString(bszDate);
  433. _fputtc('\t', of);
  434. // print either "No Expiration" or locale-nice expiration date
  435. if (0x7FFFFFFF == p->ftExpireDate)
  436. {
  437. _fputts(noExpire, of);
  438. }
  439. else
  440. {
  441. UnixTimeToSystemTime((const time_t)p->ftExpireDate, &uDate.st);
  442. hr = VarDateFromUdate(&uDate, 0, &Date);
  443. if (S_OK != hr)
  444. {
  445. return;
  446. }
  447. hr = VarBstrFromDate(Date, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), VAR_DATEVALUEONLY, &bszDate);
  448. if (S_OK != hr)
  449. {
  450. return;
  451. }
  452. _fputts(bszDate, of);
  453. SysFreeString(bszDate);
  454. }
  455. _fputtc('\t', of);
  456. // Assign the right kind of text for the type of license,
  457. // and then print the license type.
  458. switch (p->ucLicenseStatus) {
  459. case LSLICENSE_STATUS_TEMPORARY:
  460. szType = szTemp;
  461. break;
  462. case LSLICENSE_STATUS_ACTIVE:
  463. szType = szActive;
  464. break;
  465. case LSLICENSE_STATUS_UPGRADED:
  466. szType = szUpgrade;
  467. break;
  468. case LSLICENSE_STATUS_REVOKE:
  469. szType = szRevoked;
  470. break;
  471. case LSLICENSE_STATUS_PENDING:
  472. szType = szPending;
  473. break;
  474. case LSLICENSE_STATUS_CONCURRENT:
  475. szType = szConcur;
  476. break;
  477. case LSLICENSE_STATUS_UNKNOWN:
  478. // Fall through
  479. default:
  480. szType = szUnknown;
  481. }
  482. _fputts(szType, of);
  483. _fputtc('\t', of);
  484. // Print the description
  485. _fputts(szProductDesc, of);
  486. _fputtc('\t', of);
  487. //Doughu: Representation algorithm
  488. //We have only 36 informational chars I0 through I35 due to szHWID being TCHAR[37]
  489. //and we have to represent this in client HWID format, which is:
  490. //0xI0I10000I2I3, 0xI4I5I6I7I8I9I10I11, 0xI12I13I14I15I16I17I18I19, 0xI20I21I22I23I24I25I26I27, 0xI28I29I30I31I32I33I34I35
  491. if (fHwid)
  492. {
  493. for (int i=0; (((tc=p->szHWID[i])!=NULL)&&(i<36)); i++)
  494. {
  495. //this if statement is for prepending 0x
  496. if (i==0)
  497. {
  498. _fputtc('0', of);_fputtc('x', of);
  499. }
  500. _fputtc(tc,of);
  501. //this if statement is for 4 zeroes that need to be print since they were masked
  502. if (i==1)
  503. {
  504. _fputtc('0', of); _fputtc('0', of); _fputtc('0', of); _fputtc('0', of);
  505. }
  506. //this if statement is for I3, I11, I19 and I26 values where we put comma followed by space and 0x
  507. if((((i+5)%8)==0) &&( i!=35))
  508. {
  509. _fputtc(',', of); _fputtc(' ', of); _fputtc('0', of); _fputtc('x', of);
  510. }
  511. }
  512. _fputtc('\n', of);
  513. }
  514. else
  515. {
  516. _fputtc('\n', of);
  517. }
  518. }
  519. // returns <0 if when is before st, ==0 if they are the same date, and
  520. // >0 if when is after st.
  521. int CompDate(
  522. IN DWORD when, // treated as a time_t
  523. IN const PSYSTEMTIME st)
  524. {
  525. time_t when_t;
  526. //
  527. // time_t is 64 bits in win64. Convert, being careful to sign extend.
  528. //
  529. when_t = (time_t)((LONG)(when));
  530. struct tm *t = localtime(&when_t);
  531. if ((t->tm_year+1900) < st->wYear) {
  532. return -1;
  533. }
  534. if ((t->tm_year+1900) > st->wYear) {
  535. return 1;
  536. }
  537. if ((t->tm_mon+1) < st->wMonth) {
  538. return -1;
  539. }
  540. if ((t->tm_mon+1) > st->wMonth) {
  541. return 1;
  542. }
  543. if (t->tm_mday < st->wDay) {
  544. return -1;
  545. }
  546. if (t->tm_mday > st->wDay) {
  547. return 1;
  548. }
  549. return 0;
  550. }
  551. // From the Platform SDK.
  552. void
  553. UnixTimeToFileTime(
  554. IN time_t t,
  555. OUT LPFILETIME pft)
  556. {
  557. // Note that LONGLONG is a 64-bit value
  558. LONGLONG ll;
  559. ll = Int32x32To64(t, 10000000) + 116444736000000000;
  560. pft->dwLowDateTime = (DWORD)ll;
  561. pft->dwHighDateTime = (DWORD)(ll >> 32);
  562. }
  563. // Also from the Platform SDK.
  564. void
  565. UnixTimeToSystemTime(
  566. IN time_t t,
  567. OUT LPSYSTEMTIME pst)
  568. {
  569. FILETIME ft;
  570. FILETIME ftloc;
  571. UnixTimeToFileTime(t, &ft);
  572. FileTimeToLocalFileTime(&ft, &ftloc);
  573. FileTimeToSystemTime(&ftloc, pst);
  574. }