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.

893 lines
17 KiB

  1. /*++
  2. Copyright (c) 1994-95 Microsoft Corporation
  3. Module Name:
  4. prdobj.cpp
  5. Abstract:
  6. Product object implementation.
  7. Author:
  8. Don Ryan (donryan) 11-Jan-1995
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. --*/
  13. #include "stdafx.h"
  14. #include "llsmgr.h"
  15. #ifdef _DEBUG
  16. #undef THIS_FILE
  17. static char BASED_CODE THIS_FILE[] = __FILE__;
  18. #endif
  19. IMPLEMENT_DYNCREATE(CProduct, CCmdTarget)
  20. BEGIN_MESSAGE_MAP(CProduct, CCmdTarget)
  21. //{{AFX_MSG_MAP(CProduct)
  22. // NOTE - the ClassWizard will add and remove mapping macros here.
  23. //}}AFX_MSG_MAP
  24. END_MESSAGE_MAP()
  25. BEGIN_DISPATCH_MAP(CProduct, CCmdTarget)
  26. //{{AFX_DISPATCH_MAP(CProduct)
  27. DISP_PROPERTY_EX(CProduct, "Application", GetApplication, SetNotSupported, VT_DISPATCH)
  28. DISP_PROPERTY_EX(CProduct, "Parent", GetParent, SetNotSupported, VT_DISPATCH)
  29. DISP_PROPERTY_EX(CProduct, "InUse", GetInUse, SetNotSupported, VT_I4)
  30. DISP_PROPERTY_EX(CProduct, "Name", GetName, SetNotSupported, VT_BSTR)
  31. DISP_PROPERTY_EX(CProduct, "PerSeatLimit", GetPerSeatLimit, SetNotSupported, VT_I4)
  32. DISP_PROPERTY_EX(CProduct, "PerServerLimit", GetPerServerLimit, SetNotSupported, VT_I4)
  33. DISP_PROPERTY_EX(CProduct, "PerServerReached", GetPerServerReached, SetNotSupported, VT_I4)
  34. DISP_PROPERTY_PARAM(CProduct, "Licenses", GetLicenses, SetNotSupported, VT_DISPATCH, VTS_VARIANT)
  35. DISP_PROPERTY_PARAM(CProduct, "Statistics", GetStatistics, SetNotSupported, VT_DISPATCH, VTS_VARIANT)
  36. DISP_PROPERTY_PARAM(CProduct, "ServerStatistics", GetServerStatistics, SetNotSupported, VT_DISPATCH, VTS_VARIANT)
  37. DISP_DEFVALUE(CProduct, "Name")
  38. //}}AFX_DISPATCH_MAP
  39. END_DISPATCH_MAP()
  40. CProduct::CProduct(
  41. CCmdTarget* pParent,
  42. LPCTSTR pName,
  43. long lPurchased,
  44. long lInUse,
  45. long lConcurrent,
  46. long lHighMark
  47. )
  48. /*++
  49. Routine Description:
  50. Constructor for product object.
  51. Arguments:
  52. pParent - creator of object.
  53. pName - name of product.
  54. lPurchased - number of licenses available.
  55. lInUse - number of licenses consumed.
  56. lConcurrent - number of concurrent licenses.
  57. lHighMark - high water mark for domain.
  58. Return Values:
  59. None.
  60. --*/
  61. {
  62. EnableAutomation();
  63. #ifdef ENABLE_PARENT_CHECK
  64. ASSERT(pParent && pParent->IsKindOf(RUNTIME_CLASS(CController)));
  65. #endif // ENABLE_PARENT_CHECK
  66. m_pParent = pParent;
  67. ASSERT(pName && *pName);
  68. m_strName = pName;
  69. m_lInUse = lInUse;
  70. m_lLimit = lPurchased;
  71. m_lConcurrent = lConcurrent;
  72. m_lHighMark = lHighMark;
  73. m_pLicenses = NULL;
  74. m_pStatistics = NULL;
  75. m_pServerStatistics = NULL;
  76. m_licenseArray.RemoveAll();
  77. m_statisticArray.RemoveAll();
  78. m_serverstatisticArray.RemoveAll();
  79. m_bLicensesRefreshed = FALSE;
  80. m_bStatisticsRefreshed = FALSE;
  81. m_bServerStatisticsRefreshed = FALSE;
  82. }
  83. CProduct::~CProduct()
  84. /*++
  85. Routine Description:
  86. Destructor for product object.
  87. Arguments:
  88. None.
  89. Return Values:
  90. None.
  91. --*/
  92. {
  93. if (m_pLicenses)
  94. m_pLicenses->InternalRelease();
  95. if (m_pStatistics)
  96. m_pStatistics->InternalRelease();
  97. if (m_pServerStatistics)
  98. m_pServerStatistics->InternalRelease();
  99. }
  100. void CProduct::OnFinalRelease()
  101. /*++
  102. Routine Description:
  103. When the last reference for an automation object is released
  104. OnFinalRelease is called. This implementation deletes object.
  105. Arguments:
  106. None.
  107. Return Values:
  108. None.
  109. --*/
  110. {
  111. ResetLicenses();
  112. ResetStatistics();
  113. ResetServerStatistics();
  114. delete this;
  115. }
  116. LPDISPATCH CProduct::GetApplication()
  117. /*++
  118. Routine Description:
  119. Returns the application object.
  120. Arguments:
  121. None.
  122. Return Values:
  123. VT_DISPATCH.
  124. --*/
  125. {
  126. return theApp.GetAppIDispatch();
  127. }
  128. long CProduct::GetInUse()
  129. /*++
  130. Routine Description:
  131. Returns the number of clients registered as using product.
  132. Arguments:
  133. None.
  134. Return Values:
  135. VT_I4.
  136. --*/
  137. {
  138. return m_lInUse;
  139. }
  140. LPDISPATCH CProduct::GetLicenses(const VARIANT FAR& index)
  141. /*++
  142. Routine Description:
  143. Returns a collection object containing all of the
  144. license agreements recorded on the license controller
  145. pertaining to the product or returns an individual
  146. license agreement pertaining to the product described
  147. by an index into the collection.
  148. Arguments:
  149. index - optional argument that may be a number (VT_I4)
  150. indicating the position within collection.
  151. Return Values:
  152. VT_DISPATCH or VT_EMPTY.
  153. --*/
  154. {
  155. LPDISPATCH lpdispatch = NULL;
  156. if (!m_pLicenses)
  157. {
  158. m_pLicenses = new CLicenses(this, &m_licenseArray);
  159. }
  160. if (m_pLicenses)
  161. {
  162. if (V_ISVOID((VARIANT FAR*)&index))
  163. {
  164. if (RefreshLicenses())
  165. {
  166. lpdispatch = m_pLicenses->GetIDispatch(TRUE);
  167. }
  168. }
  169. else
  170. {
  171. if (m_bLicensesRefreshed)
  172. {
  173. lpdispatch = m_pLicenses->GetItem(index);
  174. }
  175. else if (RefreshLicenses())
  176. {
  177. lpdispatch = m_pLicenses->GetItem(index);
  178. }
  179. }
  180. }
  181. else
  182. {
  183. LlsSetLastStatus( STATUS_NO_MEMORY );
  184. }
  185. return lpdispatch;
  186. }
  187. BSTR CProduct::GetName()
  188. /*++
  189. Routine Description:
  190. Returns the name of the server product.
  191. Arguments:
  192. None.
  193. Return Values:
  194. VT_BSTR.
  195. --*/
  196. {
  197. return m_strName.AllocSysString();
  198. }
  199. LPDISPATCH CProduct::GetParent()
  200. /*++
  201. Routine Description:
  202. Returns the parent of the object.
  203. Arguments:
  204. None.
  205. Return Values:
  206. VT_DISPATCH.
  207. --*/
  208. {
  209. return m_pParent ? m_pParent->GetIDispatch(TRUE) : NULL;
  210. }
  211. long CProduct::GetPerSeatLimit()
  212. /*++
  213. Routine Description:
  214. Returns number of per seat clients purchased.
  215. Arguments:
  216. None.
  217. Return Values:
  218. VT_I4.
  219. --*/
  220. {
  221. return m_lLimit;
  222. }
  223. long CProduct::GetPerServerLimit()
  224. /*++
  225. Routine Description:
  226. Returns number of per server clients purchased.
  227. Arguments:
  228. None.
  229. Return Values:
  230. VT_I4.
  231. --*/
  232. {
  233. return m_lConcurrent;
  234. }
  235. LPDISPATCH CProduct::GetStatistics(const VARIANT FAR& index)
  236. /*++
  237. Routine Description:
  238. Returns a collection object containing all of the
  239. usage statistics recorded on the license controller
  240. pertaining to the product or returns an individual
  241. usage statistic pertaining to the product described
  242. by an index into the collection.
  243. Arguments:
  244. index - optional argument that may be a number (VT_I4)
  245. indicating the position within collection.
  246. Return Values:
  247. VT_DISPATCH or VT_EMPTY.
  248. --*/
  249. {
  250. LPDISPATCH lpdispatch = NULL;
  251. if (!m_pStatistics)
  252. {
  253. m_pStatistics = new CStatistics(this, &m_statisticArray);
  254. }
  255. if (m_pStatistics)
  256. {
  257. if (V_ISVOID((VARIANT FAR*)&index))
  258. {
  259. if (RefreshStatistics())
  260. {
  261. lpdispatch = m_pStatistics->GetIDispatch(TRUE);
  262. }
  263. }
  264. else
  265. {
  266. if (m_bStatisticsRefreshed)
  267. {
  268. lpdispatch = m_pStatistics->GetItem(index);
  269. }
  270. else if (RefreshStatistics())
  271. {
  272. lpdispatch = m_pStatistics->GetItem(index);
  273. }
  274. }
  275. }
  276. else
  277. {
  278. LlsSetLastStatus( STATUS_NO_MEMORY );
  279. }
  280. return lpdispatch;
  281. }
  282. LPDISPATCH CProduct::GetServerStatistics(const VARIANT FAR& index)
  283. /*++
  284. Routine Description:
  285. Returns a collection object containing all of the
  286. usage statistics recorded on the license controller
  287. pertaining to the product or returns an individual
  288. server statistic pertaining to the product described
  289. by an index into the collection.
  290. Arguments:
  291. index - optional argument that may be a number (VT_I4)
  292. indicating the position within collection.
  293. Return Values:
  294. VT_DISPATCH or VT_EMPTY.
  295. --*/
  296. {
  297. LPDISPATCH lpdispatch = NULL;
  298. if (!m_pServerStatistics)
  299. {
  300. m_pServerStatistics = new CServerStatistics(this, &m_serverstatisticArray);
  301. }
  302. if (m_pServerStatistics)
  303. {
  304. if (V_ISVOID((VARIANT FAR*)&index))
  305. {
  306. if (RefreshServerStatistics())
  307. {
  308. lpdispatch = m_pServerStatistics->GetIDispatch(TRUE);
  309. }
  310. }
  311. else
  312. {
  313. if (m_bServerStatisticsRefreshed)
  314. {
  315. lpdispatch = m_pServerStatistics->GetItem(index);
  316. }
  317. else if (RefreshServerStatistics())
  318. {
  319. lpdispatch = m_pServerStatistics->GetItem(index);
  320. }
  321. }
  322. }
  323. else
  324. {
  325. LlsSetLastStatus( STATUS_NO_MEMORY );
  326. }
  327. return lpdispatch;
  328. }
  329. BOOL CProduct::RefreshLicenses()
  330. /*++
  331. Routine Description:
  332. Refreshs license object list.
  333. Arguments:
  334. None.
  335. Return Values:
  336. None.
  337. --*/
  338. {
  339. ResetLicenses();
  340. NTSTATUS NtStatus;
  341. DWORD ResumeHandle = 0L;
  342. int iLicense = 0;
  343. do
  344. {
  345. DWORD EntriesRead;
  346. DWORD TotalEntries;
  347. LPBYTE ReturnBuffer = NULL;
  348. NtStatus = ::LlsProductLicenseEnum(
  349. LlsGetActiveHandle(),
  350. MKSTR(m_strName),
  351. 0,
  352. &ReturnBuffer,
  353. LLS_PREFERRED_LENGTH,
  354. &EntriesRead,
  355. &TotalEntries,
  356. &ResumeHandle
  357. );
  358. if (NtStatus == STATUS_SUCCESS ||
  359. NtStatus == STATUS_MORE_ENTRIES)
  360. {
  361. CLicense* pLicense;
  362. PLLS_PRODUCT_LICENSE_INFO_0 pProductLicenseInfo0;
  363. pProductLicenseInfo0 = (PLLS_PRODUCT_LICENSE_INFO_0)ReturnBuffer;
  364. ASSERT(iLicense == m_licenseArray.GetSize());
  365. m_licenseArray.SetSize(m_licenseArray.GetSize() + EntriesRead);
  366. while (EntriesRead--)
  367. {
  368. pLicense = new CLicense(
  369. this,
  370. m_strName,
  371. pProductLicenseInfo0->Admin,
  372. pProductLicenseInfo0->Date,
  373. pProductLicenseInfo0->Quantity,
  374. pProductLicenseInfo0->Comment
  375. );
  376. m_licenseArray.SetAt(iLicense++, pLicense); // validate later...
  377. #ifndef DISABLE_PER_NODE_ALLOCATION
  378. ::LlsFreeMemory(pProductLicenseInfo0->Admin);
  379. ::LlsFreeMemory(pProductLicenseInfo0->Comment);
  380. #endif // DISABLE_PER_NODE_ALLOCATION
  381. pProductLicenseInfo0++;
  382. }
  383. ::LlsFreeMemory(ReturnBuffer);
  384. }
  385. } while (NtStatus == STATUS_MORE_ENTRIES);
  386. LlsSetLastStatus(NtStatus); // called api
  387. if (NT_SUCCESS(NtStatus))
  388. {
  389. m_bLicensesRefreshed = TRUE;
  390. }
  391. else
  392. {
  393. ResetLicenses();
  394. }
  395. return m_bLicensesRefreshed;
  396. }
  397. BOOL CProduct::RefreshStatistics()
  398. /*++
  399. Routine Description:
  400. Refreshs statistic object list.
  401. Arguments:
  402. None.
  403. Return Values:
  404. None.
  405. --*/
  406. {
  407. ResetStatistics();
  408. NTSTATUS NtStatus;
  409. DWORD ResumeHandle = 0L;
  410. int iStatistic = 0;
  411. do
  412. {
  413. DWORD EntriesRead;
  414. DWORD TotalEntries;
  415. LPBYTE ReturnBuffer = NULL;
  416. NtStatus = ::LlsProductUserEnum(
  417. LlsGetActiveHandle(),
  418. MKSTR(m_strName),
  419. 1,
  420. &ReturnBuffer,
  421. LLS_PREFERRED_LENGTH,
  422. &EntriesRead,
  423. &TotalEntries,
  424. &ResumeHandle
  425. );
  426. if (NtStatus == STATUS_SUCCESS ||
  427. NtStatus == STATUS_MORE_ENTRIES)
  428. {
  429. CStatistic* pStatistic;
  430. PLLS_PRODUCT_USER_INFO_1 pProductUserInfo1;
  431. pProductUserInfo1 = (PLLS_PRODUCT_USER_INFO_1)ReturnBuffer;
  432. ASSERT(iStatistic == m_statisticArray.GetSize());
  433. m_statisticArray.SetSize(m_statisticArray.GetSize() + EntriesRead);
  434. while (EntriesRead--)
  435. {
  436. pStatistic = new CStatistic(
  437. this,
  438. pProductUserInfo1->User,
  439. pProductUserInfo1->Flags,
  440. pProductUserInfo1->LastUsed,
  441. pProductUserInfo1->UsageCount
  442. );
  443. m_statisticArray.SetAt(iStatistic++, pStatistic); // validate later...
  444. #ifndef DISABLE_PER_NODE_ALLOCATION
  445. ::LlsFreeMemory(pProductUserInfo1->User);
  446. #endif // DISABLE_PER_NODE_ALLOCATION
  447. pProductUserInfo1++;
  448. }
  449. ::LlsFreeMemory(ReturnBuffer);
  450. }
  451. } while (NtStatus == STATUS_MORE_ENTRIES);
  452. LlsSetLastStatus(NtStatus); // called api
  453. if (NT_SUCCESS(NtStatus))
  454. {
  455. m_bStatisticsRefreshed = TRUE;
  456. }
  457. else
  458. {
  459. ResetStatistics();
  460. }
  461. return m_bStatisticsRefreshed;
  462. }
  463. BOOL CProduct::RefreshServerStatistics()
  464. /*++
  465. Routine Description:
  466. Refreshs server statistic object list.
  467. Arguments:
  468. None.
  469. Return Values:
  470. None.
  471. --*/
  472. {
  473. ResetServerStatistics();
  474. NTSTATUS NtStatus;
  475. DWORD ResumeHandle = 0L;
  476. int iStatistic = 0;
  477. do
  478. {
  479. DWORD EntriesRead;
  480. DWORD TotalEntries;
  481. LPBYTE ReturnBuffer = NULL;
  482. NtStatus = ::LlsProductServerEnum(
  483. LlsGetActiveHandle(),
  484. MKSTR(m_strName),
  485. 1,
  486. &ReturnBuffer,
  487. LLS_PREFERRED_LENGTH,
  488. &EntriesRead,
  489. &TotalEntries,
  490. &ResumeHandle
  491. );
  492. if (NtStatus == STATUS_SUCCESS ||
  493. NtStatus == STATUS_MORE_ENTRIES)
  494. {
  495. CServerStatistic* pStatistic;
  496. PLLS_SERVER_PRODUCT_INFO_1 pProductServerInfo1;
  497. pProductServerInfo1 = (PLLS_SERVER_PRODUCT_INFO_1)ReturnBuffer;
  498. ASSERT(iStatistic == m_serverstatisticArray.GetSize());
  499. m_serverstatisticArray.SetSize(m_serverstatisticArray.GetSize() + EntriesRead);
  500. while (EntriesRead--)
  501. {
  502. pStatistic = new CServerStatistic(
  503. this,
  504. pProductServerInfo1->Name,
  505. pProductServerInfo1->Flags,
  506. pProductServerInfo1->MaxUses,
  507. pProductServerInfo1->HighMark
  508. );
  509. m_serverstatisticArray.SetAt(iStatistic++, pStatistic); // validate later...
  510. #ifndef DISABLE_PER_NODE_ALLOCATION
  511. ::LlsFreeMemory(pProductServerInfo1->Name);
  512. #endif // DISABLE_PER_NODE_ALLOCATION
  513. pProductServerInfo1++;
  514. }
  515. ::LlsFreeMemory(ReturnBuffer);
  516. }
  517. } while (NtStatus == STATUS_MORE_ENTRIES);
  518. LlsSetLastStatus(NtStatus); // called api
  519. if (NT_SUCCESS(NtStatus))
  520. {
  521. m_bServerStatisticsRefreshed = TRUE;
  522. }
  523. else
  524. {
  525. ResetServerStatistics();
  526. }
  527. return m_bServerStatisticsRefreshed;
  528. }
  529. void CProduct::ResetLicenses()
  530. /*++
  531. Routine Description:
  532. Resets license object list.
  533. Arguments:
  534. None.
  535. Return Values:
  536. None.
  537. --*/
  538. {
  539. CLicense* pLicense;
  540. INT_PTR iLicense = m_licenseArray.GetSize();
  541. while (iLicense--)
  542. {
  543. if (pLicense = (CLicense*)m_licenseArray[iLicense])
  544. {
  545. ASSERT(pLicense->IsKindOf(RUNTIME_CLASS(CLicense)));
  546. pLicense->InternalRelease();
  547. }
  548. }
  549. m_licenseArray.RemoveAll();
  550. m_bLicensesRefreshed = FALSE;
  551. }
  552. void CProduct::ResetStatistics()
  553. /*++
  554. Routine Description:
  555. Resets statistic object list.
  556. Arguments:
  557. None.
  558. Return Values:
  559. None.
  560. --*/
  561. {
  562. CStatistic* pStatistic;
  563. INT_PTR iStatistic = m_statisticArray.GetSize();
  564. while (iStatistic--)
  565. {
  566. if (pStatistic = (CStatistic*)m_statisticArray[iStatistic])
  567. {
  568. ASSERT(pStatistic->IsKindOf(RUNTIME_CLASS(CStatistic)));
  569. pStatistic->InternalRelease();
  570. }
  571. }
  572. m_statisticArray.RemoveAll();
  573. m_bStatisticsRefreshed = FALSE;
  574. }
  575. void CProduct::ResetServerStatistics()
  576. /*++
  577. Routine Description:
  578. Resets statistic object list.
  579. Arguments:
  580. None.
  581. Return Values:
  582. None.
  583. --*/
  584. {
  585. CServerStatistic* pStatistic;
  586. INT_PTR iStatistic = m_serverstatisticArray.GetSize();
  587. while (iStatistic--)
  588. {
  589. if (pStatistic = (CServerStatistic*)m_serverstatisticArray[iStatistic])
  590. {
  591. ASSERT(pStatistic->IsKindOf(RUNTIME_CLASS(CServerStatistic)));
  592. pStatistic->InternalRelease();
  593. }
  594. }
  595. m_serverstatisticArray.RemoveAll();
  596. m_bServerStatisticsRefreshed = FALSE;
  597. }
  598. long CProduct::GetPerServerReached()
  599. {
  600. return m_lHighMark;
  601. }