Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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