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.

8430 lines
204 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. rpc.c
  5. Abstract:
  6. Author:
  7. Arthur Hanson (arth) 06-Jan-1995
  8. Revision History:
  9. Jeff Parham (jeffparh) 05-Dec-1995
  10. o Added replication of certificate database and secure service list.
  11. o Added Llsr API to support secure certificates.
  12. o Added LLS_LICENSE_INFO_1 support to LlsrLicenseEnumW() and
  13. LlsrLicenseAddW().
  14. o Added LLS_PRODUCT_LICENSE_INFO_1 support to LlsrProductLicenseEnumW().
  15. o Added save of all data files after receiving replicated data.
  16. --*/
  17. #include <nt.h>
  18. #include <ntrtl.h>
  19. #include <nturtl.h>
  20. #include <windows.h>
  21. #include <dsgetdc.h>
  22. #include <malloc.h> // Added for SBS mods (bug# 505640). _wcsdup uses malloc
  23. #include "llsapi.h"
  24. #include "debug.h"
  25. #include "llssrv.h"
  26. #include "mapping.h"
  27. #include "msvctbl.h"
  28. #include "svctbl.h"
  29. #include "perseat.h"
  30. #include "purchase.h"
  31. #include "server.h"
  32. #include "ntlsapi.h"
  33. #include "llsrpc_s.h"
  34. #include "lsapi_s.h"
  35. #include "llsdbg_s.h"
  36. #include "repl.h"
  37. #include "pack.h"
  38. #include "registry.h"
  39. #include "certdb.h"
  40. #include "llsrtl.h"
  41. #include <strsafe.h> //include last
  42. #define LLS_SIG "LLSS"
  43. #define LLS_SIG_SIZE 4
  44. #define LLS_REPL_SIG "REPL"
  45. #define LLS_REPL_SIG_SIZE 4
  46. extern RTL_RESOURCE CertDbHeaderListLock;
  47. #define LLS_POTENTIAL_ATTACK_THRESHHOLD 20
  48. DWORD PotentialAttackCounter = 0;
  49. typedef struct {
  50. char Signature[LLS_SIG_SIZE];
  51. PVOID *ProductUserEnumWRestartTable;
  52. DWORD ProductUserEnumWRestartTableSize;
  53. PVOID *UserEnumWRestartTable;
  54. DWORD UserEnumWRestartTableSize;
  55. TCHAR Name[MAX_COMPUTERNAME_LENGTH + 1];
  56. } CLIENT_CONTEXT_TYPE, *PCLIENT_CONTEXT_TYPE;
  57. typedef struct {
  58. char Signature[LLS_REPL_SIG_SIZE];
  59. TCHAR Name[MAX_COMPUTERNAME_LENGTH + 1];
  60. DWORD ReplicationStart;
  61. BOOL Active;
  62. BOOL Replicated;
  63. BOOL ServicesSent;
  64. ULONG ServiceTableSize;
  65. PREPL_SERVICE_RECORD Services;
  66. BOOL ServersSent;
  67. ULONG ServerTableSize;
  68. PREPL_SERVER_RECORD Servers;
  69. BOOL ServerServicesSent;
  70. ULONG ServerServiceTableSize;
  71. PREPL_SERVER_SERVICE_RECORD ServerServices;
  72. BOOL UsersSent;
  73. ULONG UserLevel;
  74. ULONG UserTableSize;
  75. LPVOID Users;
  76. BOOL CertDbSent;
  77. ULONG CertDbProductStringSize;
  78. WCHAR * CertDbProductStrings;
  79. ULONG CertDbNumHeaders;
  80. PREPL_CERT_DB_CERTIFICATE_HEADER_0 CertDbHeaders;
  81. ULONG CertDbNumClaims;
  82. PREPL_CERT_DB_CERTIFICATE_CLAIM_0 CertDbClaims;
  83. BOOL ProductSecuritySent;
  84. ULONG ProductSecurityStringSize;
  85. WCHAR * ProductSecurityStrings;
  86. } REPL_CONTEXT_TYPE, *PREPL_CONTEXT_TYPE;
  87. //
  88. // This function is obtained from the April 1998 Knowledge Base
  89. // Its purpose is to determine if the current user is an
  90. // Administrator and therefore priveledged to change license
  91. // settings.
  92. //
  93. // BOOL IsAdmin(void)
  94. //
  95. // returns TRUE if user is an admin
  96. // FALSE if user is not an admin
  97. //
  98. #if 0
  99. BOOL IsAdmin(void)
  100. {
  101. HANDLE hAccessToken;
  102. UCHAR InfoBuffer[1024];
  103. PTOKEN_GROUPS ptgGroups = (PTOKEN_GROUPS)InfoBuffer;
  104. DWORD dwInfoBufferSize;
  105. PSID psidAdministrators;
  106. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  107. UINT x;
  108. BOOL bSuccess;
  109. if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE,
  110. &hAccessToken )) {
  111. if (GetLastError() != ERROR_NO_TOKEN)
  112. return FALSE;
  113. //
  114. // retry against process token if no thread token exists
  115. //
  116. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY,
  117. &hAccessToken))
  118. return FALSE;
  119. }
  120. bSuccess = GetTokenInformation(hAccessToken,TokenGroups,InfoBuffer,
  121. 1024, &dwInfoBufferSize);
  122. CloseHandle(hAccessToken);
  123. if (!bSuccess )
  124. return FALSE;
  125. if (!AllocateAndInitializeSid(&siaNtAuthority, 2,
  126. SECURITY_BUILTIN_DOMAIN_RID,
  127. DOMAIN_ALIAS_RID_ADMINS,
  128. 0, 0, 0, 0, 0, 0,
  129. &psidAdministrators))
  130. return FALSE;
  131. // assume that we don't find the admin SID.
  132. bSuccess = FALSE;
  133. for (x=0;x<ptgGroups->GroupCount;x++) {
  134. if ( EqualSid(psidAdministrators, ptgGroups->Groups[x].Sid) ) {
  135. bSuccess = TRUE;
  136. break;
  137. }
  138. }
  139. FreeSid(psidAdministrators);
  140. return bSuccess;
  141. }
  142. #endif
  143. /////////////////////////////////////////////////////////////////////////
  144. NTSTATUS
  145. LLSRpcListen (
  146. IN PVOID ThreadParameter
  147. )
  148. /*++
  149. Routine Description:
  150. Arguments:
  151. ThreadParameter - Indicates how many active threads there currently
  152. are.
  153. Return Value:
  154. None.
  155. --*/
  156. {
  157. RPC_STATUS Status;
  158. UNREFERENCED_PARAMETER(ThreadParameter);
  159. Status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, 0);
  160. if (Status) {
  161. #if DBG
  162. dprintf(TEXT("RpcServerListen Failed (0x%lx)\n"), Status);
  163. #endif
  164. }
  165. return Status;
  166. } // LLSRpcListen
  167. /////////////////////////////////////////////////////////////////////////
  168. VOID
  169. LLSRpcInit()
  170. /*++
  171. Routine Description:
  172. Arguments:
  173. Return Value:
  174. None.
  175. --*/
  176. {
  177. RPC_STATUS Status;
  178. DWORD Ignore;
  179. HANDLE Thread;
  180. //
  181. // Setup for LPC calls..
  182. //
  183. Status = RpcServerUseProtseqEp(TEXT("ncalrpc"), RPC_C_PROTSEQ_MAX_REQS_DEFAULT, TEXT(LLS_LPC_ENDPOINT), NULL);
  184. if (Status) {
  185. #if DBG
  186. dprintf(TEXT("RpcServerUseProtseq ncalrpc Failed (0x%lx)\n"), Status);
  187. #endif
  188. return;
  189. }
  190. // Named pipes as well
  191. Status = RpcServerUseProtseqEp(TEXT("ncacn_np"), RPC_C_PROTSEQ_MAX_REQS_DEFAULT, TEXT(LLS_NP_ENDPOINT), NULL);
  192. if (Status) {
  193. #if DBG
  194. dprintf(TEXT("RpcServerUseProtseq ncacn_np Failed (0x%lx)\n"), Status);
  195. #endif
  196. return;
  197. }
  198. // register the interface for the UI RPC's
  199. Status = RpcServerRegisterIf(llsrpc_ServerIfHandle, NULL, NULL);
  200. if (Status) {
  201. #if DBG
  202. dprintf(TEXT("RpcServerRegisterIf Failed (0x%lx)\n"), Status);
  203. #endif
  204. return;
  205. }
  206. // Now the interface for the Licensing RPC's
  207. Status = RpcServerRegisterIf(lsapirpc_ServerIfHandle, NULL, NULL);
  208. if (Status) {
  209. #if DBG
  210. dprintf(TEXT("RpcServerRegisterIf2 Failed (0x%lx)\n"), Status);
  211. #endif
  212. return;
  213. }
  214. #if DBG
  215. //
  216. // ... and if DEBUG then the debugging interface
  217. //
  218. Status = RpcServerRegisterIf(llsdbgrpc_ServerIfHandle, NULL, NULL);
  219. if (Status) {
  220. #if DBG
  221. dprintf(TEXT("RpcServerRegisterIf (debug) Failed (0x%lx)\n"), Status);
  222. #endif
  223. return;
  224. }
  225. #endif
  226. //
  227. // Create thread to listen for requests.
  228. //
  229. Thread = CreateThread(
  230. NULL,
  231. 0L,
  232. (LPTHREAD_START_ROUTINE) LLSRpcListen,
  233. 0L,
  234. 0L,
  235. &Ignore
  236. );
  237. #if DBG
  238. if (NULL == Thread) {
  239. dprintf(TEXT("CreateThread Failed\n"));
  240. }
  241. #endif
  242. if (NULL != Thread)
  243. CloseHandle(Thread);
  244. } // LLSRpcInit
  245. ///////////////////////////////////////////////////////////////////////////////
  246. ///////////////////////////////////////////////////////////////////////////////
  247. ///////////////////////////////////////////////////////////////////////////////
  248. /////////////////////////////////////////////////////////////////////////
  249. VOID __RPC_USER LLS_HANDLE_rundown(
  250. LLS_HANDLE Handle
  251. )
  252. /*++
  253. Routine Description:
  254. Arguments:
  255. Return Value:
  256. --*/
  257. {
  258. PCLIENT_CONTEXT_TYPE pClient;
  259. #if DBG
  260. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  261. dprintf(TEXT("LLS TRACE: LLS_HANDLE_rundown\n"));
  262. #endif
  263. pClient = (PCLIENT_CONTEXT_TYPE) Handle;
  264. try
  265. {
  266. if (0 != memcmp(pClient->Signature,LLS_SIG,LLS_SIG_SIZE))
  267. {
  268. return;
  269. }
  270. if (NULL != pClient->ProductUserEnumWRestartTable)
  271. LocalFree(pClient->ProductUserEnumWRestartTable);
  272. if (NULL != pClient->UserEnumWRestartTable)
  273. LocalFree(pClient->UserEnumWRestartTable);
  274. //
  275. // Deallocate context.
  276. //
  277. midl_user_free(Handle);
  278. } except(EXCEPTION_EXECUTE_HANDLER ) {
  279. }
  280. } // LLS_HANDLE_rundown
  281. /////////////////////////////////////////////////////////////////////////
  282. NTSTATUS LlsrConnect(
  283. PLLS_HANDLE Handle,
  284. LPTSTR Name
  285. )
  286. /*++
  287. Routine Description:
  288. Arguments:
  289. Return Value:
  290. --*/
  291. {
  292. CLIENT_CONTEXT_TYPE *pClient;
  293. RPC_STATUS Status = STATUS_SUCCESS;
  294. HRESULT hr;
  295. #if DBG
  296. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  297. dprintf(TEXT("LLS TRACE: LlsConnect: %s\n"), Name);
  298. #endif
  299. #if DELAY_INITIALIZATION
  300. EnsureInitialized();
  301. #endif
  302. if (NULL == Handle)
  303. {
  304. return STATUS_INVALID_PARAMETER;
  305. }
  306. *Handle = NULL;
  307. pClient = (CLIENT_CONTEXT_TYPE *) midl_user_allocate(sizeof(CLIENT_CONTEXT_TYPE));
  308. if (NULL == pClient)
  309. {
  310. #if DBG
  311. dprintf(TEXT("midl_user_allocate Failed\n"));
  312. #endif
  313. Status = STATUS_NO_MEMORY;
  314. goto LlsrConnectExit;
  315. }
  316. if (Name != NULL)
  317. {
  318. if (lstrlen(Name) > MAX_COMPUTERNAME_LENGTH)
  319. {
  320. Status = STATUS_INVALID_PARAMETER;
  321. midl_user_free(pClient);
  322. goto LlsrConnectExit;
  323. }
  324. hr = StringCbCopy(pClient->Name, sizeof(pClient->Name), Name);
  325. ASSERT(SUCCEEDED(hr));
  326. }
  327. else
  328. {
  329. hr = StringCbCopy(pClient->Name, sizeof(pClient->Name), TEXT(""));
  330. ASSERT(SUCCEEDED(hr));
  331. }
  332. memcpy(pClient->Signature,LLS_SIG,LLS_SIG_SIZE);
  333. pClient->ProductUserEnumWRestartTable = NULL;
  334. pClient->ProductUserEnumWRestartTableSize = 0;
  335. pClient->UserEnumWRestartTable = NULL;
  336. pClient->UserEnumWRestartTableSize = 0;
  337. *Handle = pClient;
  338. LlsrConnectExit:
  339. return Status;
  340. } // LlsrConnect
  341. /////////////////////////////////////////////////////////////////////////
  342. NTSTATUS LlsrClose(
  343. LLS_HANDLE Handle
  344. )
  345. /*++
  346. Routine Description:
  347. Obsolete - use LlsrCloseEx
  348. Arguments:
  349. Return Value:
  350. --*/
  351. {
  352. #if DBG
  353. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  354. dprintf(TEXT("LLS TRACE: LlsClose\n"));
  355. #endif
  356. UNREFERENCED_PARAMETER(Handle);
  357. //
  358. // Don't do anything; let rundown do cleanup
  359. // We have no way of telling RPC system the handle can't be used
  360. //
  361. return STATUS_SUCCESS;
  362. } // LlsrClose
  363. /////////////////////////////////////////////////////////////////////////
  364. NTSTATUS LlsrCloseEx(
  365. LLS_HANDLE * pHandle
  366. )
  367. /*++
  368. Routine Description:
  369. Arguments:
  370. Return Value:
  371. --*/
  372. {
  373. #if DBG
  374. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  375. dprintf(TEXT("LLS TRACE: LlsCloseEx\n"));
  376. #endif
  377. if ((pHandle != NULL) && (*pHandle != NULL))
  378. {
  379. LLS_HANDLE_rundown(*pHandle);
  380. *pHandle = NULL;
  381. }
  382. return STATUS_SUCCESS;
  383. } // LlsrCloseEx
  384. /////////////////////////////////////////////////////////////////////////
  385. NTSTATUS LlsrLicenseEnumW(
  386. LLS_HANDLE Handle,
  387. PLLS_LICENSE_ENUM_STRUCTW pLicenseInfo,
  388. DWORD pPrefMaxLen,
  389. LPDWORD pTotalEntries,
  390. LPDWORD pResumeHandle
  391. )
  392. /*++
  393. Routine Description:
  394. Arguments:
  395. Return Value:
  396. --*/
  397. {
  398. NTSTATUS Status = STATUS_SUCCESS;
  399. DWORD Level;
  400. PVOID BufPtr = NULL;
  401. ULONG BufSize = 0;
  402. ULONG EntriesRead = 0;
  403. ULONG TotalEntries = 0;
  404. ULONG i = 0;
  405. ULONG j = 0;
  406. DWORD RecordSize;
  407. #if DBG
  408. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  409. dprintf(TEXT("LLS TRACE: LlsLicenseEnumW\n"));
  410. #endif
  411. UNREFERENCED_PARAMETER(Handle);
  412. #if DELAY_INITIALIZATION
  413. EnsureInitialized();
  414. #endif
  415. //
  416. // Need to scan list so get read access.
  417. //
  418. RtlAcquireResourceShared(&LicenseListLock, TRUE);
  419. if ((NULL == pLicenseInfo) || (NULL == pTotalEntries))
  420. {
  421. return STATUS_INVALID_PARAMETER;
  422. }
  423. Level = pLicenseInfo->Level;
  424. *pTotalEntries = 0;
  425. if ( 0 == Level )
  426. {
  427. if (NULL == pLicenseInfo->LlsLicenseInfo.Level0)
  428. {
  429. return STATUS_INVALID_PARAMETER;
  430. }
  431. RecordSize = sizeof( LLS_LICENSE_INFO_0W );
  432. }
  433. else if ( 1 == Level )
  434. {
  435. if (NULL == pLicenseInfo->LlsLicenseInfo.Level1)
  436. {
  437. return STATUS_INVALID_PARAMETER;
  438. }
  439. RecordSize = sizeof( LLS_LICENSE_INFO_1W );
  440. }
  441. else
  442. {
  443. return STATUS_INVALID_LEVEL;
  444. }
  445. //
  446. // Calculate how many records will fit into PrefMaxLen buffer.
  447. //
  448. i = (pResumeHandle != NULL) ? *pResumeHandle : 0;
  449. while ( ( i < PurchaseListSize ) && ( BufSize < pPrefMaxLen ) )
  450. {
  451. if ( ( Level > 0 )
  452. || ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SEAT ) )
  453. {
  454. BufSize += RecordSize;
  455. EntriesRead++;
  456. }
  457. i++;
  458. }
  459. TotalEntries = EntriesRead;
  460. //
  461. // If we overflowed the buffer then back up one record.
  462. //
  463. if (BufSize > pPrefMaxLen)
  464. {
  465. BufSize -= RecordSize;
  466. EntriesRead--;
  467. }
  468. //
  469. // Now walk to the end of the list to see how many more records are still
  470. // available.
  471. //
  472. while ( i < PurchaseListSize )
  473. {
  474. if ( ( Level > 0 )
  475. || ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SEAT ) )
  476. {
  477. TotalEntries++;
  478. }
  479. i++;
  480. }
  481. if (TotalEntries > EntriesRead)
  482. Status = STATUS_MORE_ENTRIES;
  483. //
  484. // Reset Enum to correct place.
  485. //
  486. i = (pResumeHandle != NULL) ? *pResumeHandle : 0;
  487. //
  488. // We now know how many records will fit into the buffer, so allocate space
  489. // and fix up pointers so we can copy the information.
  490. //
  491. BufPtr = MIDL_user_allocate(BufSize);
  492. if (BufPtr == NULL) {
  493. Status = STATUS_NO_MEMORY;
  494. goto LlsrLicenseEnumWExit;
  495. }
  496. RtlZeroMemory((PVOID) BufPtr, BufSize);
  497. //
  498. // Buffers are all setup, so loop through records and copy the data.
  499. //
  500. while ((j < EntriesRead) && (i < PurchaseListSize))
  501. {
  502. if ( ( Level > 0 )
  503. || ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SEAT ) )
  504. {
  505. if ( 0 == Level )
  506. {
  507. ((PLLS_LICENSE_INFO_0W) BufPtr)[j].Product = PurchaseList[i].Service->ServiceName;
  508. ((PLLS_LICENSE_INFO_0W) BufPtr)[j].Quantity = PurchaseList[i].NumberLicenses;
  509. ((PLLS_LICENSE_INFO_0W) BufPtr)[j].Date = PurchaseList[i].Date;
  510. ((PLLS_LICENSE_INFO_0W) BufPtr)[j].Admin = PurchaseList[i].Admin;
  511. ((PLLS_LICENSE_INFO_0W) BufPtr)[j].Comment = PurchaseList[i].Comment;
  512. }
  513. else
  514. {
  515. ((PLLS_LICENSE_INFO_1W) BufPtr)[j].Product = ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SEAT )
  516. ? PurchaseList[i].Service->ServiceName
  517. : PurchaseList[i].PerServerService->ServiceName;
  518. ((PLLS_LICENSE_INFO_1W) BufPtr)[j].Vendor = PurchaseList[i].Vendor;
  519. ((PLLS_LICENSE_INFO_1W) BufPtr)[j].Quantity = PurchaseList[i].NumberLicenses;
  520. ((PLLS_LICENSE_INFO_1W) BufPtr)[j].MaxQuantity = PurchaseList[i].MaxQuantity;
  521. ((PLLS_LICENSE_INFO_1W) BufPtr)[j].Date = PurchaseList[i].Date;
  522. ((PLLS_LICENSE_INFO_1W) BufPtr)[j].Admin = PurchaseList[i].Admin;
  523. ((PLLS_LICENSE_INFO_1W) BufPtr)[j].Comment = PurchaseList[i].Comment;
  524. ((PLLS_LICENSE_INFO_1W) BufPtr)[j].AllowedModes = PurchaseList[i].AllowedModes;
  525. ((PLLS_LICENSE_INFO_1W) BufPtr)[j].CertificateID = PurchaseList[i].CertificateID;
  526. ((PLLS_LICENSE_INFO_1W) BufPtr)[j].Source = PurchaseList[i].Source;
  527. ((PLLS_LICENSE_INFO_1W) BufPtr)[j].ExpirationDate = PurchaseList[i].ExpirationDate;
  528. memcpy( ((PLLS_LICENSE_INFO_1W) BufPtr)[j].Secrets, PurchaseList[i].Secrets, LLS_NUM_SECRETS * sizeof( *PurchaseList[i].Secrets ) );
  529. }
  530. j++;
  531. }
  532. i++;
  533. }
  534. LlsrLicenseEnumWExit:
  535. #if DBG
  536. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  537. dprintf(TEXT(" TotalEntries: %lu EntriesRead: %lu ResumeHandle: 0x%lX\n"), TotalEntries, EntriesRead, i);
  538. #endif
  539. *pTotalEntries = TotalEntries;
  540. if (pResumeHandle != NULL)
  541. *pResumeHandle = (ULONG) i;
  542. if ( 0 == Level )
  543. {
  544. pLicenseInfo->LlsLicenseInfo.Level0->EntriesRead = EntriesRead;
  545. pLicenseInfo->LlsLicenseInfo.Level0->Buffer = (PLLS_LICENSE_INFO_0W) BufPtr;
  546. }
  547. else
  548. {
  549. pLicenseInfo->LlsLicenseInfo.Level1->EntriesRead = EntriesRead;
  550. pLicenseInfo->LlsLicenseInfo.Level1->Buffer = (PLLS_LICENSE_INFO_1W) BufPtr;
  551. }
  552. return Status;
  553. } // LlsrLicenseEnumW
  554. void LlsrLicenseEnumW_notify_flag(
  555. boolean fNotify
  556. )
  557. {
  558. if (fNotify)
  559. {
  560. RtlReleaseResource(&LicenseListLock);
  561. }
  562. }
  563. /////////////////////////////////////////////////////////////////////////
  564. NTSTATUS LlsrLicenseEnumA(
  565. LLS_HANDLE Handle,
  566. PLLS_LICENSE_ENUM_STRUCTA LicenseInfo,
  567. DWORD PrefMaxLen,
  568. LPDWORD TotalEntries,
  569. LPDWORD ResumeHandle
  570. )
  571. /*++
  572. Routine Description:
  573. Arguments:
  574. Return Value:
  575. --*/
  576. {
  577. #if DBG
  578. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  579. dprintf(TEXT("LLS TRACE: LlsLicenseEnumA\n"));
  580. #endif
  581. UNREFERENCED_PARAMETER(Handle);
  582. UNREFERENCED_PARAMETER(LicenseInfo);
  583. UNREFERENCED_PARAMETER(PrefMaxLen);
  584. UNREFERENCED_PARAMETER(ResumeHandle);
  585. if (NULL == TotalEntries)
  586. {
  587. return STATUS_INVALID_PARAMETER;
  588. }
  589. *TotalEntries = 0;
  590. return STATUS_NOT_SUPPORTED;
  591. } // LlsrLicenseEnumA
  592. /////////////////////////////////////////////////////////////////////////
  593. NTSTATUS LlsrLicenseAddW(
  594. LLS_HANDLE Handle,
  595. DWORD Level,
  596. PLLS_LICENSE_INFOW BufPtr
  597. )
  598. /*++
  599. Routine Description:
  600. Arguments:
  601. Return Value:
  602. --*/
  603. {
  604. NTSTATUS Status;
  605. HRESULT hr;
  606. #if DBG
  607. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  608. dprintf(TEXT("LLS TRACE: LlsLicenseAddW\n"));
  609. #endif
  610. UNREFERENCED_PARAMETER(Handle);
  611. #if DELAY_INITIALIZATION
  612. EnsureInitialized();
  613. #endif
  614. #if 0
  615. //
  616. // Check that client is an administrator
  617. //
  618. rpcstat = RpcImpersonateClient(0);
  619. if (rpcstat != RPC_S_OK)
  620. {
  621. //should handle dont_free in BufPtr
  622. return STATUS_ACCESS_DENIED;
  623. }
  624. if (!IsAdmin())
  625. {
  626. RpcRevertToSelf();
  627. //should handle dont_free in BufPtr
  628. return STATUS_ACCESS_DENIED;
  629. }
  630. RpcRevertToSelf();
  631. #endif
  632. if ( 0 == Level )
  633. {
  634. if ( ( NULL == BufPtr )
  635. || ( NULL == BufPtr->LicenseInfo0.Product )
  636. || ( NULL == BufPtr->LicenseInfo0.Admin )
  637. || ( NULL == BufPtr->LicenseInfo0.Comment ) )
  638. {
  639. Status = STATUS_INVALID_PARAMETER;
  640. }
  641. else
  642. {
  643. Status = LicenseAdd( BufPtr->LicenseInfo0.Product,
  644. TEXT("Microsoft"),
  645. BufPtr->LicenseInfo0.Quantity,
  646. 0,
  647. BufPtr->LicenseInfo0.Admin,
  648. BufPtr->LicenseInfo0.Comment,
  649. 0,
  650. LLS_LICENSE_MODE_ALLOW_PER_SEAT,
  651. 0,
  652. TEXT("None"),
  653. 0,
  654. NULL );
  655. }
  656. }
  657. else if ( 1 == Level )
  658. {
  659. if ( ( NULL == BufPtr )
  660. || ( NULL == BufPtr->LicenseInfo1.Product )
  661. || ( NULL == BufPtr->LicenseInfo1.Admin )
  662. || ( NULL == BufPtr->LicenseInfo1.Comment )
  663. || ( 0 == BufPtr->LicenseInfo1.Quantity )
  664. || ( 0 == ( BufPtr->LicenseInfo1.AllowedModes
  665. & ( LLS_LICENSE_MODE_ALLOW_PER_SERVER
  666. | LLS_LICENSE_MODE_ALLOW_PER_SEAT ) ) ) )
  667. {
  668. Status = STATUS_INVALID_PARAMETER;
  669. }
  670. else
  671. {
  672. // check to see if this certificate is already maxed out in the enterprise
  673. BOOL bIsMaster = TRUE;
  674. BOOL bMayInstall = TRUE;
  675. HINSTANCE hDll = NULL;
  676. PLLS_CONNECT_ENTERPRISE_W pLlsConnectEnterpriseW = NULL;
  677. PLLS_CLOSE pLlsClose = NULL;
  678. PLLS_CAPABILITY_IS_SUPPORTED pLlsCapabilityIsSupported = NULL;
  679. PLLS_CERTIFICATE_CLAIM_ADD_CHECK_W pLlsCertificateClaimAddCheckW = NULL;
  680. PLLS_CERTIFICATE_CLAIM_ADD_W pLlsCertificateClaimAddW = NULL;
  681. PLLS_FREE_MEMORY pLlsFreeMemory = NULL;
  682. LLS_HANDLE hEnterpriseLls = NULL;
  683. TCHAR szComputerName[ 1 + MAX_COMPUTERNAME_LENGTH ];
  684. szComputerName[0] = 0;
  685. ConfigInfoUpdate(NULL,TRUE);
  686. RtlEnterCriticalSection( &ConfigInfoLock );
  687. bIsMaster = ConfigInfo.IsMaster;
  688. if (ConfigInfo.ComputerName != NULL)
  689. {
  690. hr = StringCbCopy( szComputerName, sizeof(szComputerName), ConfigInfo.ComputerName );
  691. ASSERT(SUCCEEDED(hr));
  692. }
  693. RtlLeaveCriticalSection( &ConfigInfoLock );
  694. if( !bIsMaster && ( 0 != BufPtr->LicenseInfo1.CertificateID ) )
  695. {
  696. // ask enterprise server if we can install this certfificate
  697. hDll = LoadLibraryA( "LLSRPC.DLL" );
  698. if ( NULL == hDll )
  699. {
  700. // LLSRPC.DLL should be available!
  701. ASSERT( FALSE );
  702. }
  703. else
  704. {
  705. pLlsConnectEnterpriseW = (PLLS_CONNECT_ENTERPRISE_W ) GetProcAddress( hDll, "LlsConnectEnterpriseW" );
  706. pLlsClose = (PLLS_CLOSE ) GetProcAddress( hDll, "LlsClose" );
  707. pLlsCapabilityIsSupported = (PLLS_CAPABILITY_IS_SUPPORTED ) GetProcAddress( hDll, "LlsCapabilityIsSupported" );
  708. pLlsCertificateClaimAddCheckW = (PLLS_CERTIFICATE_CLAIM_ADD_CHECK_W ) GetProcAddress( hDll, "LlsCertificateClaimAddCheckW" );
  709. pLlsCertificateClaimAddW = (PLLS_CERTIFICATE_CLAIM_ADD_W ) GetProcAddress( hDll, "LlsCertificateClaimAddW" );
  710. pLlsFreeMemory = (PLLS_FREE_MEMORY ) GetProcAddress( hDll, "LlsFreeMemory" );
  711. if ( ( NULL == pLlsConnectEnterpriseW )
  712. || ( NULL == pLlsClose )
  713. || ( NULL == pLlsCapabilityIsSupported )
  714. || ( NULL == pLlsCertificateClaimAddCheckW )
  715. || ( NULL == pLlsCertificateClaimAddW )
  716. || ( NULL == pLlsFreeMemory ) )
  717. {
  718. // All of these functions should be exported!
  719. ASSERT( FALSE );
  720. }
  721. else
  722. {
  723. PLLS_CONNECT_INFO_0 pConnectInfo;
  724. Status = (*pLlsConnectEnterpriseW)( NULL, &hEnterpriseLls, 0, (LPBYTE *)&pConnectInfo );
  725. if ( STATUS_SUCCESS == Status )
  726. {
  727. (*pLlsFreeMemory)( pConnectInfo );
  728. if ( (*pLlsCapabilityIsSupported)( hEnterpriseLls, LLS_CAPABILITY_SECURE_CERTIFICATES ) )
  729. {
  730. Status = (*pLlsCertificateClaimAddCheckW)( hEnterpriseLls, Level, (LPBYTE) BufPtr, &bMayInstall );
  731. if ( STATUS_SUCCESS != Status )
  732. {
  733. bMayInstall = TRUE;
  734. }
  735. }
  736. }
  737. }
  738. }
  739. }
  740. if ( !bMayInstall )
  741. {
  742. // denied!
  743. Status = STATUS_ALREADY_COMMITTED;
  744. }
  745. else
  746. {
  747. // approved! (or an error occurred trying to get approval...)
  748. Status = LicenseAdd( BufPtr->LicenseInfo1.Product,
  749. BufPtr->LicenseInfo1.Vendor,
  750. BufPtr->LicenseInfo1.Quantity,
  751. BufPtr->LicenseInfo1.MaxQuantity,
  752. BufPtr->LicenseInfo1.Admin,
  753. BufPtr->LicenseInfo1.Comment,
  754. 0,
  755. BufPtr->LicenseInfo1.AllowedModes,
  756. BufPtr->LicenseInfo1.CertificateID,
  757. BufPtr->LicenseInfo1.Source,
  758. BufPtr->LicenseInfo1.ExpirationDate,
  759. BufPtr->LicenseInfo1.Secrets );
  760. if ( ( STATUS_SUCCESS == Status )
  761. && ( NULL != hEnterpriseLls )
  762. && ( (*pLlsCapabilityIsSupported)( hEnterpriseLls, LLS_CAPABILITY_SECURE_CERTIFICATES ) ) )
  763. {
  764. // certificate successfully installed on this machine; register it
  765. (*pLlsCertificateClaimAddW)( hEnterpriseLls, szComputerName, Level, (LPBYTE) BufPtr );
  766. }
  767. }
  768. if ( NULL != hEnterpriseLls )
  769. {
  770. (*pLlsClose)( hEnterpriseLls );
  771. }
  772. if ( NULL != hDll )
  773. {
  774. FreeLibrary( hDll );
  775. }
  776. }
  777. }
  778. else
  779. {
  780. Status = STATUS_INVALID_LEVEL;
  781. }
  782. if ( STATUS_SUCCESS == Status )
  783. {
  784. Status = LicenseListSave();
  785. }
  786. if (NULL != BufPtr)
  787. {
  788. // PNAMEW are declared as dont_free, we should free them
  789. if (0 == Level)
  790. {
  791. if (NULL != BufPtr->LicenseInfo0.Product)
  792. {
  793. MIDL_user_free(BufPtr->LicenseInfo0.Product);
  794. }
  795. if (NULL != BufPtr->LicenseInfo0.Admin)
  796. {
  797. MIDL_user_free(BufPtr->LicenseInfo0.Admin);
  798. }
  799. if (NULL != BufPtr->LicenseInfo0.Comment)
  800. {
  801. MIDL_user_free(BufPtr->LicenseInfo0.Comment);
  802. }
  803. }
  804. if (1 == Level)
  805. {
  806. if (NULL != BufPtr->LicenseInfo1.Product)
  807. {
  808. MIDL_user_free(BufPtr->LicenseInfo1.Product);
  809. }
  810. if (NULL != BufPtr->LicenseInfo1.Admin)
  811. {
  812. MIDL_user_free(BufPtr->LicenseInfo1.Admin);
  813. }
  814. if (NULL != BufPtr->LicenseInfo1.Comment)
  815. {
  816. MIDL_user_free(BufPtr->LicenseInfo1.Comment);
  817. }
  818. if (NULL != BufPtr->LicenseInfo1.Vendor)
  819. {
  820. MIDL_user_free(BufPtr->LicenseInfo1.Vendor);
  821. }
  822. if (NULL != BufPtr->LicenseInfo1.Source)
  823. {
  824. MIDL_user_free(BufPtr->LicenseInfo1.Source);
  825. }
  826. }
  827. }
  828. return Status;
  829. } // LlsrLicenseAddW
  830. /////////////////////////////////////////////////////////////////////////
  831. NTSTATUS LlsrLicenseAddA(
  832. LLS_HANDLE Handle,
  833. DWORD Level,
  834. PLLS_LICENSE_INFOA BufPtr
  835. )
  836. /*++
  837. Routine Description:
  838. Arguments:
  839. Return Value:
  840. --*/
  841. {
  842. #if DBG
  843. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  844. dprintf(TEXT("LLS TRACE: LlsLicenseAddA\n"));
  845. #endif
  846. UNREFERENCED_PARAMETER(Handle);
  847. UNREFERENCED_PARAMETER(Level);
  848. UNREFERENCED_PARAMETER(BufPtr);
  849. return STATUS_NOT_SUPPORTED;
  850. } // LlsrLicenseAddA
  851. /////////////////////////////////////////////////////////////////////////
  852. NTSTATUS LlsrProductEnumW(
  853. LLS_HANDLE Handle,
  854. PLLS_PRODUCT_ENUM_STRUCTW pProductInfo,
  855. DWORD pPrefMaxLen,
  856. LPDWORD pTotalEntries,
  857. LPDWORD pResumeHandle
  858. )
  859. /*++
  860. Routine Description:
  861. Arguments:
  862. Return Value:
  863. --*/
  864. {
  865. NTSTATUS Status = STATUS_SUCCESS;
  866. DWORD Level;
  867. ULONG RecSize;
  868. PVOID BufPtr = NULL;
  869. ULONG BufSize = 0;
  870. ULONG EntriesRead = 0;
  871. ULONG TotalEntries = 0;
  872. ULONG i = 0;
  873. ULONG j = 0;
  874. UNREFERENCED_PARAMETER(Handle);
  875. #if DBG
  876. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  877. dprintf(TEXT("LLS TRACE: LlsProductEnumW\n"));
  878. #endif
  879. #if DELAY_INITIALIZATION
  880. EnsureInitialized();
  881. #endif
  882. //
  883. // Need to scan list so get read access.
  884. //
  885. RtlAcquireResourceShared(&MasterServiceListLock, TRUE);
  886. if ((NULL == pTotalEntries) || (NULL == pProductInfo))
  887. {
  888. return STATUS_INVALID_PARAMETER;
  889. }
  890. *pTotalEntries = 0;
  891. //
  892. // Get size of each record based on info level. Only 0 and 1 supported.
  893. //
  894. Level = pProductInfo->Level;
  895. if (Level == 0)
  896. {
  897. if (NULL == pProductInfo->LlsProductInfo.Level0)
  898. {
  899. return STATUS_INVALID_PARAMETER;
  900. }
  901. RecSize = sizeof(LLS_PRODUCT_INFO_0W);
  902. }
  903. else if (Level == 1)
  904. {
  905. if (NULL == pProductInfo->LlsProductInfo.Level1)
  906. {
  907. return STATUS_INVALID_PARAMETER;
  908. }
  909. RecSize = sizeof(LLS_PRODUCT_INFO_1W);
  910. }
  911. else {
  912. return STATUS_INVALID_LEVEL;
  913. }
  914. //
  915. // Calculate how many records will fit into PrefMaxLen buffer. This is
  916. // the record size * # records + space for the string data. If MAX_ULONG
  917. // is passed in then we return all records.
  918. //
  919. i = (pResumeHandle != NULL) ? *pResumeHandle : 0;
  920. while ((i < MasterServiceListSize) && (BufSize < pPrefMaxLen)) {
  921. BufSize += RecSize;
  922. EntriesRead++;
  923. i++;
  924. }
  925. TotalEntries = EntriesRead;
  926. //
  927. // If we overflowed the buffer then back up one record.
  928. //
  929. if (BufSize > pPrefMaxLen) {
  930. BufSize -= RecSize;
  931. EntriesRead--;
  932. }
  933. if (i < MasterServiceListSize)
  934. Status = STATUS_MORE_ENTRIES;
  935. //
  936. // Now walk to the end of the list to see how many more records are still
  937. // available.
  938. //
  939. TotalEntries += (MasterServiceListSize - i);
  940. //
  941. // Reset Enum to correct place.
  942. //
  943. i = (pResumeHandle != NULL) ? *pResumeHandle : 0;
  944. //
  945. // We now know how many records will fit into the buffer, so allocate space
  946. // and fix up pointers so we can copy the information.
  947. //
  948. BufPtr = MIDL_user_allocate(BufSize);
  949. if (BufPtr == NULL) {
  950. Status = STATUS_NO_MEMORY;
  951. goto LlsrProductEnumWExit;
  952. }
  953. RtlZeroMemory((PVOID) BufPtr, BufSize);
  954. //
  955. // Buffers are all setup, so loop through records and copy the data.
  956. //
  957. while ((j < EntriesRead) && (i < MasterServiceListSize)) {
  958. if (Level == 0)
  959. ((PLLS_PRODUCT_INFO_0) BufPtr)[j].Product = MasterServiceList[i]->Name;
  960. else {
  961. ((PLLS_PRODUCT_INFO_1) BufPtr)[j].Product = MasterServiceList[i]->Name;
  962. ((PLLS_PRODUCT_INFO_1) BufPtr)[j].Purchased = MasterServiceList[i]->Licenses;
  963. ((PLLS_PRODUCT_INFO_1) BufPtr)[j].InUse = MasterServiceList[i]->LicensesUsed;
  964. ((PLLS_PRODUCT_INFO_1) BufPtr)[j].ConcurrentTotal = MasterServiceList[i]->MaxSessionCount;
  965. ((PLLS_PRODUCT_INFO_1) BufPtr)[j].HighMark = MasterServiceList[i]->HighMark;
  966. }
  967. i++; j++;
  968. }
  969. LlsrProductEnumWExit:
  970. #if DBG
  971. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  972. dprintf(TEXT(" TotalEntries: %lu EntriesRead: %lu ResumeHandle: 0x%lX\n"), TotalEntries, EntriesRead, i);
  973. #endif
  974. *pTotalEntries = TotalEntries;
  975. if (pResumeHandle != NULL)
  976. *pResumeHandle = (ULONG) i;
  977. if (Level == 0) {
  978. pProductInfo->LlsProductInfo.Level0->EntriesRead = EntriesRead;
  979. pProductInfo->LlsProductInfo.Level0->Buffer = (PLLS_PRODUCT_INFO_0W) BufPtr;
  980. } else {
  981. pProductInfo->LlsProductInfo.Level1->EntriesRead = EntriesRead;
  982. pProductInfo->LlsProductInfo.Level1->Buffer = (PLLS_PRODUCT_INFO_1W) BufPtr;
  983. }
  984. return Status;
  985. } // LlsrProductEnumW
  986. void LlsrProductEnumW_notify_flag(
  987. boolean fNotify
  988. )
  989. {
  990. if (fNotify)
  991. {
  992. RtlReleaseResource(&MasterServiceListLock);
  993. }
  994. }
  995. /////////////////////////////////////////////////////////////////////////
  996. NTSTATUS LlsrProductEnumA(
  997. LLS_HANDLE Handle,
  998. PLLS_PRODUCT_ENUM_STRUCTA ProductInfo,
  999. DWORD PrefMaxLen,
  1000. LPDWORD TotalEntries,
  1001. LPDWORD ResumeHandle
  1002. )
  1003. /*++
  1004. Routine Description:
  1005. Arguments:
  1006. Return Value:
  1007. --*/
  1008. {
  1009. #if DBG
  1010. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  1011. dprintf(TEXT("LLS TRACE: LlsProductEnumA\n"));
  1012. #endif
  1013. UNREFERENCED_PARAMETER(Handle);
  1014. UNREFERENCED_PARAMETER(ProductInfo);
  1015. UNREFERENCED_PARAMETER(PrefMaxLen);
  1016. UNREFERENCED_PARAMETER(ResumeHandle);
  1017. if (NULL == TotalEntries)
  1018. {
  1019. return STATUS_INVALID_PARAMETER;
  1020. }
  1021. *TotalEntries = 0;
  1022. return STATUS_NOT_SUPPORTED;
  1023. } // LlsrProductEnumA
  1024. /////////////////////////////////////////////////////////////////////////
  1025. NTSTATUS LlsrProductAddW(
  1026. LLS_HANDLE Handle,
  1027. LPWSTR ProductFamily,
  1028. LPWSTR Product,
  1029. LPWSTR lpVersion
  1030. )
  1031. /*++
  1032. Routine Description:
  1033. Arguments:
  1034. Return Value:
  1035. --*/
  1036. {
  1037. PMASTER_SERVICE_RECORD Service;
  1038. DWORD Version;
  1039. #if DBG
  1040. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  1041. dprintf(TEXT("LLS TRACE: LlsProductAddW\n"));
  1042. #endif
  1043. UNREFERENCED_PARAMETER(Handle);
  1044. #if DELAY_INITIALIZATION
  1045. EnsureInitialized();
  1046. #endif
  1047. if ((ProductFamily == NULL) || (Product == NULL) || (lpVersion == NULL))
  1048. return STATUS_INVALID_PARAMETER;
  1049. Version = VersionToDWORD(lpVersion);
  1050. RtlAcquireResourceExclusive(&MasterServiceListLock,TRUE);
  1051. Service = MasterServiceListAdd(ProductFamily, Product, Version);
  1052. RtlReleaseResource(&MasterServiceListLock);
  1053. if (Service == NULL)
  1054. return STATUS_NO_MEMORY;
  1055. return STATUS_SUCCESS;
  1056. } // LlsrProductAddW
  1057. /////////////////////////////////////////////////////////////////////////
  1058. NTSTATUS LlsrProductAddA(
  1059. LLS_HANDLE Handle,
  1060. IN LPSTR ProductFamily,
  1061. IN LPSTR Product,
  1062. IN LPSTR Version
  1063. )
  1064. /*++
  1065. Routine Description:
  1066. Arguments:
  1067. Return Value:
  1068. --*/
  1069. {
  1070. #if DBG
  1071. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  1072. dprintf(TEXT("LLS TRACE: LlsProductAddA\n"));
  1073. #endif
  1074. UNREFERENCED_PARAMETER(Handle);
  1075. UNREFERENCED_PARAMETER(ProductFamily);
  1076. UNREFERENCED_PARAMETER(Product);
  1077. UNREFERENCED_PARAMETER(Version);
  1078. return STATUS_NOT_SUPPORTED;
  1079. } // LlsrProductAddA
  1080. /////////////////////////////////////////////////////////////////////////
  1081. NTSTATUS LlsrProductUserEnumW(
  1082. LLS_HANDLE Handle,
  1083. LPWSTR Product,
  1084. PLLS_PRODUCT_USER_ENUM_STRUCTW pProductUserInfo,
  1085. DWORD pPrefMaxLen,
  1086. LPDWORD pTotalEntries,
  1087. LPDWORD pResumeHandle
  1088. )
  1089. /*++
  1090. Routine Description:
  1091. Arguments:
  1092. Return Value:
  1093. --*/
  1094. {
  1095. NTSTATUS Status = STATUS_SUCCESS;
  1096. DWORD Level;
  1097. ULONG RecSize;
  1098. PVOID BufPtr = NULL;
  1099. ULONG BufSize = 0;
  1100. ULONG EntriesRead = 0;
  1101. ULONG TotalEntries = 0;
  1102. ULONG i = 0;
  1103. PUSER_RECORD UserRec = NULL;
  1104. PVOID RestartKey = NULL, RestartKeySave = NULL;
  1105. PSVC_RECORD pService;
  1106. DWORD Flags;
  1107. ULONG j, AccessCount;
  1108. DWORD LastAccess;
  1109. PCLIENT_CONTEXT_TYPE pClient = NULL;
  1110. PVOID *pTableTmp;
  1111. #if DBG
  1112. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  1113. dprintf(TEXT("LLS TRACE: LlsProductUserEnumW\n"));
  1114. #endif
  1115. #if DELAY_INITIALIZATION
  1116. EnsureInitialized();
  1117. #endif
  1118. RtlAcquireResourceShared(&UserListLock, TRUE);
  1119. if ((Product == NULL) || (NULL == pTotalEntries))
  1120. return STATUS_INVALID_PARAMETER;
  1121. *pTotalEntries = 0;
  1122. //
  1123. // Reset Enum to correct place.
  1124. //
  1125. if (pResumeHandle != NULL)
  1126. {
  1127. if (NULL == Handle)
  1128. return STATUS_INVALID_PARAMETER;
  1129. pClient = (PCLIENT_CONTEXT_TYPE) Handle;
  1130. try
  1131. {
  1132. if (0 != memcmp(pClient->Signature,LLS_SIG,LLS_SIG_SIZE))
  1133. {
  1134. return STATUS_INVALID_PARAMETER;
  1135. }
  1136. if (*pResumeHandle != 0)
  1137. {
  1138. if ((NULL == pClient->ProductUserEnumWRestartTable)
  1139. || (*pResumeHandle >= pClient->ProductUserEnumWRestartTableSize))
  1140. {
  1141. return STATUS_INVALID_PARAMETER;
  1142. }
  1143. RestartKey = RestartKeySave = pClient->ProductUserEnumWRestartTable[(*pResumeHandle)-1];
  1144. }
  1145. } except(EXCEPTION_EXECUTE_HANDLER ) {
  1146. Status = GetExceptionCode();
  1147. }
  1148. if (Status != STATUS_SUCCESS)
  1149. {
  1150. return Status;
  1151. }
  1152. }
  1153. UserRec = (PUSER_RECORD) LLSEnumerateGenericTableWithoutSplaying(&UserList, (VOID **) &RestartKey);
  1154. //
  1155. // Get size of each record based on info level. Only 0 and 1 supported.
  1156. //
  1157. Level = pProductUserInfo->Level;
  1158. if (Level == 0)
  1159. {
  1160. if (NULL == pProductUserInfo->LlsProductUserInfo.Level0)
  1161. {
  1162. return STATUS_INVALID_PARAMETER;
  1163. }
  1164. RecSize = sizeof(LLS_PRODUCT_USER_INFO_0);
  1165. }
  1166. else if (Level == 1)
  1167. {
  1168. if (NULL == pProductUserInfo->LlsProductUserInfo.Level1)
  1169. {
  1170. return STATUS_INVALID_PARAMETER;
  1171. }
  1172. RecSize = sizeof(LLS_PRODUCT_USER_INFO_1);
  1173. }
  1174. else {
  1175. return STATUS_INVALID_LEVEL;
  1176. }
  1177. //
  1178. // Calculate how many records will fit into PrefMaxLen buffer. This is
  1179. // the record size * # records + space for the string data. If MAX_ULONG
  1180. // is passed in then we return all records.
  1181. //
  1182. if (lstrcmpi(Product, BackOfficeStr))
  1183. while ((UserRec != NULL) && (BufSize < pPrefMaxLen)) {
  1184. if ( !(UserRec->Flags & LLS_FLAG_DELETED) ) {
  1185. RtlEnterCriticalSection(&UserRec->ServiceTableLock);
  1186. pService = SvcListFind( Product, UserRec->Services, UserRec->ServiceTableSize );
  1187. RtlLeaveCriticalSection(&UserRec->ServiceTableLock);
  1188. if (pService != NULL) {
  1189. BufSize += RecSize;
  1190. EntriesRead++;
  1191. }
  1192. }
  1193. // Get next record
  1194. UserRec = (PUSER_RECORD) LLSEnumerateGenericTableWithoutSplaying(&UserList, (VOID **) &RestartKey);
  1195. }
  1196. else
  1197. while ((UserRec != NULL) && (BufSize < pPrefMaxLen)) {
  1198. if (UserRec->Mapping != NULL)
  1199. Flags = UserRec->Mapping->Flags;
  1200. else
  1201. Flags = UserRec->Flags;
  1202. if (!(UserRec->Flags & LLS_FLAG_DELETED))
  1203. if (Flags & LLS_FLAG_SUITE_USE) {
  1204. BufSize += RecSize;
  1205. EntriesRead++;
  1206. }
  1207. // Get next record
  1208. UserRec = (PUSER_RECORD) LLSEnumerateGenericTableWithoutSplaying(&UserList, (VOID **) &RestartKey);
  1209. }
  1210. TotalEntries = EntriesRead;
  1211. //
  1212. // If we overflowed the buffer then back up one record.
  1213. //
  1214. if (BufSize > pPrefMaxLen) {
  1215. BufSize -= RecSize;
  1216. EntriesRead--;
  1217. }
  1218. if (UserRec != NULL)
  1219. Status = STATUS_MORE_ENTRIES;
  1220. //
  1221. // Now walk to the end of the list to see how many more records are still
  1222. // available.
  1223. //
  1224. while (UserRec != NULL) {
  1225. TotalEntries++;
  1226. UserRec = (PUSER_RECORD) LLSEnumerateGenericTableWithoutSplaying(&UserList, (VOID **) &RestartKey);
  1227. }
  1228. //
  1229. // Reset Enum to correct place.
  1230. //
  1231. RestartKey = RestartKeySave;
  1232. UserRec = (PUSER_RECORD) LLSEnumerateGenericTableWithoutSplaying(&UserList, (VOID **) &RestartKey);
  1233. //
  1234. // We now know how many records will fit into the buffer, so allocate space
  1235. // and fix up pointers so we can copy the information.
  1236. //
  1237. BufPtr = MIDL_user_allocate(BufSize);
  1238. if (BufPtr == NULL) {
  1239. Status = STATUS_NO_MEMORY;
  1240. goto LlsrProductUserEnumWExit;
  1241. }
  1242. RtlZeroMemory((PVOID) BufPtr, BufSize);
  1243. //
  1244. // Buffers are all setup, so loop through records and copy the data.
  1245. //
  1246. if (lstrcmpi(Product, BackOfficeStr))
  1247. while ((i < EntriesRead) && (UserRec != NULL)) {
  1248. if (!(UserRec->Flags & LLS_FLAG_DELETED)) {
  1249. RtlEnterCriticalSection(&UserRec->ServiceTableLock);
  1250. pService = SvcListFind( Product, UserRec->Services, UserRec->ServiceTableSize );
  1251. if (pService != NULL) {
  1252. if (Level == 0)
  1253. ((PLLS_PRODUCT_USER_INFO_0) BufPtr)[i].User = (LPTSTR) UserRec->UserID;
  1254. else {
  1255. ((PLLS_PRODUCT_USER_INFO_1) BufPtr)[i].User = (LPTSTR) UserRec->UserID;
  1256. ((PLLS_PRODUCT_USER_INFO_1) BufPtr)[i].Flags = pService->Flags;
  1257. ((PLLS_PRODUCT_USER_INFO_1) BufPtr)[i].LastUsed = pService->LastAccess;
  1258. ((PLLS_PRODUCT_USER_INFO_1) BufPtr)[i].UsageCount = pService->AccessCount;
  1259. }
  1260. i++;
  1261. }
  1262. RtlLeaveCriticalSection(&UserRec->ServiceTableLock);
  1263. }
  1264. UserRec = (PUSER_RECORD) LLSEnumerateGenericTableWithoutSplaying(&UserList, (VOID **) &RestartKey);
  1265. }
  1266. else
  1267. while ((i < EntriesRead) && (UserRec != NULL)) {
  1268. if (!(UserRec->Flags & LLS_FLAG_DELETED)) {
  1269. if (UserRec->Mapping != NULL)
  1270. Flags = UserRec->Mapping->Flags;
  1271. else
  1272. Flags = UserRec->Flags;
  1273. if (!(UserRec->Flags & LLS_FLAG_DELETED))
  1274. if (Flags & LLS_FLAG_SUITE_USE) {
  1275. AccessCount = 0;
  1276. LastAccess = 0;
  1277. RtlEnterCriticalSection(&UserRec->ServiceTableLock);
  1278. for (j = 0; j < UserRec->ServiceTableSize; j++) {
  1279. if (UserRec->Services[j].LastAccess > LastAccess)
  1280. LastAccess = UserRec->Services[j].LastAccess;
  1281. if (UserRec->Services[j].AccessCount > AccessCount)
  1282. AccessCount = UserRec->Services[j].AccessCount;
  1283. }
  1284. RtlLeaveCriticalSection(&UserRec->ServiceTableLock);
  1285. if (Level == 0)
  1286. ((PLLS_PRODUCT_USER_INFO_0) BufPtr)[i].User = (LPTSTR) UserRec->UserID;
  1287. else {
  1288. ((PLLS_PRODUCT_USER_INFO_1) BufPtr)[i].User = (LPTSTR) UserRec->UserID;
  1289. ((PLLS_PRODUCT_USER_INFO_1) BufPtr)[i].Flags = UserRec->Flags;
  1290. ((PLLS_PRODUCT_USER_INFO_1) BufPtr)[i].LastUsed = LastAccess;
  1291. ((PLLS_PRODUCT_USER_INFO_1) BufPtr)[i].UsageCount = AccessCount;
  1292. }
  1293. i++;
  1294. }
  1295. }
  1296. UserRec = (PUSER_RECORD) LLSEnumerateGenericTableWithoutSplaying(&UserList, (VOID **) &RestartKey);
  1297. }
  1298. LlsrProductUserEnumWExit:
  1299. #if DBG
  1300. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  1301. dprintf(TEXT(" TotalEntries: %lu EntriesRead: %lu ResumeHandle: 0x%lX\n"), TotalEntries, EntriesRead, RestartKey);
  1302. #endif
  1303. *pTotalEntries = TotalEntries;
  1304. if (pResumeHandle != NULL)
  1305. {
  1306. try
  1307. {
  1308. if (NULL == pClient->ProductUserEnumWRestartTable)
  1309. {
  1310. pTableTmp = (PVOID *) LocalAlloc(LPTR,sizeof(PVOID));
  1311. } else
  1312. {
  1313. pTableTmp = (PVOID *) LocalReAlloc(pClient->ProductUserEnumWRestartTable,sizeof(PVOID) * (pClient->ProductUserEnumWRestartTableSize + 1),LHND);
  1314. }
  1315. if (NULL == pTableTmp)
  1316. {
  1317. if (BufPtr != NULL)
  1318. {
  1319. MIDL_user_free(BufPtr);
  1320. }
  1321. return STATUS_NO_MEMORY;
  1322. } else {
  1323. pClient->ProductUserEnumWRestartTable = pTableTmp;
  1324. }
  1325. pClient->ProductUserEnumWRestartTable[pClient->ProductUserEnumWRestartTableSize++] = RestartKey;
  1326. *pResumeHandle = pClient->ProductUserEnumWRestartTableSize;
  1327. } except(EXCEPTION_EXECUTE_HANDLER ) {
  1328. Status = GetExceptionCode();
  1329. }
  1330. if (Status != STATUS_SUCCESS)
  1331. return Status;
  1332. }
  1333. pProductUserInfo->LlsProductUserInfo.Level0->EntriesRead = EntriesRead;
  1334. pProductUserInfo->LlsProductUserInfo.Level0->Buffer = (PLLS_PRODUCT_USER_INFO_0W) BufPtr;
  1335. return Status;
  1336. } // LlsrProductUserEnumW
  1337. void LlsrProductUserEnumW_notify_flag(
  1338. boolean fNotify
  1339. )
  1340. {
  1341. if (fNotify)
  1342. {
  1343. RtlReleaseResource(&UserListLock);
  1344. }
  1345. }
  1346. /////////////////////////////////////////////////////////////////////////
  1347. NTSTATUS LlsrProductUserEnumA(
  1348. LLS_HANDLE Handle,
  1349. LPSTR Product,
  1350. PLLS_PRODUCT_USER_ENUM_STRUCTA ProductUserInfo,
  1351. DWORD PrefMaxLen,
  1352. LPDWORD TotalEntries,
  1353. LPDWORD ResumeHandle
  1354. )
  1355. /*++
  1356. Routine Description:
  1357. Arguments:
  1358. Return Value:
  1359. --*/
  1360. {
  1361. #if DBG
  1362. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  1363. dprintf(TEXT("LLS TRACE: LlsProductUserEnumA\n"));
  1364. #endif
  1365. UNREFERENCED_PARAMETER(Handle);
  1366. UNREFERENCED_PARAMETER(Product);
  1367. UNREFERENCED_PARAMETER(ProductUserInfo);
  1368. UNREFERENCED_PARAMETER(PrefMaxLen);
  1369. UNREFERENCED_PARAMETER(ResumeHandle);
  1370. if (NULL == TotalEntries)
  1371. {
  1372. return STATUS_INVALID_PARAMETER;
  1373. }
  1374. *TotalEntries = 0;
  1375. return STATUS_NOT_SUPPORTED;
  1376. } // LlsrProductUserEnumA
  1377. /////////////////////////////////////////////////////////////////////////
  1378. NTSTATUS LlsrProductServerEnumW(
  1379. LLS_HANDLE Handle,
  1380. LPTSTR Product,
  1381. PLLS_SERVER_PRODUCT_ENUM_STRUCTW pProductServerInfo,
  1382. DWORD pPrefMaxLen,
  1383. LPDWORD pTotalEntries,
  1384. LPDWORD pResumeHandle
  1385. )
  1386. /*++
  1387. Routine Description:
  1388. Arguments:
  1389. Return Value:
  1390. --*/
  1391. {
  1392. NTSTATUS Status = STATUS_SUCCESS;
  1393. DWORD Level;
  1394. ULONG RecSize;
  1395. PVOID BufPtr = NULL;
  1396. ULONG BufSize = 0;
  1397. ULONG EntriesRead = 0;
  1398. ULONG TotalEntries = 0;
  1399. ULONG i = 0;
  1400. ULONG j;
  1401. ULONG RestartKey = 0;
  1402. PSERVER_SERVICE_RECORD pSvc;
  1403. UNREFERENCED_PARAMETER(Handle);
  1404. UNREFERENCED_PARAMETER(pPrefMaxLen);
  1405. #if DBG
  1406. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  1407. dprintf(TEXT("LLS TRACE: LlsProductServerEnumW\n"));
  1408. #endif
  1409. #if DELAY_INITIALIZATION
  1410. EnsureInitialized();
  1411. #endif
  1412. RtlAcquireResourceShared(&ServerListLock, TRUE);
  1413. if ((Product == NULL) || (NULL == pTotalEntries) || (NULL == pProductServerInfo))
  1414. return STATUS_INVALID_PARAMETER;
  1415. *pTotalEntries = 0;
  1416. //
  1417. // Reset Enum to correct place.
  1418. //
  1419. RestartKey = (ULONG) (pResumeHandle != NULL) ? *pResumeHandle : 0;
  1420. //
  1421. // Get size of each record based on info level. Only 0 and 1 supported.
  1422. //
  1423. Level = pProductServerInfo->Level;
  1424. if (Level == 0)
  1425. {
  1426. if (pProductServerInfo->LlsServerProductInfo.Level0 == NULL)
  1427. {
  1428. return STATUS_INVALID_PARAMETER;
  1429. }
  1430. RecSize = sizeof(LLS_SERVER_PRODUCT_INFO_0);
  1431. }
  1432. else if (Level == 1)
  1433. {
  1434. if (pProductServerInfo->LlsServerProductInfo.Level1 == NULL)
  1435. {
  1436. return STATUS_INVALID_PARAMETER;
  1437. }
  1438. RecSize = sizeof(LLS_SERVER_PRODUCT_INFO_1);
  1439. }
  1440. else {
  1441. return STATUS_INVALID_LEVEL;
  1442. }
  1443. //
  1444. // Calculate how many records will fit into PrefMaxLen buffer. This is
  1445. // the record size * # records + space for the string data. If MAX_ULONG
  1446. // is passed in then we return all records.
  1447. //
  1448. RtlAcquireResourceShared(&MasterServiceListLock,TRUE); // required for ServerServiceListFind
  1449. for (i = RestartKey; i < ServerListSize; i++) {
  1450. pSvc = ServerServiceListFind( Product, ServerList[i]->ServiceTableSize, ServerList[i]->Services );
  1451. if (pSvc != NULL) {
  1452. BufSize += RecSize;
  1453. EntriesRead++;
  1454. }
  1455. }
  1456. RtlReleaseResource(&MasterServiceListLock);
  1457. TotalEntries = EntriesRead;
  1458. //
  1459. // We now know how many records will fit into the buffer, so allocate space
  1460. // and fix up pointers so we can copy the information.
  1461. //
  1462. BufPtr = MIDL_user_allocate(BufSize);
  1463. if (BufPtr == NULL) {
  1464. Status = STATUS_NO_MEMORY;
  1465. goto LlsrProductServerEnumWExit;
  1466. }
  1467. RtlZeroMemory((PVOID) BufPtr, BufSize);
  1468. //
  1469. // Buffers are all setup, so loop through records and copy the data.
  1470. //
  1471. j = 0;
  1472. RtlAcquireResourceShared(&MasterServiceListLock,TRUE); // required for ServerServiceListFind
  1473. for (i = RestartKey; i < ServerListSize; i++) {
  1474. pSvc = ServerServiceListFind( Product, ServerList[i]->ServiceTableSize, ServerList[i]->Services );
  1475. if (pSvc != NULL) {
  1476. if (Level == 0)
  1477. ((PLLS_SERVER_PRODUCT_INFO_0) BufPtr)[j].Name = ServerList[i]->Name;
  1478. else {
  1479. ((PLLS_SERVER_PRODUCT_INFO_1) BufPtr)[j].Name = ServerList[i]->Name;
  1480. ((PLLS_SERVER_PRODUCT_INFO_1) BufPtr)[j].Flags = pSvc->Flags;
  1481. ((PLLS_SERVER_PRODUCT_INFO_1) BufPtr)[j].MaxUses = pSvc->MaxSessionCount;
  1482. ((PLLS_SERVER_PRODUCT_INFO_1) BufPtr)[j].MaxSetUses = pSvc->MaxSetSessionCount;
  1483. ((PLLS_SERVER_PRODUCT_INFO_1) BufPtr)[j].HighMark = pSvc->HighMark;
  1484. }
  1485. j++;
  1486. }
  1487. }
  1488. RtlReleaseResource(&MasterServiceListLock);
  1489. LlsrProductServerEnumWExit:
  1490. #if DBG
  1491. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  1492. dprintf(TEXT(" TotalEntries: %lu EntriesRead: %lu ResumeHandle: 0x%lX\n"), TotalEntries, EntriesRead, RestartKey);
  1493. #endif
  1494. *pTotalEntries = TotalEntries;
  1495. if (pResumeHandle != NULL)
  1496. *pResumeHandle = (ULONG) RestartKey;
  1497. pProductServerInfo->LlsServerProductInfo.Level0->EntriesRead = EntriesRead;
  1498. pProductServerInfo->LlsServerProductInfo.Level0->Buffer = (PLLS_SERVER_PRODUCT_INFO_0W) BufPtr;
  1499. return Status;
  1500. } // LlsrProductServerEnumW
  1501. void LlsrProductServerEnumW_notify_flag(
  1502. boolean fNotify
  1503. )
  1504. {
  1505. if (fNotify)
  1506. {
  1507. RtlReleaseResource(&ServerListLock);
  1508. }
  1509. }
  1510. /////////////////////////////////////////////////////////////////////////
  1511. NTSTATUS LlsrProductServerEnumA(
  1512. LLS_HANDLE Handle,
  1513. LPSTR Product,
  1514. PLLS_SERVER_PRODUCT_ENUM_STRUCTA ProductServerInfo,
  1515. DWORD PrefMaxLen,
  1516. LPDWORD TotalEntries,
  1517. LPDWORD ResumeHandle
  1518. )
  1519. /*++
  1520. Routine Description:
  1521. Arguments:
  1522. Return Value:
  1523. --*/
  1524. {
  1525. #if DBG
  1526. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  1527. dprintf(TEXT("LLS TRACE: LlsProductServerEnumA\n"));
  1528. #endif
  1529. UNREFERENCED_PARAMETER(Handle);
  1530. UNREFERENCED_PARAMETER(Product);
  1531. UNREFERENCED_PARAMETER(ProductServerInfo);
  1532. UNREFERENCED_PARAMETER(PrefMaxLen);
  1533. UNREFERENCED_PARAMETER(ResumeHandle);
  1534. if (NULL == TotalEntries)
  1535. {
  1536. return STATUS_INVALID_PARAMETER;
  1537. }
  1538. *TotalEntries = 0;
  1539. return STATUS_NOT_SUPPORTED;
  1540. } // LlsrProductServerEnumA
  1541. /////////////////////////////////////////////////////////////////////////
  1542. NTSTATUS LlsrProductLicenseEnumW(
  1543. LLS_HANDLE Handle,
  1544. LPWSTR Product,
  1545. PLLS_PRODUCT_LICENSE_ENUM_STRUCTW pProductLicenseInfo,
  1546. DWORD pPrefMaxLen,
  1547. LPDWORD pTotalEntries,
  1548. LPDWORD pResumeHandle
  1549. )
  1550. /*++
  1551. Routine Description:
  1552. Arguments:
  1553. Return Value:
  1554. --*/
  1555. {
  1556. NTSTATUS Status = STATUS_SUCCESS;
  1557. DWORD Level;
  1558. PVOID BufPtr = NULL;
  1559. ULONG BufSize = 0;
  1560. ULONG EntriesRead = 0;
  1561. ULONG TotalEntries = 0;
  1562. ULONG i = 0;
  1563. ULONG j = 0;
  1564. DWORD RecordSize;
  1565. #if DBG
  1566. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  1567. dprintf(TEXT("LLS TRACE: LlsProductLicenseEnumW\n"));
  1568. #endif
  1569. UNREFERENCED_PARAMETER(Handle);
  1570. #if DELAY_INITIALIZATION
  1571. EnsureInitialized();
  1572. #endif
  1573. //
  1574. // Need to scan list so get read access.
  1575. //
  1576. RtlAcquireResourceShared(&LicenseListLock, TRUE);
  1577. if ((NULL == pTotalEntries) || (NULL == pProductLicenseInfo))
  1578. {
  1579. return STATUS_INVALID_PARAMETER;
  1580. }
  1581. Level = pProductLicenseInfo->Level;
  1582. *pTotalEntries = 0;
  1583. if ( 0 == Level )
  1584. {
  1585. if (NULL == pProductLicenseInfo->LlsProductLicenseInfo.Level0)
  1586. {
  1587. return STATUS_INVALID_PARAMETER;
  1588. }
  1589. RecordSize = sizeof( LLS_PRODUCT_LICENSE_INFO_0W );
  1590. }
  1591. else if ( 1 == Level )
  1592. {
  1593. if (NULL == pProductLicenseInfo->LlsProductLicenseInfo.Level1)
  1594. {
  1595. return STATUS_INVALID_PARAMETER;
  1596. }
  1597. RecordSize = sizeof( LLS_PRODUCT_LICENSE_INFO_1W );
  1598. }
  1599. else
  1600. {
  1601. return STATUS_INVALID_LEVEL;
  1602. }
  1603. //
  1604. // Calculate how many records will fit into PrefMaxLen buffer.
  1605. //
  1606. i = (pResumeHandle != NULL) ? *pResumeHandle : 0;
  1607. while ( ( i < PurchaseListSize ) && ( BufSize < pPrefMaxLen ) )
  1608. {
  1609. // level 0 enums return only per seat licenses for backwards compatibility
  1610. if ( ( ( ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SEAT )
  1611. && !lstrcmpi( PurchaseList[i].Service->ServiceName, Product ) )
  1612. || ( ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SERVER )
  1613. && !lstrcmpi( PurchaseList[i].PerServerService->ServiceName, Product ) ) )
  1614. && ( ( Level > 0 )
  1615. || ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SEAT ) ) )
  1616. {
  1617. BufSize += RecordSize;
  1618. EntriesRead++;
  1619. }
  1620. i++;
  1621. }
  1622. TotalEntries = EntriesRead;
  1623. //
  1624. // If we overflowed the buffer then back up one record.
  1625. //
  1626. if (BufSize > pPrefMaxLen)
  1627. {
  1628. BufSize -= RecordSize;
  1629. EntriesRead--;
  1630. }
  1631. //
  1632. // Now walk to the end of the list to see how many more records are still
  1633. // available.
  1634. //
  1635. while ( i < PurchaseListSize )
  1636. {
  1637. if ( ( ( ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SEAT )
  1638. && !lstrcmpi( PurchaseList[i].Service->ServiceName, Product ) )
  1639. || ( ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SERVER )
  1640. && !lstrcmpi( PurchaseList[i].PerServerService->ServiceName, Product ) ) )
  1641. && ( ( Level > 0 )
  1642. || ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SEAT ) ) )
  1643. {
  1644. TotalEntries++;
  1645. }
  1646. i++;
  1647. }
  1648. if (TotalEntries > EntriesRead)
  1649. Status = STATUS_MORE_ENTRIES;
  1650. //
  1651. // Reset Enum to correct place.
  1652. //
  1653. i = (pResumeHandle != NULL) ? *pResumeHandle : 0;
  1654. //
  1655. // We now know how many records will fit into the buffer, so allocate space
  1656. // and fix up pointers so we can copy the information.
  1657. //
  1658. BufPtr = MIDL_user_allocate(BufSize);
  1659. if (BufPtr == NULL) {
  1660. Status = STATUS_NO_MEMORY;
  1661. goto LlsrLicenseEnumWExit;
  1662. }
  1663. RtlZeroMemory((PVOID) BufPtr, BufSize);
  1664. //
  1665. // Buffers are all setup, so loop through records and copy the data.
  1666. //
  1667. while ((j < EntriesRead) && (i < PurchaseListSize))
  1668. {
  1669. if ( ( ( ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SEAT )
  1670. && !lstrcmpi( PurchaseList[i].Service->ServiceName, Product ) )
  1671. || ( ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SERVER )
  1672. && !lstrcmpi( PurchaseList[i].PerServerService->ServiceName, Product ) ) )
  1673. && ( ( Level > 0 )
  1674. || ( PurchaseList[i].AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SEAT ) ) )
  1675. {
  1676. if ( 0 == Level )
  1677. {
  1678. ((PLLS_PRODUCT_LICENSE_INFO_0W) BufPtr)[j].Quantity = PurchaseList[i].NumberLicenses;
  1679. ((PLLS_PRODUCT_LICENSE_INFO_0W) BufPtr)[j].Date = PurchaseList[i].Date;
  1680. ((PLLS_PRODUCT_LICENSE_INFO_0W) BufPtr)[j].Admin = PurchaseList[i].Admin;
  1681. ((PLLS_PRODUCT_LICENSE_INFO_0W) BufPtr)[j].Comment = PurchaseList[i].Comment;
  1682. }
  1683. else
  1684. {
  1685. ((PLLS_PRODUCT_LICENSE_INFO_1W) BufPtr)[j].Quantity = PurchaseList[i].NumberLicenses;
  1686. ((PLLS_PRODUCT_LICENSE_INFO_1W) BufPtr)[j].MaxQuantity = PurchaseList[i].MaxQuantity;
  1687. ((PLLS_PRODUCT_LICENSE_INFO_1W) BufPtr)[j].Date = PurchaseList[i].Date;
  1688. ((PLLS_PRODUCT_LICENSE_INFO_1W) BufPtr)[j].Admin = PurchaseList[i].Admin;
  1689. ((PLLS_PRODUCT_LICENSE_INFO_1W) BufPtr)[j].Comment = PurchaseList[i].Comment;
  1690. ((PLLS_PRODUCT_LICENSE_INFO_1W) BufPtr)[j].AllowedModes = PurchaseList[i].AllowedModes;
  1691. ((PLLS_PRODUCT_LICENSE_INFO_1W) BufPtr)[j].CertificateID = PurchaseList[i].CertificateID;
  1692. ((PLLS_PRODUCT_LICENSE_INFO_1W) BufPtr)[j].Source = PurchaseList[i].Source;
  1693. ((PLLS_PRODUCT_LICENSE_INFO_1W) BufPtr)[j].ExpirationDate = PurchaseList[i].ExpirationDate;
  1694. memcpy( ((PLLS_PRODUCT_LICENSE_INFO_1W) BufPtr)[j].Secrets, PurchaseList[i].Secrets, LLS_NUM_SECRETS * sizeof( *PurchaseList[i].Secrets ) );
  1695. }
  1696. j++;
  1697. }
  1698. i++;
  1699. }
  1700. LlsrLicenseEnumWExit:
  1701. #if DBG
  1702. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  1703. dprintf(TEXT(" TotalEntries: %lu EntriesRead: %lu ResumeHandle: 0x%lX\n"), TotalEntries, EntriesRead, i);
  1704. #endif
  1705. *pTotalEntries = TotalEntries;
  1706. if (pResumeHandle != NULL)
  1707. *pResumeHandle = (ULONG) i;
  1708. if ( 0 == Level )
  1709. {
  1710. pProductLicenseInfo->LlsProductLicenseInfo.Level0->EntriesRead = EntriesRead;
  1711. pProductLicenseInfo->LlsProductLicenseInfo.Level0->Buffer = (PLLS_PRODUCT_LICENSE_INFO_0W) BufPtr;
  1712. }
  1713. else
  1714. {
  1715. pProductLicenseInfo->LlsProductLicenseInfo.Level1->EntriesRead = EntriesRead;
  1716. pProductLicenseInfo->LlsProductLicenseInfo.Level1->Buffer = (PLLS_PRODUCT_LICENSE_INFO_1W) BufPtr;
  1717. }
  1718. return Status;
  1719. } // LlsrProductLicenseEnumW
  1720. void LlsrProductLicenseEnumW_notify_flag(
  1721. boolean fNotify
  1722. )
  1723. {
  1724. if (fNotify)
  1725. {
  1726. RtlReleaseResource(&LicenseListLock);
  1727. }
  1728. }
  1729. /////////////////////////////////////////////////////////////////////////
  1730. NTSTATUS LlsrProductLicenseEnumA(
  1731. LLS_HANDLE Handle,
  1732. LPSTR Product,
  1733. PLLS_PRODUCT_LICENSE_ENUM_STRUCTA ProductLicenseInfo,
  1734. DWORD PrefMaxLen,
  1735. LPDWORD TotalEntries,
  1736. LPDWORD ResumeHandle
  1737. )
  1738. /*++
  1739. Routine Description:
  1740. Arguments:
  1741. Return Value:
  1742. --*/
  1743. {
  1744. #if DBG
  1745. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  1746. dprintf(TEXT("LLS TRACE: LlsProductLicenseEnumA\n"));
  1747. #endif
  1748. UNREFERENCED_PARAMETER(Handle);
  1749. UNREFERENCED_PARAMETER(Product);
  1750. UNREFERENCED_PARAMETER(ProductLicenseInfo);
  1751. UNREFERENCED_PARAMETER(PrefMaxLen);
  1752. UNREFERENCED_PARAMETER(ResumeHandle);
  1753. //swi, code review, why bother to validate input? It returns not supported anyway.
  1754. if (NULL == TotalEntries)
  1755. {
  1756. return STATUS_INVALID_PARAMETER;
  1757. }
  1758. *TotalEntries = 0;
  1759. return STATUS_NOT_SUPPORTED;
  1760. } // LlsrProductLicenseEnumA
  1761. /////////////////////////////////////////////////////////////////////////
  1762. NTSTATUS LlsrUserEnumW(
  1763. LLS_HANDLE Handle,
  1764. PLLS_USER_ENUM_STRUCTW pUserInfo,
  1765. DWORD pPrefMaxLen,
  1766. LPDWORD pTotalEntries,
  1767. LPDWORD pResumeHandle
  1768. )
  1769. /*++
  1770. Routine Description:
  1771. Arguments:
  1772. pPrefMaxLen - Supplies the number of bytes of information to return
  1773. in the buffer. If this value is MAXULONG, all available information
  1774. will be returned.
  1775. pTotalEntries - Returns the total number of entries available. This value
  1776. is only valid if the return code is STATUS_SUCCESS or STATUS_MORE_ENTRIES.
  1777. pResumeHandle - Supplies a handle to resume the enumeration from where it
  1778. left off the last time through. Returns the resume handle if return
  1779. code is STATUS_MORE_ENTRIES.
  1780. Return Value:
  1781. --*/
  1782. {
  1783. NTSTATUS Status = STATUS_SUCCESS;
  1784. DWORD Level;
  1785. ULONG RecSize;
  1786. PVOID BufPtr = NULL;
  1787. ULONG BufSize = 0;
  1788. ULONG EntriesRead = 0;
  1789. ULONG TotalEntries = 0;
  1790. ULONG i = 0;
  1791. ULONG j;
  1792. PUSER_RECORD UserRec = NULL;
  1793. PVOID RestartKey = NULL,RestartKeySave = NULL;
  1794. ULONG StrSize;
  1795. LPTSTR ProductString = NULL;
  1796. PCLIENT_CONTEXT_TYPE pClient = NULL;
  1797. PVOID *pTableTmp;
  1798. HRESULT hr;
  1799. #if DBG
  1800. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  1801. dprintf(TEXT("LLS TRACE: LlsUserEnumW\n"));
  1802. #endif
  1803. #if DELAY_INITIALIZATION
  1804. EnsureInitialized();
  1805. #endif
  1806. //
  1807. // Need AddEnum lock, but just shared UserListLock (as we just read
  1808. // the data).
  1809. //
  1810. RtlAcquireResourceShared(&UserListLock, TRUE);
  1811. if ((NULL == pTotalEntries) || (NULL == pUserInfo))
  1812. {
  1813. return STATUS_INVALID_PARAMETER;
  1814. }
  1815. *pTotalEntries = 0;
  1816. //
  1817. // Reset Enum to correct place.
  1818. //
  1819. if (pResumeHandle != NULL)
  1820. {
  1821. pClient = (PCLIENT_CONTEXT_TYPE) Handle;
  1822. try
  1823. {
  1824. if ((NULL == pClient) || (0 != memcmp(pClient->Signature,LLS_SIG,LLS_SIG_SIZE)))
  1825. {
  1826. return STATUS_INVALID_PARAMETER;
  1827. }
  1828. if (*pResumeHandle != 0)
  1829. {
  1830. if ((NULL == pClient->UserEnumWRestartTable)
  1831. || (*pResumeHandle > pClient->UserEnumWRestartTableSize))
  1832. {
  1833. return STATUS_INVALID_PARAMETER;
  1834. }
  1835. RestartKey = RestartKeySave = pClient->UserEnumWRestartTable[(*pResumeHandle)-1];
  1836. }
  1837. } except(EXCEPTION_EXECUTE_HANDLER ) {
  1838. Status = GetExceptionCode();
  1839. }
  1840. if (Status != STATUS_SUCCESS)
  1841. {
  1842. return Status;
  1843. }
  1844. }
  1845. UserRec = (PUSER_RECORD) LLSEnumerateGenericTableWithoutSplaying(&UserList, (VOID **) &RestartKey);
  1846. //
  1847. // Get size of each record based on info level. Only 0 and 1 supported.
  1848. //
  1849. Level = pUserInfo->Level;
  1850. if (Level == 0)
  1851. {
  1852. if (NULL == pUserInfo->LlsUserInfo.Level0)
  1853. {
  1854. return STATUS_INVALID_PARAMETER;
  1855. }
  1856. RecSize = sizeof(LLS_USER_INFO_0);
  1857. }
  1858. else if (Level == 1)
  1859. {
  1860. if (NULL == pUserInfo->LlsUserInfo.Level1)
  1861. {
  1862. return STATUS_INVALID_PARAMETER;
  1863. }
  1864. RecSize = sizeof(LLS_USER_INFO_1);
  1865. }
  1866. else if (Level == 2)
  1867. {
  1868. if (NULL == pUserInfo->LlsUserInfo.Level2)
  1869. {
  1870. return STATUS_INVALID_PARAMETER;
  1871. }
  1872. RecSize = sizeof(LLS_USER_INFO_2);
  1873. }
  1874. else {
  1875. return STATUS_INVALID_LEVEL;
  1876. }
  1877. //
  1878. // Calculate how many records will fit into PrefMaxLen buffer. This is
  1879. // the record size * # records + space for the string data. If MAX_ULONG
  1880. // is passed in then we return all records.
  1881. //
  1882. while ((UserRec != NULL) && (BufSize < pPrefMaxLen)) {
  1883. if (!(UserRec->Flags & LLS_FLAG_DELETED)) {
  1884. BufSize += RecSize;
  1885. EntriesRead++;
  1886. }
  1887. // Get next record
  1888. UserRec = (PUSER_RECORD) LLSEnumerateGenericTableWithoutSplaying(&UserList, (VOID **) &RestartKey);
  1889. }
  1890. TotalEntries = EntriesRead;
  1891. //
  1892. // If we overflowed the buffer then back up one record.
  1893. //
  1894. if (BufSize > pPrefMaxLen) {
  1895. BufSize -= RecSize;
  1896. EntriesRead--;
  1897. }
  1898. if (UserRec != NULL)
  1899. Status = STATUS_MORE_ENTRIES;
  1900. //
  1901. // Now walk to the end of the list to see how many more records are still
  1902. // available.
  1903. //
  1904. while (UserRec != NULL) {
  1905. TotalEntries++;
  1906. UserRec = (PUSER_RECORD) LLSEnumerateGenericTableWithoutSplaying(&UserList, (VOID **) &RestartKey);
  1907. }
  1908. //
  1909. // Reset Enum to correct place.
  1910. //
  1911. RestartKey = RestartKeySave;
  1912. UserRec = (PUSER_RECORD) LLSEnumerateGenericTableWithoutSplaying(&UserList, (VOID **) &RestartKey);
  1913. //
  1914. // We now know how many records will fit into the buffer, so allocate space
  1915. // and fix up pointers so we can copy the information.
  1916. //
  1917. BufPtr = MIDL_user_allocate(BufSize);
  1918. if (BufPtr == NULL) {
  1919. Status = STATUS_NO_MEMORY;
  1920. goto LlsrUserEnumWExit;
  1921. }
  1922. RtlZeroMemory((PVOID) BufPtr, BufSize);
  1923. //
  1924. // Buffers are all setup, so loop through records and copy the data.
  1925. //
  1926. while ((i < EntriesRead) && (UserRec != NULL)) {
  1927. if (!(UserRec->Flags & LLS_FLAG_DELETED)) {
  1928. if (Level == 0)
  1929. ((PLLS_USER_INFO_0) BufPtr)[i].Name = (LPTSTR) UserRec->UserID;
  1930. else if (Level == 1) {
  1931. ((PLLS_USER_INFO_1) BufPtr)[i].Name = (LPTSTR) UserRec->UserID;
  1932. if (UserRec->Mapping != NULL)
  1933. ((PLLS_USER_INFO_1) BufPtr)[i].Group = UserRec->Mapping->Name;
  1934. else
  1935. ((PLLS_USER_INFO_1) BufPtr)[i].Group = NULL;
  1936. ((PLLS_USER_INFO_1) BufPtr)[i].Licensed = UserRec->LicensedProducts;
  1937. ((PLLS_USER_INFO_1) BufPtr)[i].UnLicensed = UserRec->ServiceTableSize - UserRec->LicensedProducts;
  1938. ((PLLS_USER_INFO_1) BufPtr)[i].Flags = UserRec->Flags;
  1939. } else {
  1940. ((PLLS_USER_INFO_2) BufPtr)[i].Name = (LPTSTR) UserRec->UserID;
  1941. if (UserRec->Mapping != NULL)
  1942. ((PLLS_USER_INFO_2) BufPtr)[i].Group = UserRec->Mapping->Name;
  1943. else
  1944. ((PLLS_USER_INFO_2) BufPtr)[i].Group = NULL;
  1945. ((PLLS_USER_INFO_2) BufPtr)[i].Licensed = UserRec->LicensedProducts;
  1946. ((PLLS_USER_INFO_2) BufPtr)[i].UnLicensed = UserRec->ServiceTableSize - UserRec->LicensedProducts;
  1947. ((PLLS_USER_INFO_2) BufPtr)[i].Flags = UserRec->Flags;
  1948. //
  1949. // Walk product table and build up product string
  1950. //
  1951. RtlEnterCriticalSection(&UserRec->ServiceTableLock);
  1952. StrSize = 0;
  1953. for (j = 0; j < UserRec->ServiceTableSize; j++)
  1954. StrSize += ((lstrlen(UserRec->Services[j].Service->Name) + 2) * sizeof(TCHAR));
  1955. if (StrSize != 0) {
  1956. ProductString = MIDL_user_allocate(StrSize);
  1957. if (ProductString != NULL) {
  1958. hr = StringCbCopy(ProductString, StrSize, TEXT(""));
  1959. ASSERT(SUCCEEDED(hr));
  1960. for (j = 0; j < UserRec->ServiceTableSize; j++) {
  1961. if (j != 0)
  1962. {
  1963. hr = StringCbCat(ProductString, StrSize, TEXT(", "));
  1964. ASSERT(SUCCEEDED(hr));
  1965. }
  1966. hr = StringCbCat(ProductString, StrSize, UserRec->Services[j].Service->Name);
  1967. ASSERT(SUCCEEDED(hr));
  1968. }
  1969. ((PLLS_USER_INFO_2) BufPtr)[i].Products = ProductString;
  1970. }
  1971. }
  1972. if ((StrSize == 0) || (ProductString == NULL)) {
  1973. ProductString = MIDL_user_allocate(2 * sizeof(TCHAR));
  1974. if (ProductString != NULL) {
  1975. hr = StringCchCopy(ProductString, 2, TEXT(""));
  1976. ASSERT(SUCCEEDED(hr));
  1977. ((PLLS_USER_INFO_2) BufPtr)[i].Products = ProductString;
  1978. }
  1979. }
  1980. RtlLeaveCriticalSection(&UserRec->ServiceTableLock);
  1981. }
  1982. i++;
  1983. }
  1984. UserRec = (PUSER_RECORD) LLSEnumerateGenericTableWithoutSplaying(&UserList, (VOID **) &RestartKey);
  1985. }
  1986. LlsrUserEnumWExit:
  1987. #if DBG
  1988. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  1989. dprintf(TEXT(" TotalEntries: %lu EntriesRead: %lu ResumeHandle: 0x%lX\n"), TotalEntries, EntriesRead, RestartKey);
  1990. #endif
  1991. *pTotalEntries = TotalEntries;
  1992. if (NULL != pResumeHandle)
  1993. {
  1994. try
  1995. {
  1996. if (NULL == pClient->UserEnumWRestartTable)
  1997. {
  1998. pTableTmp = (PVOID *) LocalAlloc(LPTR,sizeof(PVOID));
  1999. } else
  2000. {
  2001. pTableTmp = (PVOID *) LocalReAlloc(pClient->UserEnumWRestartTable,sizeof(PVOID) * (pClient->UserEnumWRestartTableSize + 1),LHND);
  2002. }
  2003. if (NULL == pTableTmp)
  2004. {
  2005. if (BufPtr != NULL)
  2006. {
  2007. MIDL_user_free(BufPtr);
  2008. }
  2009. return STATUS_NO_MEMORY;
  2010. } else
  2011. {
  2012. pClient->UserEnumWRestartTable = pTableTmp;
  2013. }
  2014. pClient->UserEnumWRestartTable[pClient->UserEnumWRestartTableSize++] = RestartKey;
  2015. *pResumeHandle = pClient->UserEnumWRestartTableSize;
  2016. } except(EXCEPTION_EXECUTE_HANDLER ) {
  2017. Status = GetExceptionCode();
  2018. }
  2019. if (Status != STATUS_SUCCESS)
  2020. return Status;
  2021. }
  2022. pUserInfo->LlsUserInfo.Level0->EntriesRead = EntriesRead;
  2023. pUserInfo->LlsUserInfo.Level0->Buffer = (PLLS_USER_INFO_0W) BufPtr;
  2024. return Status;
  2025. } // LlsrUserEnumW
  2026. void LlsrUserEnumW_notify_flag(
  2027. boolean fNotify
  2028. )
  2029. {
  2030. if (fNotify)
  2031. {
  2032. RtlReleaseResource(&UserListLock);
  2033. }
  2034. }
  2035. /////////////////////////////////////////////////////////////////////////
  2036. NTSTATUS LlsrUserEnumA(
  2037. LLS_HANDLE Handle,
  2038. PLLS_USER_ENUM_STRUCTA UserInfo,
  2039. DWORD PrefMaxLen,
  2040. LPDWORD TotalEntries,
  2041. LPDWORD ResumeHandle
  2042. )
  2043. /*++
  2044. Routine Description:
  2045. Arguments:
  2046. Return Value:
  2047. --*/
  2048. {
  2049. #if DBG
  2050. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  2051. dprintf(TEXT("LLS TRACE: LlsUserEnumA\n"));
  2052. #endif
  2053. UNREFERENCED_PARAMETER(Handle);
  2054. UNREFERENCED_PARAMETER(UserInfo);
  2055. UNREFERENCED_PARAMETER(PrefMaxLen);
  2056. UNREFERENCED_PARAMETER(ResumeHandle);
  2057. if (NULL == TotalEntries)
  2058. {
  2059. return STATUS_INVALID_PARAMETER;
  2060. }
  2061. *TotalEntries = 0;
  2062. return STATUS_NOT_SUPPORTED;
  2063. } // LlsrUserEnumA
  2064. /////////////////////////////////////////////////////////////////////////
  2065. NTSTATUS LlsrUserInfoGetW(
  2066. LLS_HANDLE Handle,
  2067. LPWSTR User,
  2068. DWORD Level,
  2069. PLLS_USER_INFOW *BufPtr
  2070. )
  2071. /*++
  2072. Routine Description:
  2073. Arguments:
  2074. Return Value:
  2075. --*/
  2076. {
  2077. PUSER_RECORD UserRec = NULL;
  2078. PLLS_USER_INFOW pUser = NULL;
  2079. UNREFERENCED_PARAMETER(Handle);
  2080. #if DBG
  2081. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  2082. dprintf(TEXT("LLS TRACE: LlsUserInfoGetW\n"));
  2083. #endif
  2084. #if DELAY_INITIALIZATION
  2085. EnsureInitialized();
  2086. #endif
  2087. RtlAcquireResourceExclusive(&UserListLock, TRUE);
  2088. if ((User == NULL) || (BufPtr == NULL))
  2089. return STATUS_INVALID_PARAMETER;
  2090. *BufPtr = NULL;
  2091. if (Level != 1)
  2092. return STATUS_INVALID_LEVEL;
  2093. UserRec = UserListFind(User);
  2094. if (UserRec != NULL) {
  2095. pUser = MIDL_user_allocate(sizeof(LLS_USER_INFOW));
  2096. if (pUser != NULL) {
  2097. pUser->UserInfo1.Name = (LPTSTR) UserRec->UserID;
  2098. if (UserRec->Mapping != NULL) {
  2099. pUser->UserInfo1.Mapping = UserRec->Mapping->Name;
  2100. pUser->UserInfo1.Licensed = UserRec->Mapping->Licenses;
  2101. pUser->UserInfo1.UnLicensed = 0;
  2102. } else {
  2103. pUser->UserInfo1.Mapping = NULL;
  2104. pUser->UserInfo1.Licensed = 1;
  2105. pUser->UserInfo1.UnLicensed = 0;
  2106. }
  2107. pUser->UserInfo1.Flags = UserRec->Flags;
  2108. }
  2109. }
  2110. if (UserRec == NULL)
  2111. return STATUS_OBJECT_NAME_NOT_FOUND;
  2112. if (pUser == NULL)
  2113. return STATUS_NO_MEMORY;
  2114. *BufPtr = (PLLS_USER_INFOW) pUser;
  2115. return STATUS_SUCCESS;
  2116. } // LlsrUserInfoGetW
  2117. void LlsrUserInfoGetW_notify_flag(
  2118. boolean fNotify
  2119. )
  2120. {
  2121. if (fNotify)
  2122. {
  2123. RtlReleaseResource(&UserListLock);
  2124. }
  2125. }
  2126. /////////////////////////////////////////////////////////////////////////
  2127. NTSTATUS LlsrUserInfoGetA(
  2128. LLS_HANDLE Handle,
  2129. LPSTR User,
  2130. DWORD Level,
  2131. PLLS_USER_INFOA *BufPtr
  2132. )
  2133. /*++
  2134. Routine Description:
  2135. Arguments:
  2136. Return Value:
  2137. --*/
  2138. {
  2139. #if DBG
  2140. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  2141. dprintf(TEXT("LLS TRACE: LlsUserInfoGetA\n"));
  2142. #endif
  2143. UNREFERENCED_PARAMETER(Handle);
  2144. UNREFERENCED_PARAMETER(User);
  2145. UNREFERENCED_PARAMETER(Level);
  2146. if (NULL == BufPtr)
  2147. {
  2148. return STATUS_INVALID_PARAMETER;
  2149. }
  2150. *BufPtr = NULL;
  2151. return STATUS_NOT_SUPPORTED;
  2152. } // LlsrUserInfoGetA
  2153. /////////////////////////////////////////////////////////////////////////
  2154. NTSTATUS LlsrUserInfoSetW(
  2155. LLS_HANDLE Handle,
  2156. LPWSTR User,
  2157. DWORD Level,
  2158. PLLS_USER_INFOW BufPtr
  2159. )
  2160. /*++
  2161. Routine Description:
  2162. Arguments:
  2163. Return Value:
  2164. --*/
  2165. {
  2166. NTSTATUS Status;
  2167. PUSER_RECORD UserRec = NULL;
  2168. PLLS_USER_INFO_1 pUser;
  2169. UNREFERENCED_PARAMETER(Handle);
  2170. #if DBG
  2171. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  2172. dprintf(TEXT("LLS TRACE: LlsUserInfoSetW\n"));
  2173. #endif
  2174. #if DELAY_INITIALIZATION
  2175. EnsureInitialized();
  2176. #endif
  2177. if (Level != 1)
  2178. {
  2179. Status = STATUS_INVALID_LEVEL;
  2180. goto error;
  2181. }
  2182. if ((User == NULL) || (BufPtr == NULL))
  2183. {
  2184. Status = STATUS_INVALID_PARAMETER;
  2185. goto error;
  2186. }
  2187. RtlAcquireResourceExclusive(&UserListLock, TRUE);
  2188. UserRec = UserListFind(User);
  2189. if (UserRec != NULL) {
  2190. pUser = (PLLS_USER_INFO_1) BufPtr;
  2191. //
  2192. // If in a mapping can't change SUITE_USE, since it is based on the
  2193. // License Group
  2194. //
  2195. if (UserRec->Mapping != NULL) {
  2196. RtlReleaseResource(&UserListLock);
  2197. Status = STATUS_MEMBER_IN_GROUP;
  2198. goto error;
  2199. }
  2200. //
  2201. // Reset SUITE_USE and turn off SUITE_AUTO
  2202. //
  2203. pUser->Flags &= LLS_FLAG_SUITE_USE;
  2204. UserRec->Flags &= ~LLS_FLAG_SUITE_USE;
  2205. UserRec->Flags |= pUser->Flags;
  2206. UserRec->Flags &= ~LLS_FLAG_SUITE_AUTO;
  2207. //
  2208. // Run though and clean up all old licenses
  2209. //
  2210. UserLicenseListFree( UserRec );
  2211. //
  2212. // Now assign new ones
  2213. //
  2214. RtlEnterCriticalSection(&UserRec->ServiceTableLock);
  2215. SvcListLicenseUpdate( UserRec );
  2216. RtlLeaveCriticalSection(&UserRec->ServiceTableLock);
  2217. }
  2218. RtlReleaseResource(&UserListLock);
  2219. if (UserRec == NULL)
  2220. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  2221. else
  2222. Status = LLSDataSave();
  2223. error:
  2224. // note, some internal pointers are defined as dont_free, we should free them here
  2225. if (NULL != BufPtr)
  2226. {
  2227. pUser = (PLLS_USER_INFO_1) BufPtr;
  2228. if (NULL != pUser->Name)
  2229. {
  2230. MIDL_user_free(pUser->Name);
  2231. }
  2232. if (NULL != pUser->Group)
  2233. {
  2234. MIDL_user_free(pUser->Group);
  2235. }
  2236. }
  2237. return Status;
  2238. } // LlsrUserInfoSetW
  2239. /////////////////////////////////////////////////////////////////////////
  2240. NTSTATUS LlsrUserInfoSetA(
  2241. LLS_HANDLE Handle,
  2242. LPSTR User,
  2243. DWORD Level,
  2244. PLLS_USER_INFOA BufPtr
  2245. )
  2246. /*++
  2247. Routine Description:
  2248. Arguments:
  2249. Return Value:
  2250. --*/
  2251. {
  2252. #if DBG
  2253. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  2254. dprintf(TEXT("LLS TRACE: LlsUserInfoSetA\n"));
  2255. #endif
  2256. UNREFERENCED_PARAMETER(Handle);
  2257. UNREFERENCED_PARAMETER(User);
  2258. UNREFERENCED_PARAMETER(Level);
  2259. UNREFERENCED_PARAMETER(BufPtr);
  2260. return STATUS_NOT_SUPPORTED;
  2261. } // LlsrUserInfoSetA
  2262. /////////////////////////////////////////////////////////////////////////
  2263. NTSTATUS LlsrUserDeleteW(
  2264. LLS_HANDLE Handle,
  2265. LPTSTR User
  2266. )
  2267. /*++
  2268. Routine Description:
  2269. Arguments:
  2270. Return Value:
  2271. --*/
  2272. {
  2273. NTSTATUS Status;
  2274. PUSER_RECORD UserRec = NULL;
  2275. UNREFERENCED_PARAMETER(Handle);
  2276. #if DBG
  2277. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  2278. if (User != NULL)
  2279. dprintf(TEXT("LLS TRACE: LlsUserDeleteW: %s\n"), User);
  2280. else
  2281. dprintf(TEXT("LLS TRACE: LlsUserDeleteW: <NULL>\n"));
  2282. #endif
  2283. #if DELAY_INITIALIZATION
  2284. EnsureInitialized();
  2285. #endif
  2286. if (User == NULL)
  2287. return STATUS_INVALID_PARAMETER;
  2288. RtlAcquireResourceExclusive(&UserListLock, TRUE);
  2289. UserRec = UserListFind(User);
  2290. if (UserRec != NULL) {
  2291. UserRec->Flags |= LLS_FLAG_DELETED;
  2292. UsersDeleted = TRUE;
  2293. RtlEnterCriticalSection(&UserRec->ServiceTableLock);
  2294. SvcListLicenseFree(UserRec);
  2295. UserLicenseListFree(UserRec);
  2296. RtlLeaveCriticalSection(&UserRec->ServiceTableLock);
  2297. if (UserRec->Services != NULL)
  2298. LocalFree(UserRec->Services);
  2299. UserRec->Services = NULL;
  2300. UserRec->ServiceTableSize = 0;
  2301. }
  2302. RtlReleaseResource(&UserListLock);
  2303. if (UserRec == NULL)
  2304. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  2305. else
  2306. Status = LLSDataSave();
  2307. return Status;
  2308. } // LlsrUserDeleteW
  2309. /////////////////////////////////////////////////////////////////////////
  2310. NTSTATUS LlsrUserDeleteA(
  2311. LLS_HANDLE Handle,
  2312. LPSTR User
  2313. )
  2314. /*++
  2315. Routine Description:
  2316. Arguments:
  2317. Return Value:
  2318. --*/
  2319. {
  2320. #if DBG
  2321. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  2322. dprintf(TEXT("LLS TRACE: LlsUserDeleteA\n"));
  2323. #endif
  2324. UNREFERENCED_PARAMETER(Handle);
  2325. UNREFERENCED_PARAMETER(User);
  2326. return STATUS_NOT_SUPPORTED;
  2327. } // LlsrUserDeleteA
  2328. /////////////////////////////////////////////////////////////////////////
  2329. NTSTATUS LlsrUserProductEnumW(
  2330. LLS_HANDLE Handle,
  2331. LPWSTR pUser,
  2332. PLLS_USER_PRODUCT_ENUM_STRUCTW pUserProductInfo,
  2333. DWORD pPrefMaxLen,
  2334. LPDWORD pTotalEntries,
  2335. LPDWORD pResumeHandle
  2336. )
  2337. /*++
  2338. Routine Description:
  2339. Arguments:
  2340. Return Value:
  2341. --*/
  2342. {
  2343. NTSTATUS Status = STATUS_SUCCESS;
  2344. DWORD Level;
  2345. ULONG RecSize;
  2346. PVOID BufPtr = NULL;
  2347. ULONG BufSize = 0;
  2348. ULONG EntriesRead = 0;
  2349. ULONG TotalEntries = 0;
  2350. ULONG i = 0;
  2351. ULONG j = 0;
  2352. PUSER_RECORD UserRec = NULL;
  2353. UNREFERENCED_PARAMETER(Handle);
  2354. #if DBG
  2355. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  2356. dprintf(TEXT("LLS TRACE: LlsUserProductEnumW\n"));
  2357. #endif
  2358. #if DELAY_INITIALIZATION
  2359. EnsureInitialized();
  2360. #endif
  2361. //
  2362. // Need to find the user-rec
  2363. //
  2364. RtlAcquireResourceExclusive(&UserListLock, TRUE);
  2365. if ((NULL == pTotalEntries) || (pUser == NULL) || (NULL == pUserProductInfo))
  2366. {
  2367. return STATUS_INVALID_PARAMETER;
  2368. }
  2369. *pTotalEntries = 0;
  2370. //
  2371. // Get size of each record based on info level. Only 0 and 1 supported.
  2372. //
  2373. Level = pUserProductInfo->Level;
  2374. if (Level == 0)
  2375. {
  2376. if (pUserProductInfo->LlsUserProductInfo.Level0 == NULL)
  2377. {
  2378. return STATUS_INVALID_PARAMETER;
  2379. }
  2380. RecSize = sizeof(LLS_USER_PRODUCT_INFO_0);
  2381. }
  2382. else if (Level == 1)
  2383. {
  2384. if (pUserProductInfo->LlsUserProductInfo.Level1 == NULL)
  2385. {
  2386. return STATUS_INVALID_PARAMETER;
  2387. }
  2388. RecSize = sizeof(LLS_USER_PRODUCT_INFO_1);
  2389. }
  2390. else {
  2391. return STATUS_INVALID_LEVEL;
  2392. }
  2393. //
  2394. // Reset Enum to correct place.
  2395. //
  2396. UserRec = UserListFind(pUser);
  2397. if (UserRec == NULL) {
  2398. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  2399. goto LlsrUserProductEnumWExit;
  2400. }
  2401. i = (ULONG) (pResumeHandle != NULL) ? *pResumeHandle : 0;
  2402. RtlEnterCriticalSection(&UserRec->ServiceTableLock);
  2403. //
  2404. // Calculate how many records will fit into PrefMaxLen buffer. This is
  2405. // the record size * # records + space for the string data. If MAX_ULONG
  2406. // is passed in then we return all records.
  2407. //
  2408. while ((i < UserRec->ServiceTableSize) && (BufSize < pPrefMaxLen)) {
  2409. BufSize += RecSize;
  2410. EntriesRead++;
  2411. i++;
  2412. }
  2413. TotalEntries = EntriesRead;
  2414. //
  2415. // If we overflowed the buffer then back up one record.
  2416. //
  2417. if (BufSize > pPrefMaxLen) {
  2418. BufSize -= RecSize;
  2419. EntriesRead--;
  2420. }
  2421. if (i < UserRec->ServiceTableSize)
  2422. Status = STATUS_MORE_ENTRIES;
  2423. //
  2424. // Now walk to the end of the list to see how many more records are still
  2425. // available.
  2426. //
  2427. TotalEntries += (UserRec->ServiceTableSize - i);
  2428. //
  2429. // We now know how many records will fit into the buffer, so allocate space
  2430. // and fix up pointers so we can copy the information.
  2431. //
  2432. BufPtr = MIDL_user_allocate(BufSize);
  2433. if (BufPtr == NULL) {
  2434. Status = STATUS_NO_MEMORY;
  2435. RtlLeaveCriticalSection(&UserRec->ServiceTableLock);
  2436. goto LlsrUserProductEnumWExit;
  2437. }
  2438. RtlZeroMemory((PVOID) BufPtr, BufSize);
  2439. //
  2440. // Buffers are all setup, so loop through records and copy the data.
  2441. //
  2442. j = 0;
  2443. i = (ULONG) (pResumeHandle != NULL) ? *pResumeHandle : 0;
  2444. while ((j < EntriesRead) && (i < UserRec->ServiceTableSize)) {
  2445. if (Level == 0)
  2446. ((PLLS_USER_PRODUCT_INFO_0) BufPtr)[j].Product = UserRec->Services[i].Service->Name;
  2447. else {
  2448. ((PLLS_USER_PRODUCT_INFO_1) BufPtr)[j].Product = UserRec->Services[i].Service->Name;
  2449. ((PLLS_USER_PRODUCT_INFO_1) BufPtr)[j].Flags = UserRec->Services[i].Flags;
  2450. ((PLLS_USER_PRODUCT_INFO_1) BufPtr)[j].LastUsed = UserRec->Services[i].LastAccess;
  2451. ((PLLS_USER_PRODUCT_INFO_1) BufPtr)[j].UsageCount = UserRec->Services[i].AccessCount;
  2452. }
  2453. i++; j++;
  2454. }
  2455. RtlLeaveCriticalSection(&UserRec->ServiceTableLock);
  2456. LlsrUserProductEnumWExit:
  2457. #if DBG
  2458. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  2459. dprintf(TEXT(" TotalEntries: %lu EntriesRead: %lu ResumeHandle: 0x%lX\n"), TotalEntries, EntriesRead, i);
  2460. #endif
  2461. *pTotalEntries = TotalEntries;
  2462. if (pResumeHandle != NULL)
  2463. *pResumeHandle = (ULONG) i;
  2464. pUserProductInfo->LlsUserProductInfo.Level0->EntriesRead = EntriesRead;
  2465. pUserProductInfo->LlsUserProductInfo.Level0->Buffer = (PLLS_USER_PRODUCT_INFO_0W) BufPtr;
  2466. return Status;
  2467. } // LlsrUserProductEnumW
  2468. void LlsrUserProductEnumW_notify_flag(
  2469. boolean fNotify
  2470. )
  2471. {
  2472. if (fNotify)
  2473. {
  2474. RtlReleaseResource(&UserListLock);
  2475. }
  2476. }
  2477. /////////////////////////////////////////////////////////////////////////
  2478. NTSTATUS LlsrUserProductEnumA(
  2479. LLS_HANDLE Handle,
  2480. LPSTR User,
  2481. PLLS_USER_PRODUCT_ENUM_STRUCTA UserProductInfo,
  2482. DWORD PrefMaxLen,
  2483. LPDWORD TotalEntries,
  2484. LPDWORD ResumeHandle
  2485. )
  2486. /*++
  2487. Routine Description:
  2488. Arguments:
  2489. Return Value:
  2490. --*/
  2491. {
  2492. #if DBG
  2493. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  2494. dprintf(TEXT("LLS TRACE: LlsUserProductEnumA\n"));
  2495. #endif
  2496. UNREFERENCED_PARAMETER(Handle);
  2497. UNREFERENCED_PARAMETER(User);
  2498. UNREFERENCED_PARAMETER(UserProductInfo);
  2499. UNREFERENCED_PARAMETER(PrefMaxLen);
  2500. UNREFERENCED_PARAMETER(ResumeHandle);
  2501. if (NULL == TotalEntries)
  2502. {
  2503. return STATUS_INVALID_PARAMETER;
  2504. }
  2505. *TotalEntries = 0;
  2506. return STATUS_NOT_SUPPORTED;
  2507. } // LlsrUserProductEnumA
  2508. /////////////////////////////////////////////////////////////////////////
  2509. NTSTATUS LlsrUserProductDeleteW(
  2510. LLS_HANDLE Handle,
  2511. LPWSTR User,
  2512. LPWSTR Product
  2513. )
  2514. /*++
  2515. Routine Description:
  2516. Arguments:
  2517. Return Value:
  2518. --*/
  2519. {
  2520. NTSTATUS Status;
  2521. UNREFERENCED_PARAMETER(Handle);
  2522. #if DBG
  2523. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  2524. dprintf(TEXT("LLS TRACE: LlsUserProductDeleteW\n"));
  2525. #endif
  2526. #if DELAY_INITIALIZATION
  2527. EnsureInitialized();
  2528. #endif
  2529. if ((User == NULL) || (Product == NULL))
  2530. return STATUS_INVALID_PARAMETER;
  2531. RtlAcquireResourceExclusive(&UserListLock, TRUE);
  2532. Status = SvcListDelete(User, Product);
  2533. RtlReleaseResource(&UserListLock);
  2534. if ( STATUS_SUCCESS == Status )
  2535. {
  2536. // save modified data
  2537. Status = LLSDataSave();
  2538. }
  2539. return Status;
  2540. } // LlsrUserProductDeleteW
  2541. /////////////////////////////////////////////////////////////////////////
  2542. NTSTATUS LlsrUserProductDeleteA(
  2543. LLS_HANDLE Handle,
  2544. LPSTR User,
  2545. LPSTR Product
  2546. )
  2547. /*++
  2548. Routine Description:
  2549. Arguments:
  2550. Return Value:
  2551. --*/
  2552. {
  2553. #if DBG
  2554. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  2555. dprintf(TEXT("LLS TRACE: LlsUserProductDeleteA\n"));
  2556. #endif
  2557. UNREFERENCED_PARAMETER(Handle);
  2558. UNREFERENCED_PARAMETER(User);
  2559. UNREFERENCED_PARAMETER(Product);
  2560. return STATUS_NOT_SUPPORTED;
  2561. } // LlsrUserProductDeleteA
  2562. /////////////////////////////////////////////////////////////////////////
  2563. NTSTATUS LlsrMappingEnumW(
  2564. LLS_HANDLE Handle,
  2565. PLLS_MAPPING_ENUM_STRUCTW pMappingInfo,
  2566. DWORD pPrefMaxLen,
  2567. LPDWORD pTotalEntries,
  2568. LPDWORD pResumeHandle
  2569. )
  2570. /*++
  2571. Routine Description:
  2572. Arguments:
  2573. Return Value:
  2574. --*/
  2575. {
  2576. NTSTATUS Status = STATUS_SUCCESS;
  2577. DWORD Level;
  2578. ULONG RecSize;
  2579. PVOID BufPtr = NULL;
  2580. ULONG BufSize = 0;
  2581. ULONG EntriesRead = 0;
  2582. ULONG TotalEntries = 0;
  2583. ULONG i = 0;
  2584. ULONG j = 0;
  2585. UNREFERENCED_PARAMETER(Handle);
  2586. #if DBG
  2587. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  2588. dprintf(TEXT("LLS TRACE: LlsMappingEnumW\n"));
  2589. #endif
  2590. #if DELAY_INITIALIZATION
  2591. EnsureInitialized();
  2592. #endif
  2593. //
  2594. // Need to scan list so get read access.
  2595. //
  2596. RtlAcquireResourceShared(&MappingListLock, TRUE);
  2597. if ((NULL == pTotalEntries) || (NULL == pMappingInfo))
  2598. {
  2599. return STATUS_INVALID_PARAMETER;
  2600. }
  2601. *pTotalEntries = 0;
  2602. //
  2603. // Get size of each record based on info level. Only 0 and 1 supported.
  2604. //
  2605. Level = pMappingInfo->Level;
  2606. if (Level == 0)
  2607. {
  2608. if (pMappingInfo->LlsMappingInfo.Level0 == NULL)
  2609. {
  2610. return STATUS_INVALID_PARAMETER;
  2611. }
  2612. RecSize = sizeof(LLS_MAPPING_INFO_0W);
  2613. }
  2614. else if (Level == 1)
  2615. {
  2616. if (pMappingInfo->LlsMappingInfo.Level0 == NULL)
  2617. {
  2618. return STATUS_INVALID_PARAMETER;
  2619. }
  2620. RecSize = sizeof(LLS_MAPPING_INFO_1W);
  2621. }
  2622. else {
  2623. return STATUS_INVALID_LEVEL;
  2624. }
  2625. //
  2626. // Calculate how many records will fit into PrefMaxLen buffer. This is
  2627. // the record size * # records + space for the string data. If MAX_ULONG
  2628. // is passed in then we return all records.
  2629. //
  2630. i = (pResumeHandle != NULL) ? *pResumeHandle : 0;
  2631. while ((i < MappingListSize) && (BufSize < pPrefMaxLen)) {
  2632. BufSize += RecSize;
  2633. EntriesRead++;
  2634. i++;
  2635. }
  2636. TotalEntries = EntriesRead;
  2637. //
  2638. // If we overflowed the buffer then back up one record.
  2639. //
  2640. if (BufSize > pPrefMaxLen) {
  2641. BufSize -= RecSize;
  2642. EntriesRead--;
  2643. }
  2644. if (i < MappingListSize)
  2645. Status = STATUS_MORE_ENTRIES;
  2646. //
  2647. // Now walk to the end of the list to see how many more records are still
  2648. // available.
  2649. //
  2650. TotalEntries += (MappingListSize - i);
  2651. //
  2652. // Reset Enum to correct place.
  2653. //
  2654. i = (pResumeHandle != NULL) ? *pResumeHandle : 0;
  2655. //
  2656. // We now know how many records will fit into the buffer, so allocate space
  2657. // and fix up pointers so we can copy the information.
  2658. //
  2659. BufPtr = MIDL_user_allocate(BufSize);
  2660. if (BufPtr == NULL) {
  2661. Status = STATUS_NO_MEMORY;
  2662. goto LlsrMappingEnumWExit;
  2663. }
  2664. RtlZeroMemory((PVOID) BufPtr, BufSize);
  2665. //
  2666. // Buffers are all setup, so loop through records and copy the data.
  2667. //
  2668. j = 0;
  2669. while ((j < EntriesRead) && (i < MappingListSize)) {
  2670. if (Level == 0)
  2671. ((PLLS_GROUP_INFO_0) BufPtr)[j].Name = MappingList[i]->Name;
  2672. else {
  2673. ((PLLS_GROUP_INFO_1) BufPtr)[j].Name = MappingList[i]->Name;
  2674. ((PLLS_GROUP_INFO_1) BufPtr)[j].Comment = MappingList[i]->Comment;
  2675. ((PLLS_GROUP_INFO_1) BufPtr)[j].Licenses = MappingList[i]->Licenses;
  2676. }
  2677. i++; j++;
  2678. }
  2679. LlsrMappingEnumWExit:
  2680. #if DBG
  2681. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  2682. dprintf(TEXT(" TotalEntries: %lu EntriesRead: %lu ResumeHandle: 0x%lX\n"), TotalEntries, EntriesRead, i);
  2683. #endif
  2684. *pTotalEntries = TotalEntries;
  2685. if (pResumeHandle != NULL)
  2686. *pResumeHandle = (ULONG) i;
  2687. if (Level == 0) {
  2688. pMappingInfo->LlsMappingInfo.Level0->EntriesRead = EntriesRead;
  2689. pMappingInfo->LlsMappingInfo.Level0->Buffer = (PLLS_MAPPING_INFO_0W) BufPtr;
  2690. } else {
  2691. pMappingInfo->LlsMappingInfo.Level1->EntriesRead = EntriesRead;
  2692. pMappingInfo->LlsMappingInfo.Level1->Buffer = (PLLS_MAPPING_INFO_1W) BufPtr;
  2693. }
  2694. return Status;
  2695. } // LlsrMappingEnumW
  2696. void LlsrMappingEnumW_notify_flag(
  2697. boolean fNotify
  2698. )
  2699. {
  2700. if (fNotify)
  2701. {
  2702. RtlReleaseResource(&MappingListLock);
  2703. }
  2704. }
  2705. /////////////////////////////////////////////////////////////////////////
  2706. NTSTATUS LlsrMappingEnumA(
  2707. LLS_HANDLE Handle,
  2708. PLLS_MAPPING_ENUM_STRUCTA MappingInfo,
  2709. DWORD PrefMaxLen,
  2710. LPDWORD TotalEntries,
  2711. LPDWORD ResumeHandle
  2712. )
  2713. /*++
  2714. Routine Description:
  2715. Arguments:
  2716. Return Value:
  2717. --*/
  2718. {
  2719. #if DBG
  2720. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  2721. dprintf(TEXT("LLS TRACE: LlsMappingEnumA\n"));
  2722. #endif
  2723. UNREFERENCED_PARAMETER(Handle);
  2724. UNREFERENCED_PARAMETER(MappingInfo);
  2725. UNREFERENCED_PARAMETER(PrefMaxLen);
  2726. UNREFERENCED_PARAMETER(ResumeHandle);
  2727. if (NULL == TotalEntries)
  2728. {
  2729. return STATUS_INVALID_PARAMETER;
  2730. }
  2731. *TotalEntries = 0;
  2732. return STATUS_NOT_SUPPORTED;
  2733. } // LlsrMappingEnumA
  2734. /////////////////////////////////////////////////////////////////////////
  2735. NTSTATUS LlsrMappingInfoGetW(
  2736. LLS_HANDLE Handle,
  2737. LPWSTR Mapping,
  2738. DWORD Level,
  2739. PLLS_MAPPING_INFOW *BufPtr
  2740. )
  2741. /*++
  2742. Routine Description:
  2743. Arguments:
  2744. Return Value:
  2745. --*/
  2746. {
  2747. PMAPPING_RECORD pMapping = NULL;
  2748. PLLS_GROUP_INFO_1 pMap = NULL;
  2749. UNREFERENCED_PARAMETER(Handle);
  2750. #if DBG
  2751. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  2752. dprintf(TEXT("LLS TRACE: LlsMappingInfoGetW\n"));
  2753. #endif
  2754. #if DELAY_INITIALIZATION
  2755. EnsureInitialized();
  2756. #endif
  2757. RtlAcquireResourceShared(&MappingListLock, TRUE);
  2758. if ((Mapping == NULL) || (BufPtr == NULL))
  2759. return STATUS_INVALID_PARAMETER;
  2760. *BufPtr = NULL;
  2761. if (Level != 1)
  2762. return STATUS_INVALID_LEVEL;
  2763. pMapping = MappingListFind(Mapping);
  2764. if (pMapping != NULL) {
  2765. pMap = MIDL_user_allocate(sizeof(LLS_GROUP_INFO_1));
  2766. if (pMap != NULL) {
  2767. pMap->Name = pMapping->Name;
  2768. pMap->Comment = pMapping->Comment;
  2769. pMap->Licenses = pMapping->Licenses;
  2770. }
  2771. }
  2772. if (pMapping == NULL)
  2773. return STATUS_OBJECT_NAME_NOT_FOUND;
  2774. if (pMap == NULL)
  2775. return STATUS_NO_MEMORY;
  2776. *BufPtr = (PLLS_MAPPING_INFOW) pMap;
  2777. return STATUS_SUCCESS;
  2778. } // LlsrMappingInfoGetW
  2779. void LlsrMappingInfoGetW_notify_flag(
  2780. boolean fNotify
  2781. )
  2782. {
  2783. if (fNotify)
  2784. {
  2785. RtlReleaseResource(&MappingListLock);
  2786. }
  2787. }
  2788. /////////////////////////////////////////////////////////////////////////
  2789. NTSTATUS LlsrMappingInfoGetA(
  2790. LLS_HANDLE Handle,
  2791. LPSTR Mapping,
  2792. DWORD Level,
  2793. PLLS_MAPPING_INFOA *BufPtr
  2794. )
  2795. /*++
  2796. Routine Description:
  2797. Arguments:
  2798. Return Value:
  2799. --*/
  2800. {
  2801. #if DBG
  2802. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  2803. dprintf(TEXT("LLS TRACE: LlsMappingInfoGetA\n"));
  2804. #endif
  2805. UNREFERENCED_PARAMETER(Handle);
  2806. UNREFERENCED_PARAMETER(Mapping);
  2807. UNREFERENCED_PARAMETER(Level);
  2808. if (NULL == BufPtr)
  2809. {
  2810. return STATUS_INVALID_PARAMETER;
  2811. }
  2812. *BufPtr = NULL;
  2813. return STATUS_NOT_SUPPORTED;
  2814. } // LlsrMappingInfoGetA
  2815. /////////////////////////////////////////////////////////////////////////
  2816. NTSTATUS LlsrMappingInfoSetW(
  2817. LLS_HANDLE Handle,
  2818. LPWSTR Mapping,
  2819. DWORD Level,
  2820. PLLS_MAPPING_INFOW BufPtr
  2821. )
  2822. /*++
  2823. Routine Description:
  2824. Arguments:
  2825. Return Value:
  2826. --*/
  2827. {
  2828. NTSTATUS Status;
  2829. PMAPPING_RECORD pMapping = NULL;
  2830. PLLS_GROUP_INFO_1 pMap;
  2831. LPTSTR NewComment;
  2832. HRESULT hr;
  2833. size_t cch;
  2834. UNREFERENCED_PARAMETER(Handle);
  2835. #if DBG
  2836. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  2837. dprintf(TEXT("LLS TRACE: LlsMappingInfoSetW\n"));
  2838. #endif
  2839. #if DELAY_INITIALIZATION
  2840. EnsureInitialized();
  2841. #endif
  2842. if (Level != 1)
  2843. return STATUS_INVALID_LEVEL;
  2844. if ((Mapping == NULL) || (BufPtr == NULL))
  2845. return STATUS_INVALID_PARAMETER;
  2846. RtlAcquireResourceExclusive(&UserListLock, TRUE);
  2847. RtlAcquireResourceExclusive(&MappingListLock, TRUE);
  2848. pMapping = MappingListFind(Mapping);
  2849. if (pMapping != NULL) {
  2850. pMap = (PLLS_GROUP_INFO_1) BufPtr;
  2851. //
  2852. // Check if comment has changed
  2853. //
  2854. if (pMap->Comment != NULL)
  2855. if (lstrcmp(pMap->Comment, pMapping->Comment)) {
  2856. cch = lstrlen(pMap->Comment) + 1;
  2857. NewComment = (LPTSTR) LocalAlloc(LPTR, cch * sizeof(TCHAR));
  2858. if (NewComment != NULL) {
  2859. LocalFree(pMapping->Comment);
  2860. pMapping->Comment = NewComment;
  2861. hr = StringCchCopy(pMapping->Comment, cch, pMap->Comment);
  2862. ASSERT(SUCCEEDED(hr));
  2863. }
  2864. }
  2865. if ( pMapping->Licenses != pMap->Licenses )
  2866. {
  2867. MappingLicenseListFree( pMapping );
  2868. pMapping->Licenses = pMap->Licenses;
  2869. MappingLicenseUpdate( pMapping, TRUE );
  2870. }
  2871. }
  2872. RtlReleaseResource(&MappingListLock);
  2873. RtlReleaseResource(&UserListLock);
  2874. if (pMapping == NULL)
  2875. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  2876. else
  2877. Status = MappingListSave();
  2878. return Status;
  2879. } // LlsrMappingInfoSetW
  2880. /////////////////////////////////////////////////////////////////////////
  2881. NTSTATUS LlsrMappingInfoSetA(
  2882. LLS_HANDLE Handle,
  2883. LPSTR Mapping,
  2884. DWORD Level,
  2885. PLLS_MAPPING_INFOA BufPtr
  2886. )
  2887. /*++
  2888. Routine Description:
  2889. Arguments:
  2890. Return Value:
  2891. --*/
  2892. {
  2893. #if DBG
  2894. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  2895. dprintf(TEXT("LLS TRACE: LlsMappingInfoSetA\n"));
  2896. #endif
  2897. UNREFERENCED_PARAMETER(Handle);
  2898. UNREFERENCED_PARAMETER(Mapping);
  2899. UNREFERENCED_PARAMETER(Level);
  2900. UNREFERENCED_PARAMETER(BufPtr);
  2901. return STATUS_NOT_SUPPORTED;
  2902. } // LlsrMappingInfoSetA
  2903. /////////////////////////////////////////////////////////////////////////
  2904. NTSTATUS LlsrMappingUserEnumW(
  2905. LLS_HANDLE Handle,
  2906. LPWSTR Mapping,
  2907. PLLS_USER_ENUM_STRUCTW pMappingUserInfo,
  2908. DWORD pPrefMaxLen,
  2909. LPDWORD pTotalEntries,
  2910. LPDWORD pResumeHandle
  2911. )
  2912. /*++
  2913. Routine Description:
  2914. Arguments:
  2915. Return Value:
  2916. --*/
  2917. {
  2918. NTSTATUS Status = STATUS_SUCCESS;
  2919. PMAPPING_RECORD pMapping;
  2920. DWORD Level;
  2921. PVOID BufPtr = NULL;
  2922. ULONG BufSize = 0;
  2923. ULONG EntriesRead = 0;
  2924. ULONG TotalEntries = 0;
  2925. ULONG i = 0;
  2926. ULONG j = 0;
  2927. UNREFERENCED_PARAMETER(Handle);
  2928. #if DBG
  2929. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  2930. dprintf(TEXT("LLS TRACE: LlsMappingUserEnumW\n"));
  2931. #endif
  2932. #if DELAY_INITIALIZATION
  2933. EnsureInitialized();
  2934. #endif
  2935. //
  2936. // Need to scan list so get read access.
  2937. //
  2938. RtlAcquireResourceShared(&MappingListLock, TRUE);
  2939. if ((NULL == pTotalEntries) || (NULL == pMappingUserInfo))
  2940. {
  2941. return STATUS_INVALID_PARAMETER;
  2942. }
  2943. Level = pMappingUserInfo->Level;
  2944. *pTotalEntries = 0;
  2945. if (Level != 0)
  2946. return STATUS_INVALID_LEVEL;
  2947. if (pMappingUserInfo->LlsUserInfo.Level0 == NULL)
  2948. return STATUS_INVALID_PARAMETER;
  2949. pMapping = MappingListFind(Mapping);
  2950. if (pMapping == NULL) {
  2951. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  2952. goto LlsrMappingUserEnumWExit;
  2953. }
  2954. //
  2955. // Calculate how many records will fit into PrefMaxLen buffer. This is
  2956. // the record size * # records + space for the string data. If MAX_ULONG
  2957. // is passed in then we return all records.
  2958. //
  2959. i = (pResumeHandle != NULL) ? *pResumeHandle : 0;
  2960. while ((i < pMapping->NumMembers) && (BufSize < pPrefMaxLen)) {
  2961. BufSize += sizeof(LLS_USER_INFO_0);
  2962. EntriesRead++;
  2963. i++;
  2964. }
  2965. TotalEntries = EntriesRead;
  2966. //
  2967. // If we overflowed the buffer then back up one record.
  2968. //
  2969. if (BufSize > pPrefMaxLen) {
  2970. BufSize -= sizeof(LLS_USER_INFO_0);
  2971. EntriesRead--;
  2972. }
  2973. if (i < pMapping->NumMembers)
  2974. Status = STATUS_MORE_ENTRIES;
  2975. //
  2976. // Now walk to the end of the list to see how many more records are still
  2977. // available.
  2978. //
  2979. TotalEntries += (pMapping->NumMembers - i);
  2980. //
  2981. // Reset Enum to correct place.
  2982. //
  2983. i = (pResumeHandle != NULL) ? *pResumeHandle : 0;
  2984. //
  2985. // We now know how many records will fit into the buffer, so allocate space
  2986. // and fix up pointers so we can copy the information.
  2987. //
  2988. BufPtr = MIDL_user_allocate(BufSize);
  2989. if (BufPtr == NULL) {
  2990. Status = STATUS_NO_MEMORY;
  2991. goto LlsrMappingUserEnumWExit;
  2992. }
  2993. RtlZeroMemory((PVOID) BufPtr, BufSize);
  2994. //
  2995. // Buffers are all setup, so loop through records and copy the data.
  2996. //
  2997. while ((j < EntriesRead) && (i < pMapping->NumMembers)) {
  2998. ((PLLS_USER_INFO_0) BufPtr)[j].Name = pMapping->Members[i];
  2999. i++; j++;
  3000. }
  3001. LlsrMappingUserEnumWExit:
  3002. #if DBG
  3003. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3004. dprintf(TEXT(" TotalEntries: %lu EntriesRead: %lu ResumeHandle: 0x%lX\n"), TotalEntries, EntriesRead, i);
  3005. #endif
  3006. *pTotalEntries = TotalEntries;
  3007. if (pResumeHandle != NULL)
  3008. *pResumeHandle = (ULONG) i;
  3009. pMappingUserInfo->LlsUserInfo.Level0->EntriesRead = EntriesRead;
  3010. pMappingUserInfo->LlsUserInfo.Level0->Buffer = (PLLS_USER_INFO_0W) BufPtr;
  3011. return Status;
  3012. } // LlsrMappingUserEnumW
  3013. void LlsrMappingUserEnumW_notify_flag(
  3014. boolean fNotify
  3015. )
  3016. {
  3017. if (fNotify)
  3018. {
  3019. RtlReleaseResource(&MappingListLock);
  3020. }
  3021. }
  3022. /////////////////////////////////////////////////////////////////////////
  3023. NTSTATUS LlsrMappingUserEnumA(
  3024. LLS_HANDLE Handle,
  3025. LPSTR Mapping,
  3026. PLLS_USER_ENUM_STRUCTA MappingUserInfo,
  3027. DWORD PrefMaxLen,
  3028. LPDWORD TotalEntries,
  3029. LPDWORD ResumeHandle
  3030. )
  3031. /*++
  3032. Routine Description:
  3033. Arguments:
  3034. Return Value:
  3035. --*/
  3036. {
  3037. #if DBG
  3038. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3039. dprintf(TEXT("LLS TRACE: LlsMappingUserEnumA\n"));
  3040. #endif
  3041. UNREFERENCED_PARAMETER(Handle);
  3042. UNREFERENCED_PARAMETER(Mapping);
  3043. UNREFERENCED_PARAMETER(MappingUserInfo);
  3044. UNREFERENCED_PARAMETER(PrefMaxLen);
  3045. UNREFERENCED_PARAMETER(ResumeHandle);
  3046. if (NULL == TotalEntries)
  3047. {
  3048. return STATUS_INVALID_PARAMETER;
  3049. }
  3050. *TotalEntries = 0;
  3051. return STATUS_NOT_SUPPORTED;
  3052. } // LlsrMappingUserEnumA
  3053. /////////////////////////////////////////////////////////////////////////
  3054. NTSTATUS LlsrMappingUserAddW(
  3055. LLS_HANDLE Handle,
  3056. LPWSTR Mapping,
  3057. LPWSTR User
  3058. )
  3059. /*++
  3060. Routine Description:
  3061. Arguments:
  3062. Return Value:
  3063. --*/
  3064. {
  3065. NTSTATUS Status = STATUS_SUCCESS;
  3066. PUSER_RECORD pUserRec;
  3067. PMAPPING_RECORD pMap;
  3068. UNREFERENCED_PARAMETER(Handle);
  3069. #if DBG
  3070. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3071. dprintf(TEXT("LLS TRACE: LlsMappingUserAddW\n"));
  3072. #endif
  3073. #if DELAY_INITIALIZATION
  3074. EnsureInitialized();
  3075. #endif
  3076. if ((Mapping == NULL) || (User == NULL))
  3077. return STATUS_INVALID_PARAMETER;
  3078. RtlAcquireResourceExclusive(&UserListLock, TRUE);
  3079. RtlAcquireResourceExclusive(&MappingListLock, TRUE);
  3080. pMap = MappingUserListAdd( Mapping, User );
  3081. if (pMap == NULL)
  3082. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  3083. else {
  3084. pUserRec = UserListFind(User);
  3085. if (pUserRec != NULL)
  3086. UserMappingAdd(pMap, pUserRec);
  3087. }
  3088. RtlReleaseResource(&MappingListLock);
  3089. RtlReleaseResource(&UserListLock);
  3090. if (Status == STATUS_SUCCESS)
  3091. {
  3092. Status = MappingListSave();
  3093. if (Status == STATUS_SUCCESS)
  3094. Status = LLSDataSave();
  3095. }
  3096. return Status;
  3097. } // LlsrMappingUserAddW
  3098. /////////////////////////////////////////////////////////////////////////
  3099. NTSTATUS LlsrMappingUserAddA(
  3100. LLS_HANDLE Handle,
  3101. LPSTR Mapping,
  3102. LPSTR User
  3103. )
  3104. /*++
  3105. Routine Description:
  3106. Arguments:
  3107. Return Value:
  3108. --*/
  3109. {
  3110. #if DBG
  3111. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3112. dprintf(TEXT("LLS TRACE: LlsMappingUserAddA\n"));
  3113. #endif
  3114. UNREFERENCED_PARAMETER(Handle);
  3115. UNREFERENCED_PARAMETER(Mapping);
  3116. UNREFERENCED_PARAMETER(User);
  3117. return STATUS_NOT_SUPPORTED;
  3118. } // LlsrMappingUserAddA
  3119. /////////////////////////////////////////////////////////////////////////
  3120. NTSTATUS LlsrMappingUserDeleteW(
  3121. LLS_HANDLE Handle,
  3122. LPWSTR Mapping,
  3123. LPWSTR User
  3124. )
  3125. /*++
  3126. Routine Description:
  3127. Arguments:
  3128. Return Value:
  3129. --*/
  3130. {
  3131. NTSTATUS Status;
  3132. PUSER_RECORD pUser;
  3133. UNREFERENCED_PARAMETER(Handle);
  3134. #if DBG
  3135. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3136. dprintf(TEXT("LLS TRACE: LlsMappingUserDeleteW\n"));
  3137. #endif
  3138. #if DELAY_INITIALIZATION
  3139. EnsureInitialized();
  3140. #endif
  3141. if ((Mapping == NULL) || (User == NULL))
  3142. return STATUS_INVALID_PARAMETER;
  3143. RtlAcquireResourceExclusive(&MappingListLock, TRUE);
  3144. Status = MappingUserListDelete(Mapping, User);
  3145. RtlReleaseResource(&MappingListLock);
  3146. RtlAcquireResourceExclusive(&UserListLock, TRUE);
  3147. pUser = UserListFind( User );
  3148. RtlReleaseResource(&UserListLock);
  3149. if (pUser != NULL) {
  3150. //
  3151. // if auto switch to BackOffice then turn BackOffice off
  3152. //
  3153. if (pUser->Flags & LLS_FLAG_SUITE_AUTO)
  3154. pUser->Flags &= ~ LLS_FLAG_SUITE_USE;
  3155. //
  3156. // Free up any licenses used by the user
  3157. //
  3158. RtlEnterCriticalSection(&pUser->ServiceTableLock);
  3159. SvcListLicenseFree( pUser );
  3160. pUser->Mapping = NULL;
  3161. //
  3162. // And claim any needed new-ones
  3163. //
  3164. SvcListLicenseUpdate( pUser );
  3165. RtlLeaveCriticalSection(&pUser->ServiceTableLock);
  3166. }
  3167. if (Status == STATUS_SUCCESS)
  3168. {
  3169. Status = MappingListSave();
  3170. if (Status == STATUS_SUCCESS)
  3171. Status = LLSDataSave();
  3172. }
  3173. return Status;
  3174. } // LlsrMappingUserDeleteW
  3175. /////////////////////////////////////////////////////////////////////////
  3176. NTSTATUS LlsrMappingUserDeleteA(
  3177. LLS_HANDLE Handle,
  3178. LPSTR Mapping,
  3179. LPSTR User
  3180. )
  3181. /*++
  3182. Routine Description:
  3183. Arguments:
  3184. Return Value:
  3185. --*/
  3186. {
  3187. #if DBG
  3188. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3189. dprintf(TEXT("LLS TRACE: LlsMappingUserDeleteA\n"));
  3190. #endif
  3191. UNREFERENCED_PARAMETER(Handle);
  3192. UNREFERENCED_PARAMETER(Mapping);
  3193. UNREFERENCED_PARAMETER(User);
  3194. return STATUS_NOT_SUPPORTED;
  3195. } // LlsrMappingUserDeleteA
  3196. /////////////////////////////////////////////////////////////////////////
  3197. NTSTATUS LlsrMappingAddW(
  3198. LLS_HANDLE Handle,
  3199. DWORD Level,
  3200. PLLS_MAPPING_INFOW BufPtr
  3201. )
  3202. /*++
  3203. Routine Description:
  3204. Arguments:
  3205. Return Value:
  3206. --*/
  3207. {
  3208. NTSTATUS Status = STATUS_SUCCESS;
  3209. PMAPPING_RECORD pMap;
  3210. UNREFERENCED_PARAMETER(Handle);
  3211. #if DBG
  3212. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3213. dprintf(TEXT("LLS TRACE: LlsMappingAddW\n"));
  3214. #endif
  3215. #if DELAY_INITIALIZATION
  3216. EnsureInitialized();
  3217. #endif
  3218. if (Level != 1)
  3219. return STATUS_INVALID_LEVEL;
  3220. if ((BufPtr == NULL) ||
  3221. (BufPtr->MappingInfo1.Name == NULL) ||
  3222. (BufPtr->MappingInfo1.Comment == NULL))
  3223. return STATUS_INVALID_PARAMETER;
  3224. RtlAcquireResourceExclusive(&MappingListLock, TRUE);
  3225. pMap = MappingListAdd(BufPtr->MappingInfo1.Name,
  3226. BufPtr->MappingInfo1.Comment,
  3227. BufPtr->MappingInfo1.Licenses,
  3228. &Status);
  3229. RtlReleaseResource(&MappingListLock);
  3230. if (pMap == NULL)
  3231. {
  3232. if (STATUS_SUCCESS == Status)
  3233. Status = STATUS_NO_MEMORY;
  3234. }
  3235. if (Status == STATUS_SUCCESS)
  3236. Status = MappingListSave();
  3237. return Status;
  3238. } // LlsrMappingAddW
  3239. /////////////////////////////////////////////////////////////////////////
  3240. NTSTATUS LlsrMappingAddA(
  3241. LLS_HANDLE Handle,
  3242. DWORD Level,
  3243. PLLS_MAPPING_INFOA BufPtr
  3244. )
  3245. /*++
  3246. Routine Description:
  3247. Arguments:
  3248. Return Value:
  3249. --*/
  3250. {
  3251. #if DBG
  3252. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3253. dprintf(TEXT("LLS TRACE: LlsMappingAddA\n"));
  3254. #endif
  3255. UNREFERENCED_PARAMETER(Handle);
  3256. UNREFERENCED_PARAMETER(Level);
  3257. UNREFERENCED_PARAMETER(BufPtr);
  3258. return STATUS_NOT_SUPPORTED;
  3259. } // LlsrMappingAddA
  3260. /////////////////////////////////////////////////////////////////////////
  3261. NTSTATUS LlsrMappingDeleteW(
  3262. LLS_HANDLE Handle,
  3263. LPWSTR Mapping
  3264. )
  3265. /*++
  3266. Routine Description:
  3267. Arguments:
  3268. Return Value:
  3269. --*/
  3270. {
  3271. NTSTATUS Status;
  3272. UNREFERENCED_PARAMETER(Handle);
  3273. #if DBG
  3274. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3275. dprintf(TEXT("LLS TRACE: LlsMappingDeleteW\n"));
  3276. #endif
  3277. #if DELAY_INITIALIZATION
  3278. EnsureInitialized();
  3279. #endif
  3280. if (Mapping == NULL)
  3281. return STATUS_INVALID_PARAMETER;
  3282. RtlAcquireResourceExclusive(&MappingListLock, TRUE);
  3283. Status = MappingListDelete(Mapping);
  3284. RtlReleaseResource(&MappingListLock);
  3285. if (Status == STATUS_SUCCESS)
  3286. Status = MappingListSave();
  3287. return Status;
  3288. } // LlsrMappingDeleteW
  3289. /////////////////////////////////////////////////////////////////////////
  3290. NTSTATUS LlsrMappingDeleteA(
  3291. LLS_HANDLE Handle,
  3292. LPSTR Mapping
  3293. )
  3294. /*++
  3295. Routine Description:
  3296. Arguments:
  3297. Return Value:
  3298. --*/
  3299. {
  3300. #if DBG
  3301. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3302. dprintf(TEXT("LLS TRACE: LlsMappingDeleteA\n"));
  3303. #endif
  3304. UNREFERENCED_PARAMETER(Handle);
  3305. UNREFERENCED_PARAMETER(Mapping);
  3306. return STATUS_NOT_SUPPORTED;
  3307. } // LlsrMappingDeleteA
  3308. /////////////////////////////////////////////////////////////////////////
  3309. NTSTATUS LlsrServerEnumW(
  3310. LLS_HANDLE Handle,
  3311. LPWSTR Server,
  3312. PLLS_SERVER_ENUM_STRUCTW pServerProductInfo,
  3313. DWORD pPrefMaxLen,
  3314. LPDWORD pTotalEntries,
  3315. LPDWORD pResumeHandle
  3316. )
  3317. /*++
  3318. Routine Description:
  3319. Arguments:
  3320. Return Value:
  3321. --*/
  3322. {
  3323. #if DBG
  3324. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3325. dprintf(TEXT("LLS TRACE: LlsServerEnumW\n"));
  3326. #endif
  3327. UNREFERENCED_PARAMETER(Handle);
  3328. UNREFERENCED_PARAMETER(Server);
  3329. UNREFERENCED_PARAMETER(pServerProductInfo);
  3330. UNREFERENCED_PARAMETER(pPrefMaxLen);
  3331. UNREFERENCED_PARAMETER(pResumeHandle);
  3332. if (NULL == pTotalEntries)
  3333. {
  3334. return STATUS_INVALID_PARAMETER;
  3335. }
  3336. *pTotalEntries = 0;
  3337. return STATUS_NOT_SUPPORTED;
  3338. } // LlsrServerEnumW
  3339. /////////////////////////////////////////////////////////////////////////
  3340. NTSTATUS LlsrServerEnumA(
  3341. LLS_HANDLE Handle,
  3342. LPSTR Server,
  3343. PLLS_SERVER_ENUM_STRUCTA pServerProductInfo,
  3344. DWORD PrefMaxLen,
  3345. LPDWORD TotalEntries,
  3346. LPDWORD ResumeHandle
  3347. )
  3348. /*++
  3349. Routine Description:
  3350. Arguments:
  3351. Return Value:
  3352. --*/
  3353. {
  3354. #if DBG
  3355. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3356. dprintf(TEXT("LLS TRACE: LlsServerEnumA\n"));
  3357. #endif
  3358. UNREFERENCED_PARAMETER(Handle);
  3359. UNREFERENCED_PARAMETER(Server);
  3360. UNREFERENCED_PARAMETER(pServerProductInfo);
  3361. UNREFERENCED_PARAMETER(PrefMaxLen);
  3362. UNREFERENCED_PARAMETER(ResumeHandle);
  3363. if (NULL == TotalEntries)
  3364. {
  3365. return STATUS_INVALID_PARAMETER;
  3366. }
  3367. *TotalEntries = 0;
  3368. return STATUS_NOT_SUPPORTED;
  3369. } // LlsrServerEnumA
  3370. /////////////////////////////////////////////////////////////////////////
  3371. NTSTATUS LlsrServerProductEnumW(
  3372. LLS_HANDLE Handle,
  3373. LPWSTR Server,
  3374. PLLS_SERVER_PRODUCT_ENUM_STRUCTW pServerProductInfo,
  3375. DWORD pPrefMaxLen,
  3376. LPDWORD pTotalEntries,
  3377. LPDWORD pResumeHandle
  3378. )
  3379. /*++
  3380. Routine Description:
  3381. Arguments:
  3382. Return Value:
  3383. --*/
  3384. {
  3385. #if DBG
  3386. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3387. dprintf(TEXT("LLS TRACE: LlsServerProductEnumW\n"));
  3388. #endif
  3389. UNREFERENCED_PARAMETER(Handle);
  3390. UNREFERENCED_PARAMETER(Server);
  3391. UNREFERENCED_PARAMETER(pServerProductInfo);
  3392. UNREFERENCED_PARAMETER(pPrefMaxLen);
  3393. UNREFERENCED_PARAMETER(pResumeHandle);
  3394. if (NULL == pTotalEntries)
  3395. {
  3396. return STATUS_INVALID_PARAMETER;
  3397. }
  3398. *pTotalEntries = 0;
  3399. return STATUS_NOT_SUPPORTED;
  3400. } // LlsrServerProductEnumW
  3401. /////////////////////////////////////////////////////////////////////////
  3402. NTSTATUS LlsrServerProductEnumA(
  3403. LLS_HANDLE Handle,
  3404. LPSTR Server,
  3405. PLLS_SERVER_PRODUCT_ENUM_STRUCTA pServerProductInfo,
  3406. DWORD PrefMaxLen,
  3407. LPDWORD TotalEntries,
  3408. LPDWORD ResumeHandle
  3409. )
  3410. /*++
  3411. Routine Description:
  3412. Arguments:
  3413. Return Value:
  3414. --*/
  3415. {
  3416. #if DBG
  3417. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3418. dprintf(TEXT("LLS TRACE: LlsServerProductEnumA\n"));
  3419. #endif
  3420. UNREFERENCED_PARAMETER(Handle);
  3421. UNREFERENCED_PARAMETER(Server);
  3422. UNREFERENCED_PARAMETER(pServerProductInfo);
  3423. UNREFERENCED_PARAMETER(PrefMaxLen);
  3424. UNREFERENCED_PARAMETER(ResumeHandle);
  3425. if (NULL == TotalEntries)
  3426. {
  3427. return STATUS_INVALID_PARAMETER;
  3428. }
  3429. *TotalEntries = 0;
  3430. return STATUS_NOT_SUPPORTED;
  3431. } // LlsrServerProductEnumA
  3432. /////////////////////////////////////////////////////////////////////////
  3433. NTSTATUS LlsrLocalProductEnumW(
  3434. LLS_HANDLE Handle,
  3435. PLLS_SERVER_PRODUCT_ENUM_STRUCTW pServerProductInfo,
  3436. DWORD pPrefMaxLen,
  3437. LPDWORD pTotalEntries,
  3438. LPDWORD pResumeHandle
  3439. )
  3440. /*++
  3441. Routine Description:
  3442. Arguments:
  3443. Return Value:
  3444. --*/
  3445. {
  3446. #if DBG
  3447. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3448. dprintf(TEXT("LLS TRACE: LlsLocalProductEnumW\n"));
  3449. #endif
  3450. UNREFERENCED_PARAMETER(Handle);
  3451. UNREFERENCED_PARAMETER(pServerProductInfo);
  3452. UNREFERENCED_PARAMETER(pPrefMaxLen);
  3453. UNREFERENCED_PARAMETER(pResumeHandle);
  3454. if (NULL == pTotalEntries)
  3455. {
  3456. return STATUS_INVALID_PARAMETER;
  3457. }
  3458. *pTotalEntries = 0;
  3459. return STATUS_NOT_SUPPORTED;
  3460. } // LlsrLocalProductEnumW
  3461. /////////////////////////////////////////////////////////////////////////
  3462. NTSTATUS LlsrLocalProductEnumA(
  3463. LLS_HANDLE Handle,
  3464. PLLS_SERVER_PRODUCT_ENUM_STRUCTA pServerProductInfo,
  3465. DWORD PrefMaxLen,
  3466. LPDWORD TotalEntries,
  3467. LPDWORD ResumeHandle
  3468. )
  3469. /*++
  3470. Routine Description:
  3471. Arguments:
  3472. Return Value:
  3473. --*/
  3474. {
  3475. #if DBG
  3476. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3477. dprintf(TEXT("LLS TRACE: LlsLocalProductEnumA\n"));
  3478. #endif
  3479. UNREFERENCED_PARAMETER(Handle);
  3480. UNREFERENCED_PARAMETER(pServerProductInfo);
  3481. UNREFERENCED_PARAMETER(PrefMaxLen);
  3482. UNREFERENCED_PARAMETER(ResumeHandle);
  3483. if (NULL == TotalEntries)
  3484. {
  3485. return STATUS_INVALID_PARAMETER;
  3486. }
  3487. *TotalEntries = 0;
  3488. return STATUS_NOT_SUPPORTED;
  3489. } // LlsrLocalProductEnumA
  3490. /////////////////////////////////////////////////////////////////////////
  3491. NTSTATUS LlsrLocalProductInfoGetW(
  3492. LLS_HANDLE Handle,
  3493. LPWSTR Product,
  3494. DWORD Level,
  3495. PLLS_SERVER_PRODUCT_INFOW *BufPtr
  3496. )
  3497. /*++
  3498. Routine Description:
  3499. Arguments:
  3500. Return Value:
  3501. --*/
  3502. {
  3503. #if DBG
  3504. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3505. dprintf(TEXT("LLS TRACE: LlsLocalProductInfoGetW\n"));
  3506. #endif
  3507. UNREFERENCED_PARAMETER(Handle);
  3508. UNREFERENCED_PARAMETER(Product);
  3509. UNREFERENCED_PARAMETER(Level);
  3510. if (NULL == BufPtr)
  3511. {
  3512. return STATUS_INVALID_PARAMETER;
  3513. }
  3514. *BufPtr = NULL;
  3515. return STATUS_NOT_SUPPORTED;
  3516. } // LlsrLocalProductInfoGetW
  3517. /////////////////////////////////////////////////////////////////////////
  3518. NTSTATUS LlsrLocalProductInfoGetA(
  3519. LLS_HANDLE Handle,
  3520. LPSTR Product,
  3521. DWORD Level,
  3522. PLLS_SERVER_PRODUCT_INFOA *BufPtr
  3523. )
  3524. /*++
  3525. Routine Description:
  3526. Arguments:
  3527. Return Value:
  3528. --*/
  3529. {
  3530. #if DBG
  3531. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3532. dprintf(TEXT("LLS TRACE: LlsLocalProductInfoGetA\n"));
  3533. #endif
  3534. UNREFERENCED_PARAMETER(Handle);
  3535. UNREFERENCED_PARAMETER(Product);
  3536. UNREFERENCED_PARAMETER(Level);
  3537. if (NULL == BufPtr)
  3538. {
  3539. return STATUS_INVALID_PARAMETER;
  3540. }
  3541. *BufPtr = NULL;
  3542. return STATUS_NOT_SUPPORTED;
  3543. } // LlsrLocalProductInfoGetA
  3544. /////////////////////////////////////////////////////////////////////////
  3545. NTSTATUS LlsrLocalProductInfoSetW(
  3546. LLS_HANDLE Handle,
  3547. LPWSTR Product,
  3548. DWORD Level,
  3549. PLLS_SERVER_PRODUCT_INFOW BufPtr
  3550. )
  3551. /*++
  3552. Routine Description:
  3553. Arguments:
  3554. Return Value:
  3555. --*/
  3556. {
  3557. #if DBG
  3558. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3559. dprintf(TEXT("LLS TRACE: LlsLocalProductInfoSetW\n"));
  3560. #endif
  3561. UNREFERENCED_PARAMETER(Handle);
  3562. UNREFERENCED_PARAMETER(Product);
  3563. UNREFERENCED_PARAMETER(Level);
  3564. UNREFERENCED_PARAMETER(BufPtr);
  3565. return STATUS_NOT_SUPPORTED;
  3566. } // LlsrLocalProductInfoSetW
  3567. /////////////////////////////////////////////////////////////////////////
  3568. NTSTATUS LlsrLocalProductInfoSetA(
  3569. LLS_HANDLE Handle,
  3570. LPSTR Product,
  3571. DWORD Level,
  3572. PLLS_SERVER_PRODUCT_INFOA BufPtr
  3573. )
  3574. /*++
  3575. Routine Description:
  3576. Arguments:
  3577. Return Value:
  3578. --*/
  3579. {
  3580. #if DBG
  3581. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3582. dprintf(TEXT("LLS TRACE: LlsLocalProductInfoSetA\n"));
  3583. #endif
  3584. UNREFERENCED_PARAMETER(Handle);
  3585. UNREFERENCED_PARAMETER(Product);
  3586. UNREFERENCED_PARAMETER(Level);
  3587. UNREFERENCED_PARAMETER(BufPtr);
  3588. return STATUS_NOT_SUPPORTED;
  3589. } // LlsrLocalProductInfoSetA
  3590. /////////////////////////////////////////////////////////////////////////
  3591. NTSTATUS LlsrServiceInfoGetW(
  3592. LLS_HANDLE Handle,
  3593. DWORD Level,
  3594. PLLS_SERVICE_INFOW *BufPtr
  3595. )
  3596. /*++
  3597. Routine Description:
  3598. Arguments:
  3599. Return Value:
  3600. --*/
  3601. {
  3602. PLLS_SERVICE_INFO_0 pInfo;
  3603. FILETIME ftTimeStartedLocal;
  3604. LARGE_INTEGER llTimeStartedLocal;
  3605. LARGE_INTEGER llTimeStartedSystem;
  3606. UNREFERENCED_PARAMETER(Handle);
  3607. #if DBG
  3608. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3609. dprintf(TEXT("LLS TRACE: LlsServiceInfoGetW\n"));
  3610. #endif
  3611. #if DELAY_INITIALIZATION
  3612. EnsureInitialized();
  3613. #endif
  3614. // make sure the config info is up-to-date
  3615. ConfigInfoUpdate(NULL,FALSE);
  3616. RtlEnterCriticalSection(&ConfigInfoLock);
  3617. if (BufPtr == NULL)
  3618. return STATUS_INVALID_PARAMETER;
  3619. *BufPtr = NULL;
  3620. if (Level != 0)
  3621. return STATUS_INVALID_LEVEL;
  3622. pInfo = (PLLS_SERVICE_INFO_0) MIDL_user_allocate(sizeof(LLS_SERVICE_INFO_0));
  3623. if (pInfo == NULL)
  3624. return STATUS_NO_MEMORY;
  3625. pInfo->Version = ConfigInfo.Version;
  3626. pInfo->Mode = LLS_MODE_ENTERPRISE_SERVER;
  3627. pInfo->ReplicateTo = ConfigInfo.ReplicateTo;
  3628. pInfo->EnterpriseServer = ConfigInfo.EnterpriseServer;
  3629. pInfo->ReplicationType = ConfigInfo.ReplicationType;
  3630. pInfo->ReplicationTime = ConfigInfo.ReplicationTime;
  3631. pInfo->LastReplicated = ConfigInfo.LastReplicatedSeconds;
  3632. pInfo->UseEnterprise = ConfigInfo.UseEnterprise;
  3633. SystemTimeToFileTime( &ConfigInfo.Started, &ftTimeStartedLocal );
  3634. // convert time started (a local SYSTEMTIME) to a system time DWORD in seconds since 1980
  3635. llTimeStartedLocal.u.LowPart = ftTimeStartedLocal.dwLowDateTime;
  3636. llTimeStartedLocal.u.HighPart = ftTimeStartedLocal.dwHighDateTime;
  3637. RtlLocalTimeToSystemTime( &llTimeStartedLocal, &llTimeStartedSystem );
  3638. RtlTimeToSecondsSince1980( &llTimeStartedSystem, &pInfo->TimeStarted );
  3639. *BufPtr = (PLLS_SERVICE_INFOW) pInfo;
  3640. return STATUS_SUCCESS;
  3641. } // LlsrServiceInfoGetW
  3642. void LlsrServiceInfoGetW_notify_flag(
  3643. boolean fNotify
  3644. )
  3645. {
  3646. if (fNotify)
  3647. {
  3648. RtlLeaveCriticalSection(&ConfigInfoLock);
  3649. }
  3650. }
  3651. /////////////////////////////////////////////////////////////////////////
  3652. NTSTATUS LlsrServiceInfoGetA(
  3653. LLS_HANDLE Handle,
  3654. DWORD Level,
  3655. PLLS_SERVICE_INFOA *BufPtr
  3656. )
  3657. /*++
  3658. Routine Description:
  3659. Arguments:
  3660. Return Value:
  3661. --*/
  3662. {
  3663. #if DBG
  3664. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3665. dprintf(TEXT("LLS TRACE: LlsServiceInfoGetA\n"));
  3666. #endif
  3667. UNREFERENCED_PARAMETER(Handle);
  3668. UNREFERENCED_PARAMETER(Level);
  3669. if (BufPtr == NULL)
  3670. return STATUS_INVALID_PARAMETER;
  3671. *BufPtr = NULL;
  3672. return STATUS_NOT_SUPPORTED;
  3673. } // LlsrServiceInfoGetA
  3674. /////////////////////////////////////////////////////////////////////////
  3675. NTSTATUS LlsrServiceInfoSetW(
  3676. LLS_HANDLE Handle,
  3677. DWORD Level,
  3678. PLLS_SERVICE_INFOW BufPtr
  3679. )
  3680. /*++
  3681. Routine Description:
  3682. Arguments:
  3683. Return Value:
  3684. --*/
  3685. {
  3686. PLLS_SERVICE_INFO_0W pInfo;
  3687. HKEY hKeyParameters;
  3688. LONG lError;
  3689. NTSTATUS Status = STATUS_NO_MEMORY;
  3690. UNREFERENCED_PARAMETER(Handle);
  3691. #if DBG
  3692. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3693. dprintf(TEXT("LLS TRACE: LlsServiceInfoSetW\n"));
  3694. #endif
  3695. #if DELAY_INITIALIZATION
  3696. EnsureInitialized();
  3697. #endif
  3698. if (BufPtr == NULL)
  3699. {
  3700. Status = STATUS_INVALID_PARAMETER;
  3701. goto error;
  3702. }
  3703. if (Level != 0)
  3704. {
  3705. Status = STATUS_INVALID_LEVEL;
  3706. goto error;
  3707. }
  3708. pInfo = &(BufPtr->ServiceInfo0);
  3709. lError = RegOpenKeyEx( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Services\\LicenseService\\Parameters", 0, KEY_WRITE, &hKeyParameters );
  3710. if ( ERROR_SUCCESS == lError )
  3711. {
  3712. lError = RegSetValueExW( hKeyParameters, L"EnterpriseServer", 0, REG_SZ, (LPBYTE) pInfo->EnterpriseServer, sizeof( WCHAR ) * ( 1 + lstrlenW( pInfo->EnterpriseServer ) ) );
  3713. if ( ERROR_SUCCESS == lError )
  3714. {
  3715. lError = RegSetValueEx( hKeyParameters, L"ReplicationTime", 0, REG_DWORD, (LPBYTE) &pInfo->ReplicationTime, sizeof( pInfo->ReplicationTime ) );
  3716. if ( ERROR_SUCCESS == lError )
  3717. {
  3718. lError = RegSetValueEx( hKeyParameters, L"ReplicationType", 0, REG_DWORD, (LPBYTE) &pInfo->ReplicationType, sizeof( pInfo->ReplicationType ) );
  3719. if ( ERROR_SUCCESS == lError )
  3720. {
  3721. lError = RegSetValueEx( hKeyParameters, L"UseEnterprise", 0, REG_DWORD, (LPBYTE) &pInfo->UseEnterprise, sizeof( pInfo->UseEnterprise ) );
  3722. if ( ERROR_SUCCESS == lError )
  3723. {
  3724. ConfigInfoUpdate(NULL,TRUE);
  3725. Status = STATUS_SUCCESS;
  3726. }
  3727. }
  3728. }
  3729. }
  3730. RegCloseKey( hKeyParameters );
  3731. }
  3732. error:
  3733. if (NULL != BufPtr)
  3734. {
  3735. // note, some internal pointers are defined as dont_free, we should free them here
  3736. if (NULL != BufPtr->ServiceInfo0.ReplicateTo)
  3737. {
  3738. MIDL_user_free(BufPtr->ServiceInfo0.ReplicateTo);
  3739. }
  3740. if (NULL != BufPtr->ServiceInfo0.EnterpriseServer)
  3741. {
  3742. MIDL_user_free(BufPtr->ServiceInfo0.EnterpriseServer);
  3743. }
  3744. }
  3745. return Status;
  3746. } // LlsrServiceInfoSetW
  3747. /////////////////////////////////////////////////////////////////////////
  3748. NTSTATUS LlsrServiceInfoSetA(
  3749. LLS_HANDLE Handle,
  3750. DWORD Level,
  3751. PLLS_SERVICE_INFOA BufPtr
  3752. )
  3753. /*++
  3754. Routine Description:
  3755. Arguments:
  3756. Return Value:
  3757. --*/
  3758. {
  3759. #if DBG
  3760. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3761. dprintf(TEXT("LLS TRACE: LlsServiceInfoSetA\n"));
  3762. #endif
  3763. UNREFERENCED_PARAMETER(Handle);
  3764. UNREFERENCED_PARAMETER(Level);
  3765. UNREFERENCED_PARAMETER(BufPtr);
  3766. return STATUS_NOT_SUPPORTED;
  3767. } // LlsrServiceInfoSetA
  3768. /////////////////////////////////////////////////////////////////////////
  3769. /////////////////////////////////////////////////////////////////////////
  3770. // Replication Functions
  3771. /////////////////////////////////////////////////////////////////////////
  3772. VOID __RPC_USER LLS_REPL_HANDLE_rundown(
  3773. LLS_REPL_HANDLE Handle
  3774. )
  3775. /*++
  3776. Routine Description:
  3777. Arguments:
  3778. Return Value:
  3779. --*/
  3780. {
  3781. NTSTATUS Status = STATUS_SUCCESS;
  3782. REPL_CONTEXT_TYPE *pClient;
  3783. LLS_REPL_HANDLE xHandle;
  3784. #if DBG
  3785. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3786. dprintf(TEXT("LLS TRACE: LLS_REPL_HANDLE_rundown\n"));
  3787. #endif
  3788. if (Handle == NULL)
  3789. return;
  3790. #if DELAY_INITIALIZATION
  3791. EnsureInitialized();
  3792. #endif
  3793. pClient = (REPL_CONTEXT_TYPE *) Handle;
  3794. try
  3795. {
  3796. if (pClient != NULL)
  3797. if (pClient->Active) {
  3798. xHandle = Handle;
  3799. LlsrReplClose(&xHandle);
  3800. }
  3801. } except(EXCEPTION_EXECUTE_HANDLER ) {
  3802. Status = GetExceptionCode();
  3803. }
  3804. } // LLS_REPL_HANDLE_rundown
  3805. /////////////////////////////////////////////////////////////////////////
  3806. NTSTATUS LlsrReplConnect(
  3807. PLLS_REPL_HANDLE Handle,
  3808. LPTSTR Name
  3809. )
  3810. /*++
  3811. Routine Description:
  3812. Arguments:
  3813. Return Value:
  3814. --*/
  3815. {
  3816. REPL_CONTEXT_TYPE *pClient;
  3817. HRESULT hr;
  3818. #if DBG
  3819. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3820. dprintf(TEXT("LLS TRACE: LlsReplConnect: %s\n"), Name);
  3821. #endif
  3822. #if DELAY_INITIALIZATION
  3823. EnsureInitialized();
  3824. #endif
  3825. if (NULL == Handle)
  3826. {
  3827. return STATUS_INVALID_PARAMETER;
  3828. }
  3829. *Handle = NULL;
  3830. pClient = (REPL_CONTEXT_TYPE *) midl_user_allocate(sizeof(REPL_CONTEXT_TYPE));
  3831. if (pClient == NULL)
  3832. {
  3833. return STATUS_NO_MEMORY;
  3834. }
  3835. memcpy(pClient->Signature,LLS_REPL_SIG,LLS_REPL_SIG_SIZE);
  3836. if (Name != NULL)
  3837. lstrcpyn(pClient->Name, Name,MAX_COMPUTERNAME_LENGTH+1);
  3838. else
  3839. {
  3840. hr = StringCbCopy(pClient->Name, sizeof(pClient->Name), TEXT(""));
  3841. ASSERT(SUCCEEDED(hr));
  3842. }
  3843. pClient->Active = TRUE;
  3844. pClient->Replicated = FALSE;
  3845. pClient->ServicesSent = FALSE;
  3846. pClient->ServiceTableSize = 0;
  3847. pClient->Services = NULL;
  3848. pClient->ServersSent = FALSE;
  3849. pClient->ServerTableSize = 0;
  3850. pClient->Servers = NULL;
  3851. pClient->ServerServicesSent = FALSE;
  3852. pClient->ServerServiceTableSize = 0;
  3853. pClient->ServerServices = NULL;
  3854. pClient->UsersSent = FALSE;
  3855. pClient->UserLevel = 0;
  3856. pClient->UserTableSize = 0;
  3857. pClient->Users = NULL;
  3858. pClient->CertDbSent = FALSE;
  3859. pClient->CertDbProductStringSize = 0;
  3860. pClient->CertDbProductStrings = NULL;
  3861. pClient->CertDbNumHeaders = 0;
  3862. pClient->CertDbHeaders = NULL;
  3863. pClient->CertDbNumClaims = 0;
  3864. pClient->CertDbClaims = NULL;
  3865. pClient->ProductSecuritySent = FALSE;
  3866. pClient->ProductSecurityStringSize = 0;
  3867. pClient->ProductSecurityStrings = NULL;
  3868. *Handle = pClient;
  3869. return STATUS_SUCCESS;
  3870. } // LlsrReplConnect
  3871. /////////////////////////////////////////////////////////////////////////
  3872. NTSTATUS LlsrReplClose(
  3873. LLS_REPL_HANDLE *pHandle
  3874. )
  3875. /*++
  3876. Routine Description:
  3877. Arguments:
  3878. Return Value:
  3879. --*/
  3880. {
  3881. NTSTATUS Status = STATUS_SUCCESS;
  3882. BOOL Replicated = TRUE;
  3883. LLS_REPL_HANDLE Handle = NULL;
  3884. REPL_CONTEXT_TYPE *pClient;
  3885. PSERVER_RECORD Server;
  3886. ULONG i;
  3887. #if DBG
  3888. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  3889. dprintf(TEXT("LLS TRACE: LlsReplClose\n"));
  3890. #endif
  3891. #if DELAY_INITIALIZATION
  3892. EnsureInitialized();
  3893. #endif
  3894. if (NULL == pHandle)
  3895. {
  3896. return STATUS_INVALID_PARAMETER;
  3897. }
  3898. //swi, code review, why we declare Handle here? It doesn't do anything in the code
  3899. Handle = *pHandle;
  3900. pClient = (REPL_CONTEXT_TYPE *) Handle;
  3901. try
  3902. {
  3903. if ((NULL == pClient) || (0 != memcmp(pClient->Signature,LLS_REPL_SIG,LLS_REPL_SIG_SIZE)))
  3904. {
  3905. return STATUS_INVALID_PARAMETER;
  3906. }
  3907. pClient->Active = FALSE;
  3908. //
  3909. // Check to see if we have all the information from the client - if we do
  3910. // then munge this information into our internal tables.
  3911. //
  3912. if (pClient->ServersSent && pClient->UsersSent && pClient->ServicesSent && pClient->ServerServicesSent) {
  3913. #if DBG
  3914. if (TraceFlags & TRACE_RPC)
  3915. dprintf(TEXT("LLS Replication - Munging Data\n"));
  3916. #endif
  3917. UnpackAll (
  3918. pClient->ServiceTableSize,
  3919. pClient->Services,
  3920. pClient->ServerTableSize,
  3921. pClient->Servers,
  3922. pClient->ServerServiceTableSize,
  3923. pClient->ServerServices,
  3924. pClient->UserLevel,
  3925. pClient->UserTableSize,
  3926. pClient->Users
  3927. );
  3928. if ( pClient->CertDbSent )
  3929. {
  3930. CertDbUnpack(
  3931. pClient->CertDbProductStringSize,
  3932. pClient->CertDbProductStrings,
  3933. pClient->CertDbNumHeaders,
  3934. pClient->CertDbHeaders,
  3935. pClient->CertDbNumClaims,
  3936. pClient->CertDbClaims,
  3937. TRUE );
  3938. }
  3939. if ( pClient->ProductSecuritySent )
  3940. {
  3941. ProductSecurityUnpack(
  3942. pClient->ProductSecurityStringSize,
  3943. pClient->ProductSecurityStrings );
  3944. }
  3945. } else
  3946. Replicated = FALSE;
  3947. //////////////////////////////////////////////////////////////////
  3948. //
  3949. // Replication Finished - clean up the context data.
  3950. //
  3951. #if DBG
  3952. if (TraceFlags & TRACE_RPC)
  3953. dprintf(TEXT("LLS Replication - Munging Finished\n"));
  3954. #endif
  3955. if (pClient->Servers != NULL) {
  3956. for (i = 0; i < pClient->ServerTableSize; i++)
  3957. MIDL_user_free(pClient->Servers[i].Name);
  3958. MIDL_user_free(pClient->Servers);
  3959. }
  3960. if (pClient->Services != NULL) {
  3961. for (i = 0; i < pClient->ServiceTableSize; i++) {
  3962. MIDL_user_free(pClient->Services[i].Name);
  3963. MIDL_user_free(pClient->Services[i].FamilyName);
  3964. }
  3965. MIDL_user_free(pClient->Services);
  3966. }
  3967. if (pClient->ServerServices != NULL)
  3968. MIDL_user_free(pClient->ServerServices);
  3969. if (pClient->Users != NULL) {
  3970. for (i = 0; i < pClient->UserTableSize; i++)
  3971. {
  3972. if ( 0 == pClient->UserLevel )
  3973. {
  3974. MIDL_user_free( ((PREPL_USER_RECORD_0) (pClient->Users))[i].Name );
  3975. }
  3976. else
  3977. {
  3978. ASSERT( 1 == pClient->UserLevel );
  3979. MIDL_user_free( ((PREPL_USER_RECORD_1) (pClient->Users))[i].Name );
  3980. }
  3981. }
  3982. MIDL_user_free(pClient->Users);
  3983. }
  3984. if (pClient->CertDbProductStrings != NULL)
  3985. {
  3986. MIDL_user_free(pClient->CertDbProductStrings);
  3987. }
  3988. if (pClient->CertDbHeaders != NULL)
  3989. {
  3990. MIDL_user_free(pClient->CertDbHeaders);
  3991. }
  3992. if (pClient->CertDbClaims != NULL)
  3993. {
  3994. MIDL_user_free(pClient->CertDbClaims);
  3995. }
  3996. if (pClient->ProductSecurityStrings != NULL)
  3997. {
  3998. MIDL_user_free(pClient->ProductSecurityStrings);
  3999. }
  4000. if (pClient->Replicated) {
  4001. if (Replicated) {
  4002. RtlAcquireResourceShared(&ServerListLock, TRUE);
  4003. Server = ServerListFind(pClient->Name);
  4004. RtlReleaseResource(&ServerListLock);
  4005. ASSERT(Server != NULL);
  4006. if (Server != NULL)
  4007. Server->LastReplicated = pClient->ReplicationStart;
  4008. }
  4009. RtlEnterCriticalSection(&ConfigInfoLock);
  4010. i = --ConfigInfo.NumReplicating;
  4011. RtlLeaveCriticalSection(&ConfigInfoLock);
  4012. if ( !i )
  4013. {
  4014. // no one's replicating; save all our data files
  4015. SaveAll();
  4016. }
  4017. }
  4018. MIDL_user_free(pClient);
  4019. } except(EXCEPTION_EXECUTE_HANDLER ) {
  4020. Status = GetExceptionCode();
  4021. }
  4022. //
  4023. // Let RPC know were done with it.
  4024. //
  4025. *pHandle = NULL;
  4026. return Status;
  4027. } // LlsrReplClose
  4028. /////////////////////////////////////////////////////////////////////////
  4029. NTSTATUS
  4030. LlsrReplicationRequestW(
  4031. LLS_HANDLE Handle,
  4032. DWORD Version,
  4033. PREPL_REQUEST pRequest
  4034. )
  4035. /*++
  4036. Routine Description:
  4037. Arguments:
  4038. Return Value:
  4039. --*/
  4040. {
  4041. NTSTATUS Status = STATUS_SUCCESS;
  4042. TCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  4043. REPL_CONTEXT_TYPE *pClient;
  4044. PSERVER_RECORD Server = NULL;
  4045. HRESULT hr;
  4046. #if DBG
  4047. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC | TRACE_REPLICATION))
  4048. dprintf(TEXT("LLS TRACE: LlsReplicationRequestW: %s\n"), ((PCLIENT_CONTEXT_TYPE) Handle)->Name);
  4049. #endif
  4050. #if DELAY_INITIALIZATION
  4051. EnsureInitialized();
  4052. #endif
  4053. if (Version != REPL_VERSION) {
  4054. return STATUS_INVALID_LEVEL;
  4055. }
  4056. if (pRequest == NULL)
  4057. return STATUS_INVALID_PARAMETER;
  4058. ComputerName[0] = 0;
  4059. ASSERT(NULL != pRequest);
  4060. pRequest->EnterpriseServer[0] = 0;
  4061. //
  4062. // Check Enterprise server date from client to see if we need to update
  4063. // ours. Also, send back new one for the client.
  4064. //
  4065. RtlEnterCriticalSection(&ConfigInfoLock);
  4066. if (ConfigInfo.ComputerName != NULL)
  4067. {
  4068. hr = StringCbCopy(ComputerName, sizeof(ComputerName), ConfigInfo.ComputerName);
  4069. ASSERT(SUCCEEDED(hr));
  4070. }
  4071. #ifdef DISABLED_FOR_NT5
  4072. if (ConfigInfo.EnterpriseServerDate < pRequest->EnterpriseServerDate) {
  4073. if (lstrlen(pRequest->EnterpriseServer) != 0) {
  4074. //ConfigInfo.EnterpriseServer is hard code allocated in ConfigInfoInit as size of MAX_COMPUTERNAME_LENGTH + 3 chars. It seems lazy.
  4075. ASSERT(NULL != ConfigInfo.EnterpriseServer);
  4076. hr = StringCchCopy(ConfigInfo.EnterpriseServer, MAX_COMPUTERNAME_LENGTH + 3, pRequest->EnterpriseServer);
  4077. ASSERT(SUCCEEDED(hr));
  4078. ConfigInfo.EnterpriseServerDate = pRequest->EnterpriseServerDate;
  4079. }
  4080. }
  4081. #endif // DISABLED_FOR_NT5
  4082. if (ConfigInfo.EnterpriseServer != NULL)
  4083. {
  4084. //ConfigInfo.EnterpriseServer is hard code allocated in ConfigInfoInit as size of MAX_COMPUTERNAME_LENGTH + 3 chars. It seems lazy.
  4085. hr = StringCchCopy(pRequest->EnterpriseServer, MAX_COMPUTERNAME_LENGTH + 3, ConfigInfo.EnterpriseServer);
  4086. ASSERT(SUCCEEDED(hr));
  4087. }
  4088. pRequest->EnterpriseServerDate = ConfigInfo.EnterpriseServerDate;
  4089. //
  4090. // Increment Repl Count
  4091. //
  4092. ConfigInfo.NumReplicating++;
  4093. RtlLeaveCriticalSection(&ConfigInfoLock);
  4094. //
  4095. // Find this server in our server list (add it if not there)
  4096. //
  4097. pClient = (REPL_CONTEXT_TYPE *) Handle;
  4098. try
  4099. {
  4100. if ((NULL == pClient) || (0 != memcmp(pClient->Signature,LLS_REPL_SIG,LLS_REPL_SIG_SIZE)))
  4101. {
  4102. return STATUS_INVALID_PARAMETER;
  4103. }
  4104. pClient->Replicated = TRUE;
  4105. RtlAcquireResourceExclusive(&ServerListLock, TRUE);
  4106. Server = ServerListAdd(pClient->Name, ComputerName);
  4107. RtlReleaseResource(&ServerListLock);
  4108. if (Server == NULL) {
  4109. return STATUS_NO_MEMORY;
  4110. }
  4111. pClient->ReplicationStart = pRequest->CurrentTime;
  4112. } except(EXCEPTION_EXECUTE_HANDLER ) {
  4113. Status = GetExceptionCode();
  4114. }
  4115. pRequest->LastReplicated = Server->LastReplicated;
  4116. return Status;
  4117. } // LlsrReplicationRequestW
  4118. /////////////////////////////////////////////////////////////////////////
  4119. NTSTATUS
  4120. LlsrReplicationServerAddW(
  4121. LLS_HANDLE Handle,
  4122. ULONG NumRecords,
  4123. PREPL_SERVER_RECORD Servers
  4124. )
  4125. /*++
  4126. Routine Description:
  4127. Arguments:
  4128. Return Value:
  4129. --*/
  4130. {
  4131. NTSTATUS Status = STATUS_SUCCESS;
  4132. REPL_CONTEXT_TYPE *pClient;
  4133. DWORD i;
  4134. #if DBG
  4135. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  4136. dprintf(TEXT("LLS TRACE: LlsReplicationServerAddW\n"));
  4137. #endif
  4138. #if DELAY_INITIALIZATION
  4139. EnsureInitialized();
  4140. #endif
  4141. pClient = (REPL_CONTEXT_TYPE *) Handle;
  4142. try
  4143. {
  4144. if ((NULL == pClient) || (0 != memcmp(pClient->Signature,LLS_REPL_SIG,LLS_REPL_SIG_SIZE)))
  4145. {
  4146. // free all data because it is dont_free
  4147. if (NULL != Servers)
  4148. {
  4149. for (i = 0; i < NumRecords; i++)
  4150. {
  4151. MIDL_user_free(Servers[i].Name);
  4152. }
  4153. MIDL_user_free(Servers);
  4154. }
  4155. return STATUS_INVALID_PARAMETER;
  4156. }
  4157. if (pClient->ServersSent)
  4158. {
  4159. // don't accept more than one Add
  4160. // free all data because it is dont_free
  4161. if (NULL != Servers)
  4162. {
  4163. for (i = 0; i < NumRecords; i++)
  4164. {
  4165. MIDL_user_free(Servers[i].Name);
  4166. }
  4167. MIDL_user_free(Servers);
  4168. }
  4169. return HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
  4170. }
  4171. pClient->ServersSent = TRUE;
  4172. pClient->ServerTableSize = NumRecords;
  4173. pClient->Servers = Servers;
  4174. //don't free Servers and it will be free in ReplClose
  4175. } except(EXCEPTION_EXECUTE_HANDLER ) {
  4176. Status = GetExceptionCode();
  4177. }
  4178. return Status;
  4179. } // LlsrReplicationServerAddW
  4180. /////////////////////////////////////////////////////////////////////////
  4181. NTSTATUS
  4182. LlsrReplicationServerServiceAddW(
  4183. LLS_HANDLE Handle,
  4184. ULONG NumRecords,
  4185. PREPL_SERVER_SERVICE_RECORD ServerServices
  4186. )
  4187. /*++
  4188. Routine Description:
  4189. Arguments:
  4190. Return Value:
  4191. --*/
  4192. {
  4193. NTSTATUS Status = STATUS_SUCCESS;
  4194. REPL_CONTEXT_TYPE *pClient;
  4195. #if DBG
  4196. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  4197. dprintf(TEXT("LLS TRACE: LlsReplicationServerServiceAddW\n"));
  4198. #endif
  4199. #if DELAY_INITIALIZATION
  4200. EnsureInitialized();
  4201. #endif
  4202. pClient = (REPL_CONTEXT_TYPE *) Handle;
  4203. try
  4204. {
  4205. if ((NULL == pClient) || (0 != memcmp(pClient->Signature,LLS_REPL_SIG,LLS_REPL_SIG_SIZE)))
  4206. {
  4207. // free all data because it is dont_free
  4208. if (NULL != ServerServices)
  4209. {
  4210. MIDL_user_free(ServerServices);
  4211. }
  4212. return STATUS_INVALID_PARAMETER;
  4213. }
  4214. if (pClient->ServerServicesSent)
  4215. {
  4216. // don't accept more than one Add
  4217. // free all data because it is dont_free
  4218. if (NULL != ServerServices)
  4219. {
  4220. MIDL_user_free(ServerServices);
  4221. }
  4222. return HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
  4223. }
  4224. pClient->ServerServicesSent = TRUE;
  4225. pClient->ServerServiceTableSize = NumRecords;
  4226. pClient->ServerServices = ServerServices;
  4227. //don't free and it will be free in ReplClose
  4228. } except(EXCEPTION_EXECUTE_HANDLER ) {
  4229. Status = GetExceptionCode();
  4230. }
  4231. return Status;
  4232. } // LlsrReplicationServerServiceAddW
  4233. /////////////////////////////////////////////////////////////////////////
  4234. NTSTATUS
  4235. LlsrReplicationServiceAddW(
  4236. LLS_HANDLE Handle,
  4237. ULONG NumRecords,
  4238. PREPL_SERVICE_RECORD Services
  4239. )
  4240. /*++
  4241. Routine Description:
  4242. Arguments:
  4243. Return Value:
  4244. --*/
  4245. {
  4246. NTSTATUS Status = STATUS_SUCCESS;
  4247. REPL_CONTEXT_TYPE *pClient;
  4248. DWORD i;
  4249. #if DBG
  4250. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  4251. dprintf(TEXT("LLS TRACE: LlsReplicationServiceAddW\n"));
  4252. #endif
  4253. #if DELAY_INITIALIZATION
  4254. EnsureInitialized();
  4255. #endif
  4256. pClient = (REPL_CONTEXT_TYPE *) Handle;
  4257. try
  4258. {
  4259. if ((NULL == pClient) || (0 != memcmp(pClient->Signature,LLS_REPL_SIG,LLS_REPL_SIG_SIZE)))
  4260. {
  4261. // free all data because it is dont_free
  4262. if (NULL != Services)
  4263. {
  4264. for (i = 0; i < NumRecords; i++)
  4265. {
  4266. MIDL_user_free(Services[i].Name);
  4267. MIDL_user_free(Services[i].FamilyName);
  4268. }
  4269. MIDL_user_free(Services);
  4270. }
  4271. return STATUS_INVALID_PARAMETER;
  4272. }
  4273. if (pClient->ServicesSent)
  4274. {
  4275. // don't accept more than one Add
  4276. // free all data because it is dont_free
  4277. if (NULL != Services)
  4278. {
  4279. for (i = 0; i < NumRecords; i++)
  4280. {
  4281. MIDL_user_free(Services[i].Name);
  4282. MIDL_user_free(Services[i].FamilyName);
  4283. }
  4284. MIDL_user_free(Services);
  4285. }
  4286. return HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
  4287. }
  4288. pClient->ServicesSent = TRUE;
  4289. pClient->ServiceTableSize = NumRecords;
  4290. pClient->Services = Services;
  4291. // don't free and it will be free in ReplClose
  4292. } except(EXCEPTION_EXECUTE_HANDLER ) {
  4293. Status = GetExceptionCode();
  4294. }
  4295. return Status;
  4296. } // LlsrReplicationServiceAddW
  4297. /////////////////////////////////////////////////////////////////////////
  4298. NTSTATUS
  4299. LlsrReplicationUserAddW(
  4300. LLS_HANDLE Handle,
  4301. ULONG NumRecords,
  4302. PREPL_USER_RECORD_0 Users
  4303. )
  4304. /*++
  4305. Routine Description:
  4306. Arguments:
  4307. Return Value:
  4308. --*/
  4309. {
  4310. NTSTATUS Status = STATUS_SUCCESS;
  4311. REPL_CONTEXT_TYPE *pClient;
  4312. DWORD i;
  4313. #if DBG
  4314. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  4315. dprintf(TEXT("LLS TRACE: LlsReplicationUserAddW\n"));
  4316. #endif
  4317. #if DELAY_INITIALIZATION
  4318. EnsureInitialized();
  4319. #endif
  4320. pClient = (REPL_CONTEXT_TYPE *) Handle;
  4321. try
  4322. {
  4323. if ((NULL == pClient) || (0 != memcmp(pClient->Signature,LLS_REPL_SIG,LLS_REPL_SIG_SIZE)))
  4324. {
  4325. // free all data because it is dont_free
  4326. if (NULL != Users)
  4327. {
  4328. for (i = 0; i < NumRecords; i++)
  4329. {
  4330. MIDL_user_free( Users[i].Name );
  4331. }
  4332. MIDL_user_free(Users);
  4333. }
  4334. return STATUS_INVALID_PARAMETER;
  4335. }
  4336. if (pClient->UsersSent)
  4337. {
  4338. // don't accept more than one Add
  4339. // free all data because it is dont_free
  4340. if (NULL != Users)
  4341. {
  4342. for (i = 0; i < NumRecords; i++)
  4343. {
  4344. MIDL_user_free( Users[i].Name );
  4345. }
  4346. MIDL_user_free(Users);
  4347. }
  4348. return HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
  4349. }
  4350. pClient->UsersSent = TRUE;
  4351. pClient->UserLevel = 0;
  4352. pClient->UserTableSize = NumRecords;
  4353. pClient->Users = Users;
  4354. // don't free Users and it will be free in ReplClose
  4355. } except(EXCEPTION_EXECUTE_HANDLER ) {
  4356. Status = GetExceptionCode();
  4357. }
  4358. return Status;
  4359. } // LlsrReplicationUserAddW
  4360. /////////////////////////////////////////////////////////////////////////
  4361. /////////////////////////////////////////////////////////////////////////
  4362. // Licensing Functions
  4363. /////////////////////////////////////////////////////////////////////////
  4364. // Definitions from SVCTBL.C to fascilitate the SBS specific code below.
  4365. #define FILE_PRINT "FilePrint "
  4366. #define FILE_PRINT_BASE "FilePrint"
  4367. #define FILE_PRINT_VERSION_NDX ( 9 )
  4368. NTSTATUS
  4369. LlsrLicenseRequestW(
  4370. PLICENSE_HANDLE pLicenseHandle,
  4371. LPWSTR ProductID,
  4372. ULONG VersionIndex,
  4373. BOOLEAN IsAdmin,
  4374. ULONG DataType,
  4375. ULONG DataSize,
  4376. PBYTE Data
  4377. )
  4378. /*++
  4379. Routine Description:
  4380. Arguments:
  4381. Return Value:
  4382. --*/
  4383. {
  4384. NTSTATUS Status;
  4385. ULONG Handle = 0xFFFFFFFFL;
  4386. PSID Sid = NULL;
  4387. UNREFERENCED_PARAMETER(DataSize);
  4388. #if DBG
  4389. if ( TraceFlags & (TRACE_FUNCTION_TRACE) )
  4390. dprintf(TEXT("LLS TRACE: LlsrLicenseRequestW\n"));
  4391. #endif
  4392. #if DELAY_INITIALIZATION
  4393. EnsureInitialized();
  4394. #endif
  4395. if ((NULL == pLicenseHandle) || (NULL == ProductID) || (NULL == Data) || (VersionIndex >= (ULONG)lstrlen(ProductID)))
  4396. {
  4397. return STATUS_INVALID_PARAMETER;
  4398. }
  4399. //
  4400. // SBS mods (bug# 505640), per server fix. Check database of user licenses to determine whether or not the specified user
  4401. // name already has a license. If it does, just bump the RefCount.
  4402. //
  4403. if (SBSPerServerHotfix) {
  4404. PPER_SERVER_USER_RECORD Walker;
  4405. LPWSTR UserName = NULL;
  4406. DWORD SidNameSize = 0;
  4407. LPWSTR DomainName = NULL;
  4408. DWORD DomainSize = 0;
  4409. SID_NAME_USE SidNameUse;
  4410. WCHAR FilePrintName[] = TEXT(FILE_PRINT);
  4411. if (DataType == NT_LS_USER_NAME) {
  4412. //
  4413. // If we get a request from a user name with a '$' in it, we're going to return a dummy license
  4414. // handle without actually consuming a session in the license server. We need to make sure
  4415. // that a check for this is always the very first one in the free path.
  4416. //
  4417. if (wcschr((LPWSTR)Data,L'$')) {
  4418. *pLicenseHandle = (LICENSE_HANDLE) ULongToPtr(PER_SERVER_DUMMY_LICENSE);
  4419. return STATUS_SUCCESS;
  4420. }
  4421. // make sure we have a user name in the same form that we specified in the user list.
  4422. if (NULL == (UserName = wcschr((LPWSTR)Data,L'\\'))) {
  4423. UserName = (LPWSTR)Data;
  4424. } else {
  4425. UserName++;
  4426. }
  4427. //
  4428. // In the event of a bogus user account, LookupAccountName fails with ERROR_NONE_MAPPED.
  4429. // ERROR_INSUFFICIENT_BUFFER indicates that the account name exists, but that the buffer is too small.
  4430. // Hence, the following code is a simple existence check for the account name.
  4431. //
  4432. if (!LookupAccountName(NULL,
  4433. UserName,
  4434. NULL,
  4435. &SidNameSize,
  4436. NULL,
  4437. &DomainSize,
  4438. &SidNameUse)) {
  4439. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
  4440. *pLicenseHandle = NULL;
  4441. return LS_INSUFFICIENT_UNITS;
  4442. }
  4443. }
  4444. //
  4445. // Lookup the name again
  4446. if (NULL != (Sid = malloc(SidNameSize))) {
  4447. if (NULL != (DomainName = malloc(DomainSize*sizeof(WCHAR)))) {
  4448. if (!LookupAccountName(NULL,
  4449. UserName,
  4450. Sid,
  4451. &SidNameSize,
  4452. DomainName,
  4453. &DomainSize,
  4454. &SidNameUse)) {
  4455. free(DomainName);
  4456. free(Sid);
  4457. *pLicenseHandle = NULL;
  4458. return LS_UNKNOWN_STATUS;
  4459. }
  4460. free(DomainName);
  4461. } else {
  4462. free(Sid);
  4463. *pLicenseHandle = NULL;
  4464. return LS_UNKNOWN_STATUS;
  4465. }
  4466. } else {
  4467. *pLicenseHandle = NULL;
  4468. return LS_UNKNOWN_STATUS;
  4469. }
  4470. } else {
  4471. //
  4472. // Verify and make a copy of the SID for later checks.
  4473. //
  4474. if (!IsValidSid((PSID)Data)) {
  4475. *pLicenseHandle = NULL;
  4476. return LS_INSUFFICIENT_UNITS;
  4477. }
  4478. SidNameSize = GetLengthSid((PSID)Data);
  4479. if (NULL == (Sid = malloc(SidNameSize))) {
  4480. *pLicenseHandle = NULL;
  4481. return LS_UNKNOWN_STATUS;
  4482. }
  4483. if (!CopySid(SidNameSize,Sid,(PSID)Data)) {
  4484. free(Sid);
  4485. *pLicenseHandle = NULL;
  4486. return LS_UNKNOWN_STATUS;
  4487. }
  4488. if (!IsWellKnownSid(Sid,WinLocalSystemSid)) {
  4489. //
  4490. // In the event of a bogus user account, LookupAccountSid fails with ERROR_NONE_MAPPED.
  4491. // ERROR_INSUFFICIENT_BUFFER indicates that the account name exists, but that the buffer is too small.
  4492. // Hence, the following code is a simple existence check for the account name.
  4493. //
  4494. SidNameSize = 0;
  4495. if (!LookupAccountSid(NULL,
  4496. Sid,
  4497. NULL,
  4498. &SidNameSize,
  4499. NULL,
  4500. &DomainSize,
  4501. &SidNameUse)) {
  4502. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
  4503. *pLicenseHandle = NULL;
  4504. return LS_INSUFFICIENT_UNITS;
  4505. }
  4506. }
  4507. if (NULL != (UserName = malloc(SidNameSize*sizeof(WCHAR)))) {
  4508. if (NULL != (DomainName = malloc(DomainSize*sizeof(WCHAR)))) {
  4509. if (LookupAccountSid(NULL,
  4510. Sid,
  4511. UserName,
  4512. &SidNameSize,
  4513. DomainName,
  4514. &DomainSize,
  4515. &SidNameUse)) {
  4516. if (SidNameUse != SidTypeUser) {
  4517. free(UserName);
  4518. free(DomainName);
  4519. free(Sid);
  4520. *pLicenseHandle = NULL;
  4521. return LS_INSUFFICIENT_UNITS;
  4522. }
  4523. } else {
  4524. free(DomainName);
  4525. free(UserName);
  4526. free(Sid);
  4527. *pLicenseHandle = NULL;
  4528. return LS_UNKNOWN_STATUS;
  4529. }
  4530. free(DomainName);
  4531. } else {
  4532. free(Sid);
  4533. free(UserName);
  4534. *pLicenseHandle = NULL;
  4535. return LS_UNKNOWN_STATUS;
  4536. }
  4537. free(UserName);
  4538. } else {
  4539. free(Sid);
  4540. *pLicenseHandle = NULL;
  4541. return LS_UNKNOWN_STATUS;
  4542. }
  4543. }
  4544. }
  4545. RtlEnterCriticalSection(&PerServerListLock);
  4546. // Walk our database and attempt to find an entry for the user/SID specified in the call.
  4547. for (Walker = PerServerList; Walker; Walker = Walker->Next) {
  4548. if (EqualSid(Sid,Walker->Sid)) {
  4549. break;
  4550. }
  4551. }
  4552. // if we broke out of the loop early, we found a matching entry. Up the ReferenceCount and return.
  4553. if (Walker) {
  4554. Walker->RefCount++;
  4555. if (LLS_POTENTIAL_ATTACK_THRESHHOLD == Walker->RefCount) {
  4556. PotentialAttackCounter++;
  4557. }
  4558. RtlLeaveCriticalSection(&PerServerListLock);
  4559. *pLicenseHandle = (LICENSE_HANDLE)Walker;
  4560. return STATUS_SUCCESS;
  4561. }
  4562. // if we didn't find a record for the user, let the license server engine have the request and
  4563. // our code below will add a record. In order to better manage license enforcement, SBS always uses
  4564. // FilePrint CALs.
  4565. ProductID = (LPWSTR)FilePrintName;
  4566. VersionIndex = FILE_PRINT_VERSION_NDX;
  4567. RtlLeaveCriticalSection(&PerServerListLock);
  4568. }
  4569. //
  4570. // end SBS mods
  4571. //
  4572. Status = DispatchRequestLicense(DataType, Data, ProductID, VersionIndex, IsAdmin, &Handle);
  4573. //
  4574. // SBS mods (bug# 505640), per server fix, add acquired license to the user tracking database. The will function
  4575. // as expected for the end user in per seat mode as well, although some tracking information will be lost.
  4576. //
  4577. // ensure that we're on SBS and that the license acquisition succeeded. Also a sanity check on
  4578. // the input data (which should always succeed).
  4579. if (SBSPerServerHotfix && (Status == STATUS_SUCCESS) && Data) {
  4580. PPER_SERVER_USER_RECORD UserRecord = (PPER_SERVER_USER_RECORD)malloc(sizeof(PER_SERVER_USER_RECORD));
  4581. if (UserRecord) {
  4582. UserRecord->RefCount = 1;
  4583. UserRecord->ActualLicenseHandle = Handle + 1;
  4584. UserRecord->Next = NULL;
  4585. UserRecord->Sid = Sid;
  4586. // We have a valid user track record. Add it to the list.
  4587. RtlEnterCriticalSection(&PerServerListLock);
  4588. UserRecord->Next = PerServerList;
  4589. PerServerList = UserRecord;
  4590. RtlLeaveCriticalSection(&PerServerListLock);
  4591. // We've successfully added our record to the list. Return a pointer to the entry in the context
  4592. // field.
  4593. *pLicenseHandle = (LICENSE_HANDLE)UserRecord;
  4594. return STATUS_SUCCESS;
  4595. }
  4596. //
  4597. // if we've gotten here it means there's been a problem allocating something. Fall through to the normal
  4598. // path so that the customer doesn't get penalized for this. Note this adds a little bit of work for us
  4599. // in the license free path, since we could in rare cases end up with a mix of typical license handles and
  4600. // pointers to our internal structures. We just have to do a check for pointer consistency in the free path.
  4601. //
  4602. }
  4603. //
  4604. // end SBS mods
  4605. //
  4606. // Can't allow Handle value of zero
  4607. *pLicenseHandle = (LICENSE_HANDLE) ULongToPtr(Handle+1);
  4608. return Status;
  4609. } // LlsrLicenseRequestW
  4610. NTSTATUS
  4611. LlsrLicenseFree(
  4612. PLICENSE_HANDLE pLicenseHandle
  4613. )
  4614. /*++
  4615. Routine Description:
  4616. Arguments:
  4617. Return Value:
  4618. --*/
  4619. {
  4620. #if DBG
  4621. if ( TraceFlags & (TRACE_FUNCTION_TRACE) )
  4622. dprintf(TEXT("LLS TRACE: LlsrLicenseFree\n"));
  4623. #endif
  4624. #if DELAY_INITIALIZATION
  4625. EnsureInitialized();
  4626. #endif
  4627. if (NULL == pLicenseHandle)
  4628. return STATUS_INVALID_PARAMETER;
  4629. //
  4630. // SBS mods (bug# 505640), per server licensing hotfix free code.
  4631. //
  4632. if (SBSPerServerHotfix) {
  4633. PPER_SERVER_USER_RECORD Walker = NULL;
  4634. PPER_SERVER_USER_RECORD UserRecord = (PPER_SERVER_USER_RECORD)(*pLicenseHandle);
  4635. if (PtrToUlong(*pLicenseHandle) == PER_SERVER_DUMMY_LICENSE) {
  4636. *pLicenseHandle = NULL;
  4637. return STATUS_SUCCESS;
  4638. }
  4639. //
  4640. // Because there are some rare cases where we may be mixing internal license handles and our hotfix track
  4641. // records, walk the list and make sure out handle is there.
  4642. //
  4643. RtlEnterCriticalSection(&PerServerListLock);
  4644. if (PerServerList == UserRecord) {
  4645. // stupid coder tricks: if UserRecord is the first on the list, point Walker at the list head
  4646. // for later possible removal. Since we only reference Next on Walker, this shouldn't present
  4647. // a problem.
  4648. Walker = (PPER_SERVER_USER_RECORD)&PerServerList;
  4649. } else {
  4650. for (Walker = PerServerList; Walker && Walker->Next != UserRecord; Walker = Walker->Next);
  4651. }
  4652. if (Walker) {
  4653. // we've found this entry on the list. Decrement the ref count and see whether it needs to go away.
  4654. if (!(--UserRecord->RefCount)) {
  4655. //ref count went to zero. Stop tracking this user and let the license engine free the license.
  4656. Walker->Next = UserRecord->Next;
  4657. RtlLeaveCriticalSection(&PerServerListLock);
  4658. // this next line should correctly free either a SID or a user name.
  4659. free(UserRecord->Sid);
  4660. *pLicenseHandle = (LICENSE_HANDLE) ULongToPtr(UserRecord->ActualLicenseHandle);
  4661. free(UserRecord);
  4662. } else {
  4663. if (LLS_POTENTIAL_ATTACK_THRESHHOLD == UserRecord->RefCount) {
  4664. PotentialAttackCounter--;
  4665. }
  4666. // ref count still valid. Just return STATUS_SUCCESS on free call.
  4667. RtlLeaveCriticalSection(&PerServerListLock);
  4668. *pLicenseHandle = NULL;
  4669. return STATUS_SUCCESS;
  4670. }
  4671. } else {
  4672. RtlLeaveCriticalSection(&PerServerListLock);
  4673. }
  4674. //
  4675. // if we get here, we need to let the license server engine actually free it's original handle, either
  4676. // because it wasn't on our list or the ref count (i.e., number of acquires) has been matched by a
  4677. // number of frees.
  4678. //
  4679. }
  4680. //
  4681. // end SBS mods
  4682. //
  4683. DispatchFreeLicense(PtrToUlong(*pLicenseHandle) - 1);
  4684. *pLicenseHandle = NULL;
  4685. return STATUS_SUCCESS;
  4686. } // LlsrLicenseFree
  4687. void __RPC_USER LICENSE_HANDLE_rundown(
  4688. LICENSE_HANDLE LicenseHandle
  4689. )
  4690. /*++
  4691. Routine Description: Called by RPC when client quits without calling
  4692. LlsrLicenseFree (i.e. when it crashes)
  4693. Arguments: LicenseHandle - Handle given to client
  4694. Return Value: none
  4695. --*/
  4696. {
  4697. #if DBG
  4698. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  4699. dprintf(TEXT("LLS TRACE: LICENSE_HANDLE_rundown\n"));
  4700. #endif
  4701. if (LicenseHandle != NULL)
  4702. {
  4703. DispatchFreeLicense(PtrToUlong(LicenseHandle) - 1);
  4704. }
  4705. }
  4706. /////////////////////////////////////////////////////////////////////////
  4707. /////////////////////////////////////////////////////////////////////////
  4708. /////////////////////////////////////////////////////////////////////////
  4709. #if DBG
  4710. /////////////////////////////////////////////////////////////////////////
  4711. /////////////////////////////////////////////////////////////////////////
  4712. // Debugging API's
  4713. /////////////////////////////////////////////////////////////////////////
  4714. NTSTATUS
  4715. LlsrDbgTableDump(
  4716. DWORD Table
  4717. )
  4718. /*++
  4719. Routine Description:
  4720. Arguments:
  4721. Return Value:
  4722. --*/
  4723. {
  4724. #if DELAY_INITIALIZATION
  4725. EnsureInitialized();
  4726. #endif
  4727. //
  4728. // FreeHandle is actually TableID
  4729. //
  4730. switch(Table) {
  4731. case SERVICE_TABLE_NUM:
  4732. ServiceListDebugDump();
  4733. break;
  4734. case USER_TABLE_NUM:
  4735. UserListDebugDump();
  4736. break;
  4737. case SID_TABLE_NUM:
  4738. SidListDebugDump();
  4739. break;
  4740. case LICENSE_TABLE_NUM:
  4741. LicenseListDebugDump();
  4742. break;
  4743. case ADD_CACHE_TABLE_NUM:
  4744. AddCacheDebugDump();
  4745. break;
  4746. case MASTER_SERVICE_TABLE_NUM:
  4747. MasterServiceListDebugDump();
  4748. break;
  4749. case SERVICE_FAMILY_TABLE_NUM:
  4750. MasterServiceRootDebugDump();
  4751. break;
  4752. case MAPPING_TABLE_NUM:
  4753. MappingListDebugDump();
  4754. break;
  4755. case SERVER_TABLE_NUM:
  4756. ServerListDebugDump();
  4757. break;
  4758. case SECURE_PRODUCT_TABLE_NUM:
  4759. ProductSecurityListDebugDump();
  4760. break;
  4761. case CERTIFICATE_TABLE_NUM:
  4762. CertDbDebugDump();
  4763. break;
  4764. }
  4765. return STATUS_SUCCESS;
  4766. } // LlsrDbgTableDump
  4767. /////////////////////////////////////////////////////////////////////////
  4768. NTSTATUS
  4769. LlsrDbgTableInfoDump(
  4770. DWORD Table,
  4771. LPTSTR Item
  4772. )
  4773. /*++
  4774. Routine Description:
  4775. Arguments:
  4776. Return Value:
  4777. --*/
  4778. {
  4779. #if DELAY_INITIALIZATION
  4780. EnsureInitialized();
  4781. #endif
  4782. if (NULL == Item)
  4783. {
  4784. return STATUS_INVALID_PARAMETER;
  4785. }
  4786. switch(Table) {
  4787. case SERVICE_TABLE_NUM:
  4788. ServiceListDebugInfoDump((PVOID) Item);
  4789. break;
  4790. case USER_TABLE_NUM:
  4791. UserListDebugInfoDump((PVOID) Item);
  4792. break;
  4793. // case SID_TABLE_NUM:
  4794. // SidListDebugInfoDump((PVOID) Item);
  4795. // break;
  4796. // case LICENSE_TABLE_NUM:
  4797. // LicenseListInfoDebugDump((PVOID) Item);
  4798. // break;
  4799. // case ADD_CACHE_TABLE_NUM:
  4800. // AddCacheDebugDump((PVOID) Item);
  4801. // break;
  4802. case MASTER_SERVICE_TABLE_NUM:
  4803. MasterServiceListDebugInfoDump((PVOID) Item);
  4804. break;
  4805. case SERVICE_FAMILY_TABLE_NUM:
  4806. MasterServiceRootDebugInfoDump((PVOID) Item);
  4807. break;
  4808. case MAPPING_TABLE_NUM:
  4809. MappingListDebugInfoDump((PVOID) Item);
  4810. break;
  4811. case SERVER_TABLE_NUM:
  4812. ServerListDebugInfoDump((PVOID) Item);
  4813. break;
  4814. }
  4815. return STATUS_SUCCESS;
  4816. } // LlsrDbgTableInfoDump
  4817. /////////////////////////////////////////////////////////////////////////
  4818. NTSTATUS
  4819. LlsrDbgTableFlush(
  4820. DWORD Table
  4821. )
  4822. /*++
  4823. Routine Description:
  4824. Arguments:
  4825. Return Value:
  4826. --*/
  4827. {
  4828. UNREFERENCED_PARAMETER(Table);
  4829. return STATUS_SUCCESS;
  4830. } // LlsrDbgTableFlush
  4831. /////////////////////////////////////////////////////////////////////////
  4832. NTSTATUS
  4833. LlsrDbgTraceSet(
  4834. DWORD Flags
  4835. )
  4836. /*++
  4837. Routine Description:
  4838. Arguments:
  4839. Return Value:
  4840. --*/
  4841. {
  4842. TraceFlags = Flags;
  4843. return STATUS_SUCCESS;
  4844. } // LlsrDbgTraceSet
  4845. /////////////////////////////////////////////////////////////////////////
  4846. NTSTATUS
  4847. LlsrDbgConfigDump(
  4848. )
  4849. /*++
  4850. Routine Description:
  4851. Arguments:
  4852. Return Value:
  4853. --*/
  4854. {
  4855. #if DELAY_INITIALIZATION
  4856. EnsureInitialized();
  4857. #endif
  4858. ConfigInfoDebugDump();
  4859. return STATUS_SUCCESS;
  4860. } // LlsrDbgConfigDump
  4861. /////////////////////////////////////////////////////////////////////////
  4862. NTSTATUS
  4863. LlsrDbgReplicationForce(
  4864. )
  4865. /*++
  4866. Routine Description:
  4867. Arguments:
  4868. Return Value:
  4869. --*/
  4870. {
  4871. #if DELAY_INITIALIZATION
  4872. EnsureInitialized();
  4873. #endif
  4874. NtSetEvent( ReplicationEvent, NULL );
  4875. return STATUS_SUCCESS;
  4876. } // LlsrDbgReplicationForce
  4877. /////////////////////////////////////////////////////////////////////////
  4878. NTSTATUS
  4879. LlsrDbgReplicationDeny(
  4880. )
  4881. /*++
  4882. Routine Description:
  4883. Arguments:
  4884. Return Value:
  4885. --*/
  4886. {
  4887. return STATUS_SUCCESS;
  4888. } // LlsrDbgReplicationDeny
  4889. /////////////////////////////////////////////////////////////////////////
  4890. NTSTATUS
  4891. LlsrDbgRegistryUpdateForce(
  4892. )
  4893. /*++
  4894. Routine Description:
  4895. Arguments:
  4896. Return Value:
  4897. --*/
  4898. {
  4899. #if DELAY_INITIALIZATION
  4900. EnsureInitialized();
  4901. #endif
  4902. ServiceListResynch();
  4903. return STATUS_SUCCESS;
  4904. } // LlsrDbgRegistryUpdateForce
  4905. /////////////////////////////////////////////////////////////////////////
  4906. NTSTATUS
  4907. LlsrDbgDatabaseFlush(
  4908. )
  4909. /*++
  4910. Routine Description:
  4911. Arguments:
  4912. Return Value:
  4913. --*/
  4914. {
  4915. #if DELAY_INITIALIZATION
  4916. EnsureInitialized();
  4917. #endif
  4918. LLSDataSave();
  4919. return STATUS_SUCCESS;
  4920. } // LlsrDbgDatabaseFlush
  4921. #endif // #if DBG
  4922. /////////////////////////////////////////////////////////////////////////
  4923. /////////////////////////////////////////////////////////////////////////
  4924. // Extended RPC
  4925. NTSTATUS LlsrProductSecurityGetA(
  4926. LLS_HANDLE Handle,
  4927. LPSTR Product,
  4928. LPBOOL pIsSecure
  4929. )
  4930. /*++
  4931. Routine Description:
  4932. Retrieve the "security" of a product. A product is deemed secure iff
  4933. it requires a secure certificate. In such a case, licenses for the
  4934. product may not be entered via the Honesty ("enter the number of
  4935. licenses you purchased") method.
  4936. NOTE: Not yet implemented. Use LlsrProductSecurityGetW().
  4937. Arguments:
  4938. Handle (LLS_HANDLE)
  4939. An open LLS handle.
  4940. Product (LPSTR)
  4941. The name of the product ("DisplayName") for which to receive the
  4942. security.
  4943. pIsSecure (LPBOOL)
  4944. On return, and if successful, indicates whether the product is
  4945. secure.
  4946. Return Value:
  4947. STATUS_NOT_SUPPORTED.
  4948. --*/
  4949. {
  4950. #if DBG
  4951. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  4952. dprintf(TEXT("LLS TRACE: LlsrProductSecurityGetA\n"));
  4953. #endif
  4954. UNREFERENCED_PARAMETER(Handle);
  4955. UNREFERENCED_PARAMETER(Product);
  4956. if (NULL == pIsSecure)
  4957. {
  4958. return STATUS_INVALID_PARAMETER;
  4959. }
  4960. *pIsSecure = FALSE;
  4961. return STATUS_NOT_SUPPORTED;
  4962. } // LlsrProductSecurityGetA
  4963. /////////////////////////////////////////////////////////////////////////
  4964. NTSTATUS LlsrProductSecurityGetW(
  4965. LLS_HANDLE Handle,
  4966. LPWSTR DisplayName,
  4967. LPBOOL pIsSecure
  4968. )
  4969. /*++
  4970. Routine Description:
  4971. Retrieve the "security" of a product. A product is deemed secure iff
  4972. it requires a secure certificate. In such a case, licenses for the
  4973. product may not be entered via the Honesty ("enter the number of
  4974. licenses you purchased") method.
  4975. Arguments:
  4976. Handle (LLS_HANDLE)
  4977. An open LLS handle.
  4978. Product (LPWSTR)
  4979. The name of the product ("DisplayName") for which to receive the
  4980. security.
  4981. pIsSecure (LPBOOL)
  4982. On return, and if successful, indicates whether the product is
  4983. secure.
  4984. Return Value:
  4985. STATUS_SUCCESS or NTSTATUS error code.
  4986. --*/
  4987. {
  4988. #if DBG
  4989. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  4990. dprintf(TEXT("LLS TRACE: LlsrProductSecurityGetW\n"));
  4991. #endif
  4992. UNREFERENCED_PARAMETER(Handle);
  4993. #if DELAY_INITIALIZATION
  4994. EnsureInitialized();
  4995. #endif
  4996. if (NULL == pIsSecure)
  4997. {
  4998. return STATUS_INVALID_PARAMETER;
  4999. }
  5000. RtlAcquireResourceShared( &LocalServiceListLock, TRUE );
  5001. *pIsSecure = ServiceIsSecure( DisplayName );
  5002. RtlReleaseResource( &LocalServiceListLock );
  5003. return STATUS_SUCCESS;
  5004. } // LlsrProductSecurityGetW
  5005. /////////////////////////////////////////////////////////////////////////
  5006. NTSTATUS LlsrProductSecuritySetA(
  5007. LLS_HANDLE Handle,
  5008. LPSTR Product
  5009. )
  5010. /*++
  5011. Routine Description:
  5012. Flags the given product as secure. A product is deemed secure iff
  5013. it requires a secure certificate. In such a case, licenses for the
  5014. product may not be entered via the Honesty ("enter the number of
  5015. licenses you purchased") method.
  5016. This designation is not reversible and is propagated up the
  5017. replication tree.
  5018. NOTE: Not yet implemented. Use LlsrProductSecuritySetW().
  5019. Arguments:
  5020. Handle (LLS_HANDLE)
  5021. An open LLS handle.
  5022. Product (LPSTR)
  5023. The name of the product ("DisplayName") for which to activate
  5024. security.
  5025. Return Value:
  5026. STATUS_NOT_SUPPORTED.
  5027. --*/
  5028. {
  5029. #if DBG
  5030. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  5031. dprintf(TEXT("LLS TRACE: LlsrProductSecuritySetA\n"));
  5032. #endif
  5033. UNREFERENCED_PARAMETER(Handle);
  5034. UNREFERENCED_PARAMETER(Product);
  5035. return STATUS_NOT_SUPPORTED;
  5036. } // LlsrProductSecuritySetA
  5037. /////////////////////////////////////////////////////////////////////////
  5038. NTSTATUS LlsrProductSecuritySetW(
  5039. LLS_HANDLE Handle,
  5040. LPWSTR DisplayName
  5041. )
  5042. /*++
  5043. Routine Description:
  5044. Flags the given product as secure. A product is deemed secure iff
  5045. it requires a secure certificate. In such a case, licenses for the
  5046. product may not be entered via the Honesty ("enter the number of
  5047. licenses you purchased") method.
  5048. This designation is not reversible and is propagated up the
  5049. replication tree.
  5050. Arguments:
  5051. Handle (LLS_HANDLE)
  5052. An open LLS handle.
  5053. Product (LPWSTR)
  5054. The name of the product ("DisplayName") for which to activate
  5055. security.
  5056. Return Value:
  5057. STATUS_SUCCESS or NTSTATUS error code.
  5058. --*/
  5059. {
  5060. NTSTATUS nt;
  5061. UNREFERENCED_PARAMETER(Handle);
  5062. #if DBG
  5063. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  5064. dprintf(TEXT("LLS TRACE: LlsrProductSecuritySetW\n"));
  5065. #endif
  5066. #if DELAY_INITIALIZATION
  5067. EnsureInitialized();
  5068. #endif
  5069. if (NULL == DisplayName)
  5070. {
  5071. return STATUS_INVALID_PARAMETER;
  5072. }
  5073. nt = ServiceSecuritySet( DisplayName );
  5074. return nt;
  5075. } // LlsrProductSecuritySetW
  5076. /////////////////////////////////////////////////////////////////////////
  5077. NTSTATUS
  5078. LlsrProductLicensesGetA(
  5079. LLS_HANDLE Handle,
  5080. LPSTR DisplayName,
  5081. DWORD Mode,
  5082. LPDWORD pQuantity )
  5083. /*++
  5084. Routine Description:
  5085. Returns the number of licenses installed for use in the given mode.
  5086. NOTE: Not yet implemented. Use LlsrProductLicensesGetW().
  5087. Arguments:
  5088. Handle (LLS_HANDLE)
  5089. An open LLS handle.
  5090. Product (LPSTR)
  5091. The name of the product for which to tally licenses.
  5092. Mode (DWORD)
  5093. Mode for which to tally licenses.
  5094. pQuantity (LPDWORD)
  5095. On return (and if successful), holds the total number of licenses
  5096. for use by the given product in the given license mode.
  5097. Return Value:
  5098. STATUS_NOT_SUPPORTED.
  5099. --*/
  5100. {
  5101. #if DBG
  5102. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  5103. dprintf(TEXT("LLS TRACE: LlsProductLicensesGetA\n"));
  5104. #endif
  5105. UNREFERENCED_PARAMETER(Handle);
  5106. UNREFERENCED_PARAMETER(DisplayName);
  5107. UNREFERENCED_PARAMETER(Mode);
  5108. if (NULL == pQuantity)
  5109. {
  5110. return STATUS_INVALID_PARAMETER;
  5111. }
  5112. *pQuantity = 0;
  5113. return STATUS_NOT_SUPPORTED;
  5114. } // LlsProductLicensesGetA
  5115. /////////////////////////////////////////////////////////////////////////
  5116. NTSTATUS
  5117. LlsrProductLicensesGetW(
  5118. LLS_HANDLE Handle,
  5119. LPWSTR DisplayName,
  5120. DWORD Mode,
  5121. LPDWORD pQuantity )
  5122. /*++
  5123. Routine Description:
  5124. Returns the number of licenses installed for use in the given mode.
  5125. Arguments:
  5126. Handle (LLS_HANDLE)
  5127. An open LLS handle.
  5128. Product (LPWSTR)
  5129. The name of the product for which to tally licenses.
  5130. Mode (DWORD)
  5131. Mode for which to tally licenses.
  5132. pQuantity (LPDWORD)
  5133. On return (and if successful), holds the total number of licenses
  5134. for use by the given product in the given license mode.
  5135. Return Value:
  5136. STATUS_SUCCESS or NTSTATUS error code.
  5137. --*/
  5138. {
  5139. HRESULT hr;
  5140. UNREFERENCED_PARAMETER(Handle);
  5141. #if DBG
  5142. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  5143. dprintf(TEXT("LLS TRACE: LlsProductLicensesGetW\n"));
  5144. #endif
  5145. #if DELAY_INITIALIZATION
  5146. EnsureInitialized();
  5147. #endif
  5148. if (NULL == pQuantity)
  5149. {
  5150. return STATUS_INVALID_PARAMETER;
  5151. }
  5152. *pQuantity = 0;
  5153. if ( !Mode || ServiceIsSecure( DisplayName ) )
  5154. {
  5155. // get limit from purchase list
  5156. *pQuantity = ProductLicensesGet( DisplayName, Mode );
  5157. }
  5158. else
  5159. {
  5160. DWORD i;
  5161. LocalServiceListUpdate();
  5162. LocalServerServiceListUpdate();
  5163. ServiceListResynch();
  5164. RtlAcquireResourceShared( &LocalServiceListLock, TRUE );
  5165. // get limit from concurrent limit setting from the registry
  5166. for ( i=0; i < LocalServiceListSize; i++ )
  5167. {
  5168. if ( !lstrcmpi( LocalServiceList[i]->DisplayName, DisplayName ) )
  5169. {
  5170. // get concurrent limit straight from the registry, not from LocalServiceList!
  5171. // (if the mode is set to per seat, the per server licenses in the
  5172. // LocalServiceList will always be 0!)
  5173. TCHAR szKeyName[ 512 ];
  5174. HKEY hKeyService;
  5175. DWORD dwSize;
  5176. DWORD dwType;
  5177. hr = StringCbPrintf( szKeyName, sizeof(szKeyName), TEXT("System\\CurrentControlSet\\Services\\LicenseInfo\\%s"), LocalServiceList[i]->Name );
  5178. ASSERT(SUCCEEDED(hr));
  5179. // if error encountered, return STATUS_SUCCESS with *pQuantity = 0
  5180. if ( STATUS_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_READ, &hKeyService ) )
  5181. {
  5182. dwSize = sizeof( *pQuantity );
  5183. RegQueryValueEx( hKeyService, TEXT("ConcurrentLimit"), NULL, &dwType, (LPBYTE) pQuantity, &dwSize );
  5184. RegCloseKey( hKeyService );
  5185. }
  5186. break;
  5187. }
  5188. }
  5189. RtlReleaseResource( &LocalServiceListLock );
  5190. }
  5191. return STATUS_SUCCESS;
  5192. } // LlsProductLicensesGetW
  5193. /////////////////////////////////////////////////////////////////////////
  5194. NTSTATUS
  5195. LlsrCertificateClaimEnumA(
  5196. LLS_HANDLE Handle,
  5197. DWORD LicenseLevel,
  5198. PLLS_LICENSE_INFOA LicensePtr,
  5199. PLLS_CERTIFICATE_CLAIM_ENUM_STRUCTA TargetInfo )
  5200. /*++
  5201. Routine Description:
  5202. Enumerates the servers on which a given secure certificate is installed.
  5203. This function is normally invoked when an attempt to add licenses from
  5204. a certificate is denied.
  5205. NOTE: Not yet implemented. Use LlsrCertificateClaimEnumW().
  5206. Arguments:
  5207. Handle (LLS_HANDLE)
  5208. An open LLS handle.
  5209. LicenseLevel (DWORD)
  5210. The level of the license structure pointed to by pLicenseInfo.
  5211. LicensePtr (PLLS_LICENSE_INFOA)
  5212. Describes a license for which the certificate targets are requested.
  5213. TargetInfo (PLLS_CERTIFICATE_CLAIM_ENUM_STRUCTA)
  5214. Container in which to return the target information.
  5215. Return Value:
  5216. STATUS_NOT_SUPPORTED.
  5217. --*/
  5218. {
  5219. #if DBG
  5220. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  5221. dprintf(TEXT("LLS TRACE: LlsrCertificateClaimEnumA\n"));
  5222. #endif
  5223. UNREFERENCED_PARAMETER(Handle);
  5224. UNREFERENCED_PARAMETER(LicenseLevel);
  5225. UNREFERENCED_PARAMETER(LicensePtr);
  5226. UNREFERENCED_PARAMETER(TargetInfo);
  5227. return STATUS_NOT_SUPPORTED;
  5228. } // LlsrCertificateClaimEnumA
  5229. /////////////////////////////////////////////////////////////////////////
  5230. NTSTATUS
  5231. LlsrCertificateClaimEnumW(
  5232. LLS_HANDLE Handle,
  5233. DWORD LicenseLevel,
  5234. PLLS_LICENSE_INFOW LicensePtr,
  5235. PLLS_CERTIFICATE_CLAIM_ENUM_STRUCTW TargetInfo )
  5236. /*++
  5237. Routine Description:
  5238. Enumerates the servers on which a given secure certificate is installed.
  5239. This function is normally invoked when an attempt to add licenses from
  5240. a certificate is denied.
  5241. Arguments:
  5242. Handle (LLS_HANDLE)
  5243. An open LLS handle.
  5244. LicenseLevel (DWORD)
  5245. The level of the license structure pointed to by pLicenseInfo.
  5246. LicensePtr (PLLS_LICENSE_INFOW)
  5247. Describes a license for which the certificate targets are requested.
  5248. TargetInfo (PLLS_CERTIFICATE_CLAIM_ENUM_STRUCTA)
  5249. Container in which to return the target information.
  5250. Return Value:
  5251. STATUS_SUCCESS or NTSTATUS error code.
  5252. --*/
  5253. {
  5254. NTSTATUS nt;
  5255. UNREFERENCED_PARAMETER(Handle);
  5256. #if DBG
  5257. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  5258. dprintf(TEXT("LLS TRACE: LlsrCertificateClaimEnumW\n"));
  5259. #endif
  5260. #if DELAY_INITIALIZATION
  5261. EnsureInitialized();
  5262. #endif
  5263. RtlAcquireResourceShared( &CertDbHeaderListLock, TRUE );
  5264. if ((NULL == TargetInfo) || (NULL == LicensePtr))
  5265. {
  5266. return STATUS_INVALID_PARAMETER;
  5267. }
  5268. if ( ( 1 != LicenseLevel ) || ( 0 != TargetInfo->Level ) )
  5269. {
  5270. return STATUS_INVALID_LEVEL;
  5271. }
  5272. if (TargetInfo->LlsCertificateClaimInfo.Level0 == NULL)
  5273. {
  5274. return STATUS_INVALID_PARAMETER;
  5275. }
  5276. nt = CertDbClaimsGet( (PLLS_LICENSE_INFO_1) &LicensePtr->LicenseInfo1,
  5277. &TargetInfo->LlsCertificateClaimInfo.Level0->EntriesRead,
  5278. (PLLS_CERTIFICATE_CLAIM_INFO_0 *) &TargetInfo->LlsCertificateClaimInfo.Level0->Buffer );
  5279. if ( STATUS_SUCCESS != nt )
  5280. {
  5281. TargetInfo->LlsCertificateClaimInfo.Level0->EntriesRead = 0;
  5282. TargetInfo->LlsCertificateClaimInfo.Level0->Buffer = NULL;
  5283. }
  5284. return nt;
  5285. } // LlsrCertificateClaimEnumW
  5286. void LlsrCertificateClaimEnumW_notify_flag(
  5287. boolean fNotify
  5288. )
  5289. {
  5290. if (fNotify)
  5291. {
  5292. RtlReleaseResource( &CertDbHeaderListLock );
  5293. }
  5294. }
  5295. /////////////////////////////////////////////////////////////////////////
  5296. NTSTATUS
  5297. LlsrCertificateClaimAddCheckA(
  5298. LLS_HANDLE Handle,
  5299. DWORD LicenseLevel,
  5300. PLLS_LICENSE_INFOA LicensePtr,
  5301. LPBOOL pbMayInstall )
  5302. /*++
  5303. Routine Description:
  5304. Verify that no more licenses from a given certificate are installed in
  5305. a licensing enterprise than are allowed by the certificate.
  5306. NOTE: Not yet implemented. Use LlsrCertificateClaimAddCheckW().
  5307. Arguments:
  5308. Handle (LLS_HANDLE)
  5309. An open LLS handle.
  5310. LicenseLevel (DWORD)
  5311. The level of the license structure pointed to by pLicenseInfo.
  5312. LicensePtr (PLLS_LICENSE_INFOA)
  5313. Describes a license for which permission is requested.
  5314. pbMayInstall (LPBOOL)
  5315. On return (and if successful), indicates whether the certificate
  5316. may be legally installed.
  5317. Return Value:
  5318. STATUS_NOT_SUPPORTED.
  5319. --*/
  5320. {
  5321. #if DBG
  5322. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  5323. dprintf(TEXT("LLS TRACE: LlsrCertificateClaimAddCheckA\n"));
  5324. #endif
  5325. UNREFERENCED_PARAMETER(Handle);
  5326. UNREFERENCED_PARAMETER(LicenseLevel);
  5327. UNREFERENCED_PARAMETER(LicensePtr);
  5328. if (NULL == pbMayInstall)
  5329. {
  5330. return STATUS_INVALID_PARAMETER;
  5331. }
  5332. *pbMayInstall = FALSE;
  5333. return STATUS_NOT_SUPPORTED;
  5334. } // LlsrCertificateClaimAddCheckA
  5335. /////////////////////////////////////////////////////////////////////////
  5336. NTSTATUS
  5337. LlsrCertificateClaimAddCheckW(
  5338. LLS_HANDLE Handle,
  5339. DWORD LicenseLevel,
  5340. PLLS_LICENSE_INFOW LicensePtr,
  5341. LPBOOL pbMayInstall )
  5342. /*++
  5343. Routine Description:
  5344. Verify that no more licenses from a given certificate are installed in
  5345. a licensing enterprise than are allowed by the certificate.
  5346. Arguments:
  5347. Handle (LLS_HANDLE)
  5348. An open LLS handle.
  5349. LicenseLevel (DWORD)
  5350. The level of the license structure pointed to by pLicenseInfo.
  5351. LicensePtr (PLLS_LICENSE_INFOW)
  5352. Describes a license for which permission is requested.
  5353. pbMayInstall (LPBOOL)
  5354. On return (and if successful), indicates whether the certificate
  5355. may be legally installed.
  5356. Return Value:
  5357. STATUS_SUCCESS or NTSTATUS error code.
  5358. --*/
  5359. {
  5360. NTSTATUS nt;
  5361. UNREFERENCED_PARAMETER(Handle);
  5362. #if DBG
  5363. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  5364. dprintf(TEXT("LLS TRACE: LlsrCertificateClaimAddCheckW\n"));
  5365. #endif
  5366. #if DELAY_INITIALIZATION
  5367. EnsureInitialized();
  5368. #endif
  5369. if ((NULL == pbMayInstall) || (NULL == LicensePtr))
  5370. {
  5371. nt = STATUS_INVALID_PARAMETER;
  5372. goto error;
  5373. }
  5374. *pbMayInstall = FALSE;
  5375. if ( 1 != LicenseLevel )
  5376. {
  5377. nt = STATUS_INVALID_LEVEL;
  5378. goto error;
  5379. }
  5380. *pbMayInstall = CertDbClaimApprove( (PLLS_LICENSE_INFO_1) &LicensePtr->LicenseInfo1 );
  5381. nt = STATUS_SUCCESS;
  5382. error:
  5383. if (NULL != LicensePtr)
  5384. {
  5385. // PNAMEW are declared as dont_free, we should free them
  5386. if (0 == LicenseLevel)
  5387. {
  5388. if (NULL != LicensePtr->LicenseInfo0.Product)
  5389. {
  5390. MIDL_user_free(LicensePtr->LicenseInfo0.Product);
  5391. }
  5392. if (NULL != LicensePtr->LicenseInfo0.Admin)
  5393. {
  5394. MIDL_user_free(LicensePtr->LicenseInfo0.Admin);
  5395. }
  5396. if (NULL != LicensePtr->LicenseInfo0.Comment)
  5397. {
  5398. MIDL_user_free(LicensePtr->LicenseInfo0.Comment);
  5399. }
  5400. }
  5401. if (1 == LicenseLevel)
  5402. {
  5403. if (NULL != LicensePtr->LicenseInfo1.Product)
  5404. {
  5405. MIDL_user_free(LicensePtr->LicenseInfo1.Product);
  5406. }
  5407. if (NULL != LicensePtr->LicenseInfo1.Admin)
  5408. {
  5409. MIDL_user_free(LicensePtr->LicenseInfo1.Admin);
  5410. }
  5411. if (NULL != LicensePtr->LicenseInfo1.Comment)
  5412. {
  5413. MIDL_user_free(LicensePtr->LicenseInfo1.Comment);
  5414. }
  5415. if (NULL != LicensePtr->LicenseInfo1.Vendor)
  5416. {
  5417. MIDL_user_free(LicensePtr->LicenseInfo1.Vendor);
  5418. }
  5419. if (NULL != LicensePtr->LicenseInfo1.Source)
  5420. {
  5421. MIDL_user_free(LicensePtr->LicenseInfo1.Source);
  5422. }
  5423. }
  5424. }
  5425. return nt;
  5426. } // LlsrCertificateClaimAddCheckW
  5427. /////////////////////////////////////////////////////////////////////////
  5428. NTSTATUS
  5429. LlsrCertificateClaimAddA(
  5430. LLS_HANDLE Handle,
  5431. LPSTR ServerName,
  5432. DWORD LicenseLevel,
  5433. PLLS_LICENSE_INFOA LicensePtr )
  5434. /*++
  5435. Routine Description:
  5436. Declare a number of licenses from a given certificate as being installed
  5437. on the target machine.
  5438. NOTE: Not yet implemented. Use LlsCertificateClaimAddW().
  5439. Arguments:
  5440. Handle (LLS_HANDLE)
  5441. An open LLS handle.
  5442. ServerName (LPWSTR)
  5443. Name of the server on which the licenses are installed.
  5444. LicenseLevel (DWORD)
  5445. The level of the license structure pointed to by pLicenseInfo.
  5446. LicensePtr (PLLS_LICENSE_INFOA)
  5447. Describes the installed license.
  5448. Return Value:
  5449. STATUS_NOT_SUPPORTED.
  5450. --*/
  5451. {
  5452. #if DBG
  5453. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  5454. dprintf(TEXT("LLS TRACE: LlsrCertificateClaimAddA\n"));
  5455. #endif
  5456. UNREFERENCED_PARAMETER(Handle);
  5457. UNREFERENCED_PARAMETER(ServerName);
  5458. UNREFERENCED_PARAMETER(LicenseLevel);
  5459. UNREFERENCED_PARAMETER(LicensePtr);
  5460. return STATUS_NOT_SUPPORTED;
  5461. } // LlsrCertificateClaimAddA
  5462. /////////////////////////////////////////////////////////////////////////
  5463. NTSTATUS
  5464. LlsrCertificateClaimAddW(
  5465. LLS_HANDLE Handle,
  5466. LPWSTR ServerName,
  5467. DWORD LicenseLevel,
  5468. PLLS_LICENSE_INFOW LicensePtr )
  5469. /*++
  5470. Routine Description:
  5471. Declare a number of licenses from a given certificate as being installed
  5472. on the target machine.
  5473. Arguments:
  5474. Handle (LLS_HANDLE)
  5475. An open LLS handle to the target license server.
  5476. ServerName (LPWSTR)
  5477. Name of the server on which the licenses are installed.
  5478. LicenseLevel (DWORD)
  5479. The level of the license structure pointed to by pLicenseInfo.
  5480. LicensePtr (PLLS_LICENSE_INFOW)
  5481. Describes the installed license.
  5482. Return Value:
  5483. STATUS_SUCCESS or NTSTATUS error code.
  5484. --*/
  5485. {
  5486. NTSTATUS nt;
  5487. UNREFERENCED_PARAMETER(Handle);
  5488. #if DBG
  5489. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  5490. dprintf(TEXT("LLS TRACE: LlsrCertificateClaimAddW\n"));
  5491. #endif
  5492. #if DELAY_INITIALIZATION
  5493. EnsureInitialized();
  5494. #endif
  5495. if ( 1 != LicenseLevel )
  5496. {
  5497. nt = STATUS_INVALID_LEVEL;
  5498. goto error;
  5499. }
  5500. if (NULL == LicensePtr)
  5501. {
  5502. nt = STATUS_INVALID_PARAMETER;
  5503. goto error;
  5504. }
  5505. nt = CertDbClaimEnter( ServerName, (PLLS_LICENSE_INFO_1) &LicensePtr->LicenseInfo1, FALSE, 0 );
  5506. if ( STATUS_SUCCESS == nt )
  5507. {
  5508. nt = CertDbSave();
  5509. }
  5510. error:
  5511. if (NULL != LicensePtr)
  5512. {
  5513. // PNAMEW are declared as dont_free, we should free them
  5514. if (0 == LicenseLevel)
  5515. {
  5516. if (NULL != LicensePtr->LicenseInfo0.Product)
  5517. {
  5518. MIDL_user_free(LicensePtr->LicenseInfo0.Product);
  5519. }
  5520. if (NULL != LicensePtr->LicenseInfo0.Admin)
  5521. {
  5522. MIDL_user_free(LicensePtr->LicenseInfo0.Admin);
  5523. }
  5524. if (NULL != LicensePtr->LicenseInfo0.Comment)
  5525. {
  5526. MIDL_user_free(LicensePtr->LicenseInfo0.Comment);
  5527. }
  5528. }
  5529. if (1 == LicenseLevel)
  5530. {
  5531. if (NULL != LicensePtr->LicenseInfo1.Product)
  5532. {
  5533. MIDL_user_free(LicensePtr->LicenseInfo1.Product);
  5534. }
  5535. if (NULL != LicensePtr->LicenseInfo1.Admin)
  5536. {
  5537. MIDL_user_free(LicensePtr->LicenseInfo1.Admin);
  5538. }
  5539. if (NULL != LicensePtr->LicenseInfo1.Comment)
  5540. {
  5541. MIDL_user_free(LicensePtr->LicenseInfo1.Comment);
  5542. }
  5543. if (NULL != LicensePtr->LicenseInfo1.Vendor)
  5544. {
  5545. MIDL_user_free(LicensePtr->LicenseInfo1.Vendor);
  5546. }
  5547. if (NULL != LicensePtr->LicenseInfo1.Source)
  5548. {
  5549. MIDL_user_free(LicensePtr->LicenseInfo1.Source);
  5550. }
  5551. }
  5552. }
  5553. return nt;
  5554. } // LlsrCertificateClaimAddW
  5555. /////////////////////////////////////////////////////////////////////////
  5556. NTSTATUS
  5557. LlsrReplicationCertDbAddW(
  5558. LLS_REPL_HANDLE Handle,
  5559. DWORD Level,
  5560. REPL_CERTIFICATES Certificates )
  5561. /*++
  5562. Routine Description:
  5563. Called as an optional part of replication, this function receives
  5564. the contents of the remote certificate database.
  5565. Arguments:
  5566. Handle (LLS_REPL_HANDLE)
  5567. An open replication handle.
  5568. Level (DWORD)
  5569. Level of replicated certificate information.
  5570. Certificates (REPL_CERTIFICATES)
  5571. Replicated certificate information.
  5572. Return Value:
  5573. STATUS_SUCCESS or STATUS_INVALID_LEVEL.
  5574. --*/
  5575. {
  5576. NTSTATUS nt = STATUS_SUCCESS;
  5577. REPL_CONTEXT_TYPE * pClient;
  5578. #if DBG
  5579. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  5580. dprintf(TEXT("LLS TRACE: LlsrReplicationCertDbAddW\n"));
  5581. #endif
  5582. #if DELAY_INITIALIZATION
  5583. EnsureInitialized();
  5584. #endif
  5585. if ( ( 0 != Level )
  5586. || ( ( NULL != Certificates )
  5587. && ( ( 0 != Certificates->Level0.ClaimLevel )
  5588. || ( 0 != Certificates->Level0.HeaderLevel ) ) ) )
  5589. {
  5590. nt = STATUS_INVALID_LEVEL;
  5591. }
  5592. else
  5593. {
  5594. pClient = (REPL_CONTEXT_TYPE *) Handle;
  5595. try
  5596. {
  5597. if ((NULL == pClient) || (0 != memcmp(pClient->Signature,LLS_REPL_SIG,LLS_REPL_SIG_SIZE)))
  5598. {
  5599. // free all data because it is dont_free
  5600. if (NULL != Certificates)
  5601. {
  5602. if (NULL != Certificates->Level0.Strings)
  5603. {
  5604. MIDL_user_free(Certificates->Level0.Strings);
  5605. }
  5606. if (NULL != Certificates->Level0.HeaderContainer.Level0.Headers)
  5607. {
  5608. MIDL_user_free(Certificates->Level0.HeaderContainer.Level0.Headers);
  5609. }
  5610. if (NULL != Certificates->Level0.ClaimContainer.Level0.Claims)
  5611. {
  5612. MIDL_user_free(Certificates->Level0.ClaimContainer.Level0.Claims);
  5613. }
  5614. MIDL_user_free( Certificates );
  5615. }
  5616. return STATUS_INVALID_PARAMETER;
  5617. }
  5618. if (pClient->CertDbSent)
  5619. {
  5620. // don't accept more than one Add
  5621. // free all data because it is dont_free
  5622. if (NULL != Certificates)
  5623. {
  5624. if (NULL != Certificates->Level0.Strings)
  5625. {
  5626. MIDL_user_free(Certificates->Level0.Strings);
  5627. }
  5628. if (NULL != Certificates->Level0.HeaderContainer.Level0.Headers)
  5629. {
  5630. MIDL_user_free(Certificates->Level0.HeaderContainer.Level0.Headers);
  5631. }
  5632. if (NULL != Certificates->Level0.ClaimContainer.Level0.Claims)
  5633. {
  5634. MIDL_user_free(Certificates->Level0.ClaimContainer.Level0.Claims);
  5635. }
  5636. MIDL_user_free( Certificates );
  5637. }
  5638. return HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
  5639. }
  5640. pClient->CertDbSent = TRUE;
  5641. if ( NULL != Certificates )
  5642. {
  5643. pClient->CertDbProductStringSize = Certificates->Level0.StringSize;
  5644. pClient->CertDbProductStrings = Certificates->Level0.Strings;
  5645. pClient->CertDbNumHeaders = Certificates->Level0.HeaderContainer.Level0.NumHeaders;
  5646. pClient->CertDbHeaders = Certificates->Level0.HeaderContainer.Level0.Headers;
  5647. pClient->CertDbNumClaims = Certificates->Level0.ClaimContainer.Level0.NumClaims;
  5648. pClient->CertDbClaims = Certificates->Level0.ClaimContainer.Level0.Claims;
  5649. // free container only, rest of data will be free in ReplClose
  5650. MIDL_user_free( Certificates );
  5651. }
  5652. } except(EXCEPTION_EXECUTE_HANDLER ) {
  5653. nt = GetExceptionCode();
  5654. }
  5655. }
  5656. return nt;
  5657. } // LlsrReplicationCertDbAddW
  5658. /////////////////////////////////////////////////////////////////////////
  5659. NTSTATUS
  5660. LlsrReplicationProductSecurityAddW(
  5661. LLS_REPL_HANDLE Handle,
  5662. DWORD Level,
  5663. REPL_SECURE_PRODUCTS SecureProducts )
  5664. /*++
  5665. Routine Description:
  5666. Called as an optional part of replication, this function receives
  5667. the list of products which require secure certificates.
  5668. Arguments:
  5669. Handle (LLS_REPL_HANDLE)
  5670. An open replication handle.
  5671. Level (DWORD)
  5672. Level of replicated secure product information.
  5673. SecureProducts (REPL_SECURE_PRODUCTS)
  5674. Replicated secure product information.
  5675. Return Value:
  5676. STATUS_SUCCESS or STATUS_INVALID_LEVEL.
  5677. --*/
  5678. {
  5679. NTSTATUS nt = STATUS_SUCCESS;
  5680. REPL_CONTEXT_TYPE * pClient;
  5681. #if DBG
  5682. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  5683. dprintf(TEXT("LLS TRACE: LlsrReplicationProductSecurityAddW\n"));
  5684. #endif
  5685. #if DELAY_INITIALIZATION
  5686. EnsureInitialized();
  5687. #endif
  5688. if ( 0 != Level )
  5689. {
  5690. nt = STATUS_INVALID_LEVEL;
  5691. }
  5692. else
  5693. {
  5694. pClient = (REPL_CONTEXT_TYPE *) Handle;
  5695. try
  5696. {
  5697. if ((NULL == pClient) || (0 != memcmp(pClient->Signature,LLS_REPL_SIG,LLS_REPL_SIG_SIZE)))
  5698. {
  5699. // free all data because it is dont_free
  5700. if (NULL != SecureProducts)
  5701. {
  5702. if (NULL != SecureProducts->Level0.Strings)
  5703. {
  5704. MIDL_user_free( SecureProducts->Level0.Strings );
  5705. }
  5706. MIDL_user_free( SecureProducts );
  5707. }
  5708. return STATUS_INVALID_PARAMETER;
  5709. }
  5710. if (pClient->ProductSecuritySent)
  5711. {
  5712. // don't accept more than one Add
  5713. // free all data because it is dont_free
  5714. if (NULL != SecureProducts)
  5715. {
  5716. if (NULL != SecureProducts->Level0.Strings)
  5717. {
  5718. MIDL_user_free( SecureProducts->Level0.Strings );
  5719. }
  5720. MIDL_user_free( SecureProducts );
  5721. }
  5722. return HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
  5723. }
  5724. pClient->ProductSecuritySent = TRUE;
  5725. if ( NULL != SecureProducts )
  5726. {
  5727. pClient->ProductSecurityStringSize = SecureProducts->Level0.StringSize;
  5728. pClient->ProductSecurityStrings = SecureProducts->Level0.Strings;
  5729. // free container only, rest of data will be free in ReplClose
  5730. MIDL_user_free( SecureProducts );
  5731. }
  5732. } except(EXCEPTION_EXECUTE_HANDLER ) {
  5733. nt = GetExceptionCode();
  5734. }
  5735. }
  5736. return nt;
  5737. } // LlsrReplicationProductSecurityAddW
  5738. /////////////////////////////////////////////////////////////////////////
  5739. NTSTATUS
  5740. LlsrReplicationUserAddExW(
  5741. LLS_REPL_HANDLE Handle,
  5742. DWORD Level,
  5743. REPL_USERS Users )
  5744. /*++
  5745. Routine Description:
  5746. Replacement for LlsrReplicationUserAddW(). (This function, unlike its
  5747. counterpart, supports structure levels.) This function replicates the
  5748. user list.
  5749. Arguments:
  5750. Handle (LLS_REPL_HANDLE)
  5751. An open replication handle.
  5752. Level (DWORD)
  5753. Level of replicated user information.
  5754. Users (REPL_USERS)
  5755. Replicated user information.
  5756. Return Value:
  5757. STATUS_SUCCESS or STATUS_INVALID_LEVEL.
  5758. --*/
  5759. {
  5760. NTSTATUS nt = STATUS_SUCCESS;
  5761. REPL_CONTEXT_TYPE * pClient;
  5762. #if DBG
  5763. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  5764. dprintf(TEXT("LLS TRACE: LlsrReplicationUserAddExW\n"));
  5765. #endif
  5766. #if DELAY_INITIALIZATION
  5767. EnsureInitialized();
  5768. #endif
  5769. if ( ( 0 != Level ) && ( 1 != Level ) )
  5770. {
  5771. nt = STATUS_INVALID_LEVEL;
  5772. }
  5773. else
  5774. {
  5775. pClient = (REPL_CONTEXT_TYPE *) Handle;
  5776. try
  5777. {
  5778. if ((NULL == pClient) || (0 != memcmp(pClient->Signature,LLS_REPL_SIG,LLS_REPL_SIG_SIZE)))
  5779. {
  5780. // free all data because it is dont_free
  5781. if (NULL != Users)
  5782. {
  5783. if (0 == Level )
  5784. {
  5785. if (NULL != Users->Level0.Users)
  5786. {
  5787. MIDL_user_free( Users->Level0.Users );
  5788. }
  5789. }
  5790. if (1 == Level )
  5791. {
  5792. if (NULL != Users->Level1.Users)
  5793. {
  5794. MIDL_user_free( Users->Level1.Users );
  5795. }
  5796. }
  5797. MIDL_user_free( Users );
  5798. }
  5799. return STATUS_INVALID_PARAMETER;
  5800. }
  5801. if (pClient->UsersSent)
  5802. {
  5803. // don't accept more than one Add
  5804. // free all data because it is dont_free
  5805. if (NULL != Users)
  5806. {
  5807. if (0 == Level )
  5808. {
  5809. if (NULL != Users->Level0.Users)
  5810. {
  5811. MIDL_user_free( Users->Level0.Users );
  5812. }
  5813. }
  5814. if (1 == Level )
  5815. {
  5816. if (NULL != Users->Level1.Users)
  5817. {
  5818. MIDL_user_free( Users->Level1.Users );
  5819. }
  5820. }
  5821. MIDL_user_free( Users );
  5822. }
  5823. return HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
  5824. }
  5825. pClient->UsersSent = TRUE;
  5826. pClient->UserLevel = Level;
  5827. if ( NULL != Users )
  5828. {
  5829. if ( 0 == Level )
  5830. {
  5831. pClient->UserTableSize = Users->Level0.NumUsers;
  5832. pClient->Users = Users->Level0.Users;
  5833. }
  5834. else
  5835. {
  5836. pClient->UserTableSize = Users->Level1.NumUsers;
  5837. pClient->Users = Users->Level1.Users;
  5838. }
  5839. // free container only, rest of data will be free in ReplClose
  5840. MIDL_user_free( Users );
  5841. }
  5842. } except(EXCEPTION_EXECUTE_HANDLER ) {
  5843. nt = GetExceptionCode();
  5844. }
  5845. }
  5846. return nt;
  5847. } // LlsrReplicationUserAddExW
  5848. NTSTATUS
  5849. LlsrCapabilityGet(
  5850. LLS_HANDLE Handle,
  5851. DWORD cbCapabilities,
  5852. LPBYTE pbCapabilities )
  5853. {
  5854. static DWORD adwCapabilitiesSupported[] =
  5855. {
  5856. LLS_CAPABILITY_SECURE_CERTIFICATES,
  5857. LLS_CAPABILITY_REPLICATE_CERT_DB,
  5858. LLS_CAPABILITY_REPLICATE_PRODUCT_SECURITY,
  5859. LLS_CAPABILITY_REPLICATE_USERS_EX,
  5860. LLS_CAPABILITY_SERVICE_INFO_GETW,
  5861. LLS_CAPABILITY_LOCAL_SERVICE_API,
  5862. (DWORD) -1L
  5863. };
  5864. DWORD i;
  5865. DWORD dwCapByte;
  5866. DWORD dwCapBit;
  5867. UNREFERENCED_PARAMETER(Handle);
  5868. #if DELAY_INITIALIZATION
  5869. EnsureInitialized();
  5870. #endif
  5871. if (NULL == pbCapabilities)
  5872. {
  5873. return STATUS_INVALID_PARAMETER;
  5874. }
  5875. ZeroMemory( pbCapabilities, cbCapabilities );
  5876. for ( i=0; (DWORD) -1L != adwCapabilitiesSupported[ i ]; i++ )
  5877. {
  5878. dwCapByte = adwCapabilitiesSupported[ i ] / 8;
  5879. dwCapBit = adwCapabilitiesSupported[ i ] - 8 * dwCapByte;
  5880. if ( dwCapByte < cbCapabilities )
  5881. {
  5882. pbCapabilities[ dwCapByte ] |= ( 1 << dwCapBit );
  5883. }
  5884. }
  5885. return STATUS_SUCCESS;
  5886. }
  5887. NTSTATUS
  5888. LlsrLocalServiceEnumW(
  5889. LLS_HANDLE Handle,
  5890. PLLS_LOCAL_SERVICE_ENUM_STRUCTW LocalServiceInfo,
  5891. DWORD PrefMaxLen,
  5892. LPDWORD pTotalEntries,
  5893. LPDWORD pResumeHandle )
  5894. {
  5895. NTSTATUS Status = STATUS_SUCCESS;
  5896. PVOID BufPtr = NULL;
  5897. ULONG BufSize = 0;
  5898. ULONG EntriesRead = 0;
  5899. ULONG TotalEntries = 0;
  5900. ULONG i = 0;
  5901. ULONG j = 0;
  5902. const DWORD RecordSize = sizeof( LLS_LOCAL_SERVICE_INFO_0W );
  5903. UNREFERENCED_PARAMETER(Handle);
  5904. #if DBG
  5905. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  5906. dprintf(TEXT("LLS TRACE: LlsrLocalServiceEnumW\n"));
  5907. #endif
  5908. #if DELAY_INITIALIZATION
  5909. EnsureInitialized();
  5910. #endif
  5911. // Need to scan list so get read access.
  5912. RtlAcquireResourceShared(&LocalServiceListLock, TRUE);
  5913. if ((NULL == pTotalEntries) || (NULL == LocalServiceInfo))
  5914. {
  5915. return STATUS_INVALID_PARAMETER;
  5916. }
  5917. *pTotalEntries = 0;
  5918. if ( 0 != LocalServiceInfo->Level )
  5919. {
  5920. return STATUS_INVALID_LEVEL;
  5921. }
  5922. if (LocalServiceInfo->LlsLocalServiceInfo.Level0 == NULL)
  5923. {
  5924. return STATUS_INVALID_PARAMETER;
  5925. }
  5926. // Calculate how many records will fit into PrefMaxLen buffer.
  5927. i = (pResumeHandle != NULL) ? *pResumeHandle : 0;
  5928. while ( ( i < LocalServiceListSize ) && ( BufSize < PrefMaxLen ) )
  5929. {
  5930. BufSize += RecordSize;
  5931. EntriesRead++;
  5932. i++;
  5933. }
  5934. TotalEntries = EntriesRead;
  5935. // If we overflowed the buffer then back up one record.
  5936. if (BufSize > PrefMaxLen)
  5937. {
  5938. BufSize -= RecordSize;
  5939. EntriesRead--;
  5940. }
  5941. // Now walk to the end of the list to see how many more records are still
  5942. // available.
  5943. TotalEntries += LocalServiceListSize - i;
  5944. if (TotalEntries > EntriesRead)
  5945. Status = STATUS_MORE_ENTRIES;
  5946. // Reset Enum to correct place.
  5947. i = (pResumeHandle != NULL) ? *pResumeHandle : 0;
  5948. // We now know how many records will fit into the buffer, so allocate space
  5949. // and fix up pointers so we can copy the information.
  5950. BufPtr = MIDL_user_allocate(BufSize);
  5951. if (BufPtr == NULL)
  5952. {
  5953. Status = STATUS_NO_MEMORY;
  5954. goto LlsrLocalServiceEnumWExit;
  5955. }
  5956. RtlZeroMemory((PVOID) BufPtr, BufSize);
  5957. // Buffers are all setup, so loop through records and copy the data.
  5958. while ((j < EntriesRead) && (i < LocalServiceListSize))
  5959. {
  5960. ((PLLS_LOCAL_SERVICE_INFO_0W) BufPtr)[j].KeyName = LocalServiceList[i]->Name;
  5961. ((PLLS_LOCAL_SERVICE_INFO_0W) BufPtr)[j].DisplayName = LocalServiceList[i]->DisplayName;
  5962. ((PLLS_LOCAL_SERVICE_INFO_0W) BufPtr)[j].FamilyDisplayName = LocalServiceList[i]->FamilyDisplayName;
  5963. ((PLLS_LOCAL_SERVICE_INFO_0W) BufPtr)[j].Mode = LocalServiceList[i]->Mode;
  5964. ((PLLS_LOCAL_SERVICE_INFO_0W) BufPtr)[j].FlipAllow = LocalServiceList[i]->FlipAllow;
  5965. ((PLLS_LOCAL_SERVICE_INFO_0W) BufPtr)[j].ConcurrentLimit = LocalServiceList[i]->ConcurrentLimit;
  5966. ((PLLS_LOCAL_SERVICE_INFO_0W) BufPtr)[j].HighMark = LocalServiceList[i]->HighMark;
  5967. j++;
  5968. i++;
  5969. }
  5970. LlsrLocalServiceEnumWExit:
  5971. #if DBG
  5972. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  5973. dprintf(TEXT(" TotalEntries: %lu EntriesRead: %lu ResumeHandle: 0x%lX\n"), TotalEntries, EntriesRead, i);
  5974. #endif
  5975. *pTotalEntries = TotalEntries;
  5976. if (pResumeHandle != NULL)
  5977. *pResumeHandle = (ULONG) i;
  5978. LocalServiceInfo->LlsLocalServiceInfo.Level0->EntriesRead = EntriesRead;
  5979. LocalServiceInfo->LlsLocalServiceInfo.Level0->Buffer = (PLLS_LOCAL_SERVICE_INFO_0W) BufPtr;
  5980. return Status;
  5981. }
  5982. void LlsrLocalServiceEnumW_notify_flag(
  5983. boolean fNotify
  5984. )
  5985. {
  5986. if (fNotify)
  5987. {
  5988. RtlReleaseResource(&LocalServiceListLock);
  5989. }
  5990. }
  5991. NTSTATUS
  5992. LlsrLocalServiceEnumA(
  5993. LLS_HANDLE Handle,
  5994. PLLS_LOCAL_SERVICE_ENUM_STRUCTA LocalServiceInfo,
  5995. DWORD PrefMaxLen,
  5996. LPDWORD TotalEntries,
  5997. LPDWORD ResumeHandle )
  5998. {
  5999. #if DBG
  6000. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  6001. dprintf(TEXT("LLS TRACE: LlsLocalServiceEnumA\n"));
  6002. #endif
  6003. UNREFERENCED_PARAMETER(Handle);
  6004. UNREFERENCED_PARAMETER(LocalServiceInfo);
  6005. UNREFERENCED_PARAMETER(PrefMaxLen);
  6006. UNREFERENCED_PARAMETER(ResumeHandle);
  6007. if (NULL == TotalEntries)
  6008. {
  6009. return STATUS_INVALID_PARAMETER;
  6010. }
  6011. *TotalEntries = 0;
  6012. return STATUS_NOT_SUPPORTED;
  6013. }
  6014. NTSTATUS
  6015. LlsrLocalServiceAddW(
  6016. LLS_HANDLE Handle,
  6017. DWORD Level,
  6018. PLLS_LOCAL_SERVICE_INFOW LocalServiceInfo )
  6019. {
  6020. NTSTATUS Status;
  6021. #if DBG
  6022. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  6023. dprintf(TEXT("LLS TRACE: LlsrLocalServiceAddW\n"));
  6024. #endif
  6025. #if DELAY_INITIALIZATION
  6026. EnsureInitialized();
  6027. #endif
  6028. if ( 0 != Level )
  6029. {
  6030. Status = STATUS_INVALID_LEVEL;
  6031. }
  6032. else if ( ( NULL == LocalServiceInfo)
  6033. || ( NULL == LocalServiceInfo->LocalServiceInfo0.KeyName )
  6034. || ( NULL == LocalServiceInfo->LocalServiceInfo0.DisplayName )
  6035. || ( NULL == LocalServiceInfo->LocalServiceInfo0.FamilyDisplayName ) )
  6036. {
  6037. Status = STATUS_INVALID_PARAMETER;
  6038. }
  6039. else
  6040. {
  6041. LONG lError;
  6042. HKEY hKeyLicenseInfo;
  6043. HKEY hKeyService;
  6044. DWORD dwDisposition;
  6045. lError = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_KEY_LICENSE, 0, KEY_WRITE, &hKeyLicenseInfo );
  6046. if ( ERROR_SUCCESS == lError )
  6047. {
  6048. // create key
  6049. lError = RegCreateKeyEx( hKeyLicenseInfo, LocalServiceInfo->LocalServiceInfo0.KeyName, 0, NULL, 0, KEY_WRITE, NULL, &hKeyService, &dwDisposition );
  6050. if ( ERROR_SUCCESS == lError )
  6051. {
  6052. // set DisplayName
  6053. lError = RegSetValueEx( hKeyService,
  6054. REG_VALUE_NAME,
  6055. 0,
  6056. REG_SZ,
  6057. (LPBYTE) LocalServiceInfo->LocalServiceInfo0.DisplayName,
  6058. ( sizeof( *LocalServiceInfo->LocalServiceInfo0.DisplayName )
  6059. * ( 1 + lstrlen( LocalServiceInfo->LocalServiceInfo0.DisplayName ) ) ) );
  6060. if ( ERROR_SUCCESS == lError )
  6061. {
  6062. // set FamilyDisplayName
  6063. lError = RegSetValueEx( hKeyService,
  6064. REG_VALUE_FAMILY,
  6065. 0,
  6066. REG_SZ,
  6067. (LPBYTE) LocalServiceInfo->LocalServiceInfo0.FamilyDisplayName,
  6068. ( sizeof( *LocalServiceInfo->LocalServiceInfo0.FamilyDisplayName )
  6069. * ( 1 + lstrlen( LocalServiceInfo->LocalServiceInfo0.FamilyDisplayName ) ) ) );
  6070. }
  6071. RegCloseKey( hKeyService );
  6072. }
  6073. RegCloseKey( hKeyLicenseInfo );
  6074. }
  6075. switch ( lError )
  6076. {
  6077. case ERROR_SUCCESS:
  6078. Status = STATUS_SUCCESS;
  6079. break;
  6080. case ERROR_FILE_NOT_FOUND:
  6081. case ERROR_PATH_NOT_FOUND:
  6082. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  6083. break;
  6084. default:
  6085. Status = STATUS_UNSUCCESSFUL;
  6086. break;
  6087. }
  6088. if ( STATUS_SUCCESS == Status )
  6089. {
  6090. // set remaining items and update LocalServiceList
  6091. Status = LlsrLocalServiceInfoSetW( Handle, LocalServiceInfo->LocalServiceInfo0.KeyName, Level, LocalServiceInfo );
  6092. }
  6093. }
  6094. return Status;
  6095. }
  6096. NTSTATUS
  6097. LlsrLocalServiceAddA(
  6098. LLS_HANDLE Handle,
  6099. DWORD Level,
  6100. PLLS_LOCAL_SERVICE_INFOA LocalServiceInfo )
  6101. {
  6102. #if DBG
  6103. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  6104. dprintf(TEXT("LLS TRACE: LlsLocalServiceAddA\n"));
  6105. #endif
  6106. UNREFERENCED_PARAMETER(Handle);
  6107. UNREFERENCED_PARAMETER(Level);
  6108. UNREFERENCED_PARAMETER(LocalServiceInfo);
  6109. return STATUS_NOT_SUPPORTED;
  6110. }
  6111. NTSTATUS
  6112. LlsrLocalServiceInfoSetW(
  6113. LLS_HANDLE Handle,
  6114. LPWSTR KeyName,
  6115. DWORD Level,
  6116. PLLS_LOCAL_SERVICE_INFOW LocalServiceInfo )
  6117. {
  6118. NTSTATUS Status;
  6119. #if DBG
  6120. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  6121. dprintf(TEXT("LLS TRACE: LlsLocalServiceInfoSetW\n"));
  6122. #endif
  6123. UNREFERENCED_PARAMETER(Handle);
  6124. #if DELAY_INITIALIZATION
  6125. EnsureInitialized();
  6126. #endif
  6127. if ( 0 != Level )
  6128. {
  6129. Status = STATUS_INVALID_LEVEL;
  6130. }
  6131. else if (( NULL == KeyName ) || ( NULL == LocalServiceInfo ))
  6132. {
  6133. Status = STATUS_INVALID_PARAMETER;
  6134. }
  6135. else
  6136. {
  6137. LONG lError;
  6138. HKEY hKeyLicenseInfo;
  6139. HKEY hKeyService;
  6140. lError = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_KEY_LICENSE, 0, KEY_WRITE, &hKeyLicenseInfo );
  6141. if ( ERROR_SUCCESS == lError )
  6142. {
  6143. lError = RegOpenKeyEx( hKeyLicenseInfo, KeyName, 0, KEY_WRITE, &hKeyService );
  6144. if ( ERROR_SUCCESS == lError )
  6145. {
  6146. // set Mode
  6147. lError = RegSetValueEx( hKeyService, REG_VALUE_MODE, 0, REG_DWORD, (LPBYTE) &LocalServiceInfo->LocalServiceInfo0.Mode, sizeof( LocalServiceInfo->LocalServiceInfo0.Mode ) );
  6148. if ( ERROR_SUCCESS == lError )
  6149. {
  6150. // set FlipAllow
  6151. lError = RegSetValueEx( hKeyService, REG_VALUE_FLIP, 0, REG_DWORD, (LPBYTE) &LocalServiceInfo->LocalServiceInfo0.FlipAllow, sizeof( LocalServiceInfo->LocalServiceInfo0.FlipAllow ) );
  6152. if ( ERROR_SUCCESS == lError )
  6153. {
  6154. // set ConcurrentLimit
  6155. lError = RegSetValueEx( hKeyService, REG_VALUE_LIMIT, 0, REG_DWORD, (LPBYTE) &LocalServiceInfo->LocalServiceInfo0.ConcurrentLimit, sizeof( LocalServiceInfo->LocalServiceInfo0.ConcurrentLimit ) );
  6156. }
  6157. }
  6158. RegCloseKey( hKeyService );
  6159. }
  6160. RegCloseKey( hKeyLicenseInfo );
  6161. }
  6162. switch ( lError )
  6163. {
  6164. case ERROR_SUCCESS:
  6165. Status = STATUS_SUCCESS;
  6166. break;
  6167. case ERROR_FILE_NOT_FOUND:
  6168. case ERROR_PATH_NOT_FOUND:
  6169. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  6170. break;
  6171. default:
  6172. Status = STATUS_UNSUCCESSFUL;
  6173. break;
  6174. }
  6175. if ( STATUS_SUCCESS == Status )
  6176. {
  6177. LocalServiceListUpdate();
  6178. LocalServerServiceListUpdate();
  6179. ServiceListResynch();
  6180. }
  6181. }
  6182. if (NULL != LocalServiceInfo)
  6183. {
  6184. // note, some internal pointers are defined as dont_free, we should free them here
  6185. if (NULL != LocalServiceInfo->LocalServiceInfo0.KeyName)
  6186. {
  6187. MIDL_user_free(LocalServiceInfo->LocalServiceInfo0.KeyName);
  6188. }
  6189. if (NULL != LocalServiceInfo->LocalServiceInfo0.DisplayName)
  6190. {
  6191. MIDL_user_free(LocalServiceInfo->LocalServiceInfo0.DisplayName);
  6192. }
  6193. if (NULL != LocalServiceInfo->LocalServiceInfo0.FamilyDisplayName)
  6194. {
  6195. MIDL_user_free(LocalServiceInfo->LocalServiceInfo0.FamilyDisplayName);
  6196. }
  6197. }
  6198. return Status;
  6199. }
  6200. NTSTATUS
  6201. LlsrLocalServiceInfoSetA(
  6202. LLS_HANDLE Handle,
  6203. LPSTR KeyName,
  6204. DWORD Level,
  6205. PLLS_LOCAL_SERVICE_INFOA LocalServiceInfo )
  6206. {
  6207. #if DBG
  6208. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  6209. dprintf(TEXT("LLS TRACE: LlsLocalServiceInfoSetA\n"));
  6210. #endif
  6211. UNREFERENCED_PARAMETER(Handle);
  6212. UNREFERENCED_PARAMETER(KeyName);
  6213. UNREFERENCED_PARAMETER(Level);
  6214. UNREFERENCED_PARAMETER(LocalServiceInfo);
  6215. return STATUS_NOT_SUPPORTED;
  6216. }
  6217. NTSTATUS
  6218. LlsrLocalServiceInfoGetW(
  6219. LLS_HANDLE Handle,
  6220. LPWSTR KeyName,
  6221. DWORD Level,
  6222. PLLS_LOCAL_SERVICE_INFOW * pLocalServiceInfo )
  6223. {
  6224. NTSTATUS Status;
  6225. #if DBG
  6226. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  6227. dprintf(TEXT("LLS TRACE: LlsrLocalServiceInfoGetW\n"));
  6228. #endif
  6229. UNREFERENCED_PARAMETER(Handle);
  6230. #if DELAY_INITIALIZATION
  6231. EnsureInitialized();
  6232. #endif
  6233. RtlAcquireResourceShared(&LocalServiceListLock, TRUE);
  6234. if (NULL == pLocalServiceInfo)
  6235. {
  6236. return STATUS_INVALID_PARAMETER;
  6237. }
  6238. *pLocalServiceInfo = NULL;
  6239. if ( 0 != Level )
  6240. {
  6241. Status = STATUS_INVALID_LEVEL;
  6242. }
  6243. else if ( NULL == KeyName )
  6244. {
  6245. Status = STATUS_INVALID_PARAMETER;
  6246. }
  6247. else
  6248. {
  6249. PLOCAL_SERVICE_RECORD pRecord;
  6250. pRecord = LocalServiceListFind( KeyName );
  6251. if ( NULL == pRecord )
  6252. {
  6253. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  6254. }
  6255. else
  6256. {
  6257. *pLocalServiceInfo = MIDL_user_allocate( sizeof( **pLocalServiceInfo ) );
  6258. if ( NULL == *pLocalServiceInfo )
  6259. {
  6260. Status = STATUS_NO_MEMORY;
  6261. }
  6262. else
  6263. {
  6264. (*pLocalServiceInfo)->LocalServiceInfo0.KeyName = pRecord->Name;
  6265. (*pLocalServiceInfo)->LocalServiceInfo0.DisplayName = pRecord->DisplayName;
  6266. (*pLocalServiceInfo)->LocalServiceInfo0.FamilyDisplayName = pRecord->FamilyDisplayName;
  6267. (*pLocalServiceInfo)->LocalServiceInfo0.Mode = pRecord->Mode;
  6268. (*pLocalServiceInfo)->LocalServiceInfo0.FlipAllow = pRecord->FlipAllow;
  6269. (*pLocalServiceInfo)->LocalServiceInfo0.ConcurrentLimit = pRecord->ConcurrentLimit;
  6270. (*pLocalServiceInfo)->LocalServiceInfo0.HighMark = pRecord->HighMark;
  6271. Status = STATUS_SUCCESS;
  6272. }
  6273. }
  6274. }
  6275. return Status;
  6276. }
  6277. void LlsrLocalServiceInfoGetW_notify_flag(
  6278. boolean fNotify
  6279. )
  6280. {
  6281. if (fNotify)
  6282. {
  6283. RtlReleaseResource(&LocalServiceListLock);
  6284. }
  6285. }
  6286. NTSTATUS
  6287. LlsrLocalServiceInfoGetA(
  6288. LLS_HANDLE Handle,
  6289. LPSTR KeyName,
  6290. DWORD Level,
  6291. PLLS_LOCAL_SERVICE_INFOA * pLocalServiceInfo )
  6292. {
  6293. #if DBG
  6294. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_RPC))
  6295. dprintf(TEXT("LLS TRACE: LlsLocalServiceInfoGetA\n"));
  6296. #endif
  6297. UNREFERENCED_PARAMETER(Handle);
  6298. UNREFERENCED_PARAMETER(KeyName);
  6299. UNREFERENCED_PARAMETER(Level);
  6300. if (NULL == pLocalServiceInfo)
  6301. {
  6302. return STATUS_INVALID_PARAMETER;
  6303. }
  6304. *pLocalServiceInfo = NULL;
  6305. return STATUS_NOT_SUPPORTED;
  6306. }