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.

4482 lines
110 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. pack.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 new fields to purchase record to support secure certificates.
  11. o Unified per server purchase model with per seat purchase model for
  12. secure certificates; per server model still done in the traditional
  13. manner for non-secure certificates (for backwards compatibility).
  14. o Removed assertion on LicenseAdd() failure. LicenseAdd() may
  15. legitimately fail under certain circumstances.
  16. o Fixed bug wherein a memory allocation failure in the LLS routines
  17. would result in a corrupt data file (which would AV the server when
  18. it was thereafter read). (Bug #14072.)
  19. o Added SaveAll() function analogous to LoadAll().
  20. o Added support for extended user data packing/unpacking. This was
  21. done to save the SUITE_USE flag across restarts of the service.
  22. o Removed user table parameters from unpack routines that didn't use
  23. them.
  24. o Fixed ServerServiceListUnpack() to subtract out old values only when
  25. they were previously added to the MasterServiceTable. This fixes
  26. problems with the MaxSessionCount and HighMark tallies getting skewed.
  27. --*/
  28. #include <stdlib.h>
  29. #include <nt.h>
  30. #include <ntrtl.h>
  31. #include <nturtl.h>
  32. #include <windows.h>
  33. #include <tstr.h>
  34. #include <dsgetdc.h>
  35. #include "llsapi.h"
  36. #include "debug.h"
  37. #include "llsutil.h"
  38. #include "llssrv.h"
  39. #include "mapping.h"
  40. #include "msvctbl.h"
  41. #include "svctbl.h"
  42. #include "perseat.h"
  43. #include "purchase.h"
  44. #include "server.h"
  45. #include "service.h"
  46. #include "llsrpc_s.h"
  47. #include "lsapi_s.h"
  48. #include "llsdbg_s.h"
  49. #include "repl.h"
  50. #include "pack.h"
  51. #include "llsevent.h"
  52. #include "certdb.h"
  53. #include "llsrtl.h"
  54. int __cdecl MServiceRecordCompare(const void *arg1, const void *arg2);
  55. BOOL ValidateDN(LPTSTR pszDN);
  56. static HANDLE PurchaseFile = NULL;
  57. /////////////////////////////////////////////////////////////////////////
  58. // License List
  59. //
  60. /////////////////////////////////////////////////////////////////////////
  61. VOID
  62. LicenseListUnpackOld (
  63. ULONG LicenseServiceTableSize,
  64. PPACK_LICENSE_SERVICE_RECORD LicenseServices,
  65. ULONG LicenseTableSize,
  66. PPACK_LICENSE_PURCHASE_RECORD_0 Licenses
  67. )
  68. /*++
  69. Routine Description:
  70. Arguments:
  71. Return Value:
  72. --*/
  73. {
  74. NTSTATUS Status = STATUS_SUCCESS;
  75. ULONG i;
  76. PPACK_LICENSE_PURCHASE_RECORD_0 pLicense;
  77. #if DBG
  78. if (TraceFlags & TRACE_FUNCTION_TRACE)
  79. dprintf(TEXT("LicenseListUnpackOld: Service[%lu] License[%lu]\n"), LicenseServiceTableSize, LicenseTableSize);
  80. #endif
  81. //
  82. // Walk services table, adding any new services to our local table.
  83. // Fix up the index pointers to match our local services.
  84. //
  85. RtlAcquireResourceExclusive(&LicenseListLock, TRUE);
  86. for (i = 0; i < LicenseTableSize; i++) {
  87. pLicense = &Licenses[i];
  88. if (pLicense->Service < LicenseServiceTableSize)
  89. Status = LicenseAdd(LicenseServices[pLicense->Service].ServiceName, TEXT("Microsoft"), pLicense->NumberLicenses, 0, pLicense->Admin, pLicense->Comment, pLicense->Date, LLS_LICENSE_MODE_ALLOW_PER_SEAT, 0, TEXT("None"), 0, NULL );
  90. else {
  91. ASSERT(FALSE);
  92. }
  93. if (Status != STATUS_SUCCESS) {
  94. #ifdef DBG
  95. dprintf(TEXT("LicenseAdd failed: 0x%lX\n"), Status);
  96. #endif
  97. // ASSERT(FALSE);
  98. }
  99. }
  100. RtlReleaseResource(&LicenseListLock);
  101. } // LicenseListUnpackOld
  102. /////////////////////////////////////////////////////////////////////////
  103. VOID
  104. LicenseListStringsUnpackOld (
  105. ULONG LicenseServiceTableSize,
  106. PPACK_LICENSE_SERVICE_RECORD LicenseServices,
  107. ULONG LicenseServiceStringSize,
  108. LPTSTR LicenseServiceStrings,
  109. ULONG LicenseTableSize,
  110. PPACK_LICENSE_PURCHASE_RECORD_0 Licenses,
  111. ULONG LicenseStringSize,
  112. LPTSTR LicenseStrings
  113. )
  114. /*++
  115. Routine Description:
  116. Arguments:
  117. Return Value:
  118. --*/
  119. {
  120. ULONG i;
  121. PPACK_LICENSE_SERVICE_RECORD pSvc;
  122. PPACK_LICENSE_PURCHASE_RECORD_0 pLicense;
  123. TCHAR *pStr;
  124. #if DBG
  125. if (TraceFlags & TRACE_FUNCTION_TRACE)
  126. dprintf(TEXT("LicenseListStringsUnpack\n"));
  127. #endif
  128. //
  129. // First do license service strings
  130. //
  131. pStr = LicenseServiceStrings;
  132. for (i = 0; i < LicenseServiceTableSize; i++) {
  133. pSvc = &LicenseServices[i];
  134. pSvc->ServiceName = pStr;
  135. //
  136. // Move to end of current string
  137. //
  138. while (*pStr != TEXT('\0'))
  139. pStr++;
  140. // now go past ending NULL
  141. pStr++;
  142. }
  143. //
  144. // Now do license purchase strings
  145. //
  146. pStr = LicenseStrings;
  147. for (i = 0; i < LicenseTableSize; i++) {
  148. pLicense = &Licenses[i];
  149. pLicense->Admin = pStr;
  150. //
  151. // Move to end of current string
  152. //
  153. while (*pStr != TEXT('\0'))
  154. pStr++;
  155. // now go past ending NULL
  156. pStr++;
  157. pLicense->Comment = pStr;
  158. //
  159. // Move to end of current string
  160. //
  161. while (*pStr != TEXT('\0'))
  162. pStr++;
  163. // now go past ending NULL
  164. pStr++;
  165. }
  166. } // LicenseListStringsUnpackOld
  167. /////////////////////////////////////////////////////////////////////////
  168. VOID
  169. LicenseListLoadOld()
  170. /*++
  171. Routine Description:
  172. Arguments:
  173. None.
  174. Return Value:
  175. None.
  176. --*/
  177. {
  178. BOOL ret;
  179. DWORD Version, DataSize;
  180. NTSTATUS Status = STATUS_SUCCESS;
  181. HANDLE hFile = NULL;
  182. ULONG LicenseServiceTableSize;
  183. PPACK_LICENSE_SERVICE_RECORD LicenseServices = NULL;
  184. ULONG LicenseServiceStringSize;
  185. LPTSTR LicenseServiceStrings = NULL;
  186. ULONG LicenseTableSize;
  187. PPACK_LICENSE_PURCHASE_RECORD_0 Licenses = NULL;
  188. ULONG LicenseStringSize;
  189. LPTSTR LicenseStrings = NULL;
  190. LICENSE_FILE_HEADER_0 FileHeader;
  191. DWORD BytesRead;
  192. #if DBG
  193. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_DATABASE))
  194. dprintf(TEXT("LLS TRACE: LicenseListLoad\n"));
  195. #endif
  196. //
  197. // Check if we already have file open
  198. //
  199. if (PurchaseFile != NULL) {
  200. CloseHandle(PurchaseFile);
  201. PurchaseFile = NULL;
  202. }
  203. //
  204. // If nothing to load then get-out
  205. //
  206. if (!FileExists(LicenseFileName))
  207. goto LicenseListLoadExit;
  208. //
  209. // Check the init header
  210. //
  211. Version = DataSize = 0;
  212. PurchaseFile = LlsFileCheck(LicenseFileName, &Version, &DataSize );
  213. if (PurchaseFile == NULL) {
  214. Status = GetLastError();
  215. goto LicenseListLoadExit;
  216. }
  217. if ((Version != LICENSE_FILE_VERSION_0) || (DataSize != sizeof(LICENSE_FILE_HEADER_0))) {
  218. Status = STATUS_FILE_INVALID;
  219. goto LicenseListLoadExit;
  220. }
  221. //
  222. // The init header checks out, so load the license header and data blocks
  223. //
  224. hFile = PurchaseFile;
  225. ret = ReadFile(hFile, &FileHeader, sizeof(LICENSE_FILE_HEADER_0), &BytesRead, NULL);
  226. LicenseServiceTableSize = 0;
  227. LicenseServiceStringSize = 0;
  228. LicenseTableSize = 0;
  229. LicenseStringSize = 0;
  230. if (ret) {
  231. //
  232. // Run through and allocate space to read data blocks into
  233. //
  234. if (FileHeader.LicenseServiceTableSize != 0) {
  235. LicenseServiceTableSize = FileHeader.LicenseServiceTableSize / sizeof(PACK_LICENSE_SERVICE_RECORD);
  236. LicenseServices = MIDL_user_allocate(FileHeader.LicenseServiceTableSize);
  237. if ( LicenseServices == NULL ) {
  238. Status = STATUS_NO_MEMORY;
  239. goto LicenseListLoadExit;
  240. }
  241. }
  242. if (FileHeader.LicenseServiceStringSize != 0) {
  243. LicenseServiceStringSize = FileHeader.LicenseServiceStringSize / sizeof(TCHAR);
  244. LicenseServiceStrings = MIDL_user_allocate(FileHeader.LicenseServiceStringSize);
  245. if ( LicenseServiceStrings == NULL ) {
  246. Status = STATUS_NO_MEMORY;
  247. goto LicenseListLoadExit;
  248. }
  249. }
  250. if (FileHeader.LicenseTableSize != 0) {
  251. LicenseTableSize = FileHeader.LicenseTableSize / sizeof(PACK_LICENSE_PURCHASE_RECORD);
  252. Licenses = MIDL_user_allocate(FileHeader.LicenseTableSize);
  253. if ( Licenses == NULL ) {
  254. Status = STATUS_NO_MEMORY;
  255. goto LicenseListLoadExit;
  256. }
  257. }
  258. if (FileHeader.LicenseStringSize != 0) {
  259. LicenseStringSize = FileHeader.LicenseStringSize / sizeof(TCHAR);
  260. LicenseStrings = MIDL_user_allocate(FileHeader.LicenseStringSize);
  261. if ( LicenseStrings == NULL ) {
  262. Status = STATUS_NO_MEMORY;
  263. goto LicenseListLoadExit;
  264. }
  265. }
  266. }
  267. if (ret && (FileHeader.LicenseServiceTableSize != 0) )
  268. ret = ReadFile(hFile, LicenseServices, FileHeader.LicenseServiceTableSize, &BytesRead, NULL);
  269. if (ret && (FileHeader.LicenseServiceStringSize != 0) )
  270. ret = ReadFile(hFile, LicenseServiceStrings, FileHeader.LicenseServiceStringSize, &BytesRead, NULL);
  271. if (ret && (FileHeader.LicenseTableSize != 0) )
  272. ret = ReadFile(hFile, Licenses, FileHeader.LicenseTableSize, &BytesRead, NULL);
  273. if (ret && (FileHeader.LicenseStringSize != 0) )
  274. ret = ReadFile(hFile, LicenseStrings, FileHeader.LicenseStringSize, &BytesRead, NULL);
  275. if (!ret) {
  276. Status = GetLastError();
  277. goto LicenseListLoadExit;
  278. }
  279. //
  280. // Decrypt the data
  281. //
  282. Status = DeBlock(LicenseServices, FileHeader.LicenseServiceTableSize);
  283. if (Status == STATUS_SUCCESS)
  284. Status = DeBlock(LicenseServiceStrings, FileHeader.LicenseServiceStringSize);
  285. if (Status == STATUS_SUCCESS)
  286. Status = DeBlock(Licenses, FileHeader.LicenseTableSize);
  287. if (Status == STATUS_SUCCESS)
  288. Status = DeBlock(LicenseStrings, FileHeader.LicenseStringSize);
  289. if (Status != STATUS_SUCCESS)
  290. goto LicenseListLoadExit;
  291. //
  292. // Unpack the string data
  293. //
  294. LicenseListStringsUnpackOld( LicenseServiceTableSize, LicenseServices,
  295. LicenseServiceStringSize, LicenseServiceStrings,
  296. LicenseTableSize, Licenses,
  297. LicenseStringSize, LicenseStrings );
  298. //
  299. // Unpack the license data
  300. //
  301. LicenseListUnpackOld( LicenseServiceTableSize, LicenseServices, LicenseTableSize, Licenses );
  302. LicenseListLoadExit:
  303. // Note: Don't close the License Purchase File (keep it locked).
  304. //
  305. // Run through our tables and clean them up
  306. //
  307. if (LicenseServices != NULL)
  308. MIDL_user_free(LicenseServices);
  309. if (LicenseServiceStrings != NULL)
  310. MIDL_user_free(LicenseServiceStrings);
  311. if (Licenses != NULL)
  312. MIDL_user_free(Licenses);
  313. if (LicenseStrings != NULL)
  314. MIDL_user_free(LicenseStrings);
  315. //
  316. // If there was an error log it.
  317. //
  318. if (Status != STATUS_SUCCESS)
  319. LogEvent(LLS_EVENT_LOAD_LICENSE, 0, NULL, Status);
  320. } // LicenseListLoadOld
  321. /////////////////////////////////////////////////////////////////////////
  322. NTSTATUS
  323. LicenseListPack (
  324. ULONG *pLicenseServiceTableSize,
  325. PPACK_LICENSE_SERVICE_RECORD *pLicenseServices,
  326. ULONG *pLicenseTableSize,
  327. PPACK_LICENSE_PURCHASE_RECORD *pLicenses,
  328. ULONG *pPerServerLicenseServiceTableSize,
  329. PPACK_LICENSE_SERVICE_RECORD *pPerServerLicenseServices
  330. )
  331. /*++
  332. Routine Description:
  333. Arguments:
  334. Return Value:
  335. --*/
  336. {
  337. NTSTATUS Status = STATUS_SUCCESS;
  338. PPACK_LICENSE_SERVICE_RECORD LicenseServices = NULL;
  339. PPACK_LICENSE_PURCHASE_RECORD Licenses = NULL;
  340. ULONG i;
  341. ULONG TotalRecords = 0;
  342. PLICENSE_SERVICE_RECORD pLicenseService;
  343. PLICENSE_PURCHASE_RECORD pLicense;
  344. PPACK_LICENSE_SERVICE_RECORD PerServerLicenseServices = NULL;
  345. PLICENSE_SERVICE_RECORD pPerServerLicenseService;
  346. #if DBG
  347. if (TraceFlags & TRACE_FUNCTION_TRACE)
  348. dprintf(TEXT("LLS TRACE: LicenseListPack\n"));
  349. #endif
  350. ASSERT(pLicenseServices != NULL);
  351. ASSERT(pLicenseServiceTableSize != NULL);
  352. *pLicenseServices = NULL;
  353. *pLicenseServiceTableSize = 0;
  354. ASSERT(pLicenses != NULL);
  355. ASSERT(pLicenseTableSize != NULL);
  356. *pLicenses = NULL;
  357. *pLicenseTableSize = 0;
  358. ASSERT(pPerServerLicenseServices != NULL);
  359. ASSERT(pPerServerLicenseServiceTableSize != NULL);
  360. *pPerServerLicenseServices = NULL;
  361. *pPerServerLicenseServiceTableSize = 0;
  362. //////////////////////////////////////////////////////////////////
  363. //
  364. // Do License Service Table First
  365. //
  366. TotalRecords = LicenseServiceListSize;
  367. //
  368. // Make sure there is anything to replicate
  369. //
  370. if (TotalRecords > 0) {
  371. //
  372. // Create our buffer to hold all of the garbage
  373. //
  374. LicenseServices = MIDL_user_allocate(TotalRecords * sizeof(PACK_LICENSE_SERVICE_RECORD));
  375. if (LicenseServices == NULL) {
  376. ASSERT(FALSE);
  377. return STATUS_NO_MEMORY;
  378. }
  379. //
  380. // Fill in the buffer - walk the License Services tree
  381. //
  382. for (i = 0; i < LicenseServiceListSize; i++) {
  383. pLicenseService = LicenseServiceList[i];
  384. //
  385. // Make index match table in it's current state
  386. //
  387. pLicenseService->Index = i;
  388. LicenseServices[i].ServiceName = pLicenseService->ServiceName;
  389. LicenseServices[i].NumberLicenses = pLicenseService->NumberLicenses;
  390. }
  391. }
  392. *pLicenseServices = LicenseServices;
  393. *pLicenseServiceTableSize = TotalRecords;
  394. //////////////////////////////////////////////////////////////////
  395. //
  396. // Now Do Per Server License Service Table
  397. //
  398. TotalRecords = PerServerLicenseServiceListSize;
  399. //
  400. // Make sure there is anything to replicate
  401. //
  402. if (TotalRecords > 0)
  403. {
  404. //
  405. // Create our buffer to hold all of the garbage
  406. //
  407. PerServerLicenseServices = MIDL_user_allocate(TotalRecords * sizeof(PACK_LICENSE_SERVICE_RECORD));
  408. if (PerServerLicenseServices == NULL)
  409. {
  410. ASSERT(FALSE);
  411. //
  412. // Clean up already alloc'd information
  413. //
  414. if (LicenseServices != NULL)
  415. MIDL_user_free(LicenseServices);
  416. *pLicenseServices = NULL;
  417. *pLicenseServiceTableSize = 0;
  418. return STATUS_NO_MEMORY;
  419. }
  420. //
  421. // Fill in the buffer - walk the Per Server License Services tree
  422. //
  423. for (i = 0; i < PerServerLicenseServiceListSize; i++)
  424. {
  425. pPerServerLicenseService = PerServerLicenseServiceList[i];
  426. //
  427. // Make index match table in it's current state
  428. //
  429. pPerServerLicenseService->Index = i;
  430. PerServerLicenseServices[i].ServiceName = pPerServerLicenseService->ServiceName;
  431. PerServerLicenseServices[i].NumberLicenses = pPerServerLicenseService->NumberLicenses;
  432. }
  433. }
  434. *pPerServerLicenseServices = PerServerLicenseServices;
  435. *pPerServerLicenseServiceTableSize = TotalRecords;
  436. //////////////////////////////////////////////////////////////////
  437. //
  438. // Now Do License Purchase Records
  439. //
  440. TotalRecords = PurchaseListSize;
  441. //
  442. // Make sure there is anything to replicate
  443. //
  444. if (TotalRecords > 0) {
  445. //
  446. // Create our buffer to hold all of the garbage
  447. //
  448. Licenses = MIDL_user_allocate(TotalRecords * sizeof(PACK_LICENSE_PURCHASE_RECORD));
  449. if (Licenses == NULL) {
  450. ASSERT(FALSE);
  451. //
  452. // Clean up already alloc'd information
  453. //
  454. if (LicenseServices != NULL)
  455. MIDL_user_free(LicenseServices);
  456. if (PerServerLicenseServices != NULL)
  457. MIDL_user_free(PerServerLicenseServices);
  458. *pLicenseServices = NULL;
  459. *pLicenseServiceTableSize = 0;
  460. *pPerServerLicenseServices = NULL;
  461. *pPerServerLicenseServiceTableSize = 0;
  462. return STATUS_NO_MEMORY;
  463. }
  464. //
  465. // Fill in the buffer - walk the License Purchase tree
  466. //
  467. for (i = 0; i < PurchaseListSize; i++) {
  468. pLicense = &PurchaseList[i];
  469. //
  470. // License Service table index is fixed-up to what we need
  471. //
  472. Licenses[i].Service = ( pLicense->AllowedModes & 1 ) ? pLicense->Service->Index
  473. : 0xFFFFFFFF;
  474. Licenses[i].NumberLicenses = pLicense->NumberLicenses;
  475. Licenses[i].Date = pLicense->Date;
  476. Licenses[i].Admin = pLicense->Admin;
  477. Licenses[i].Comment = pLicense->Comment;
  478. Licenses[i].PerServerService = ( pLicense->AllowedModes & 2 ) ? pLicense->PerServerService->Index
  479. : 0xFFFFFFFF;
  480. Licenses[i].AllowedModes = pLicense->AllowedModes;
  481. Licenses[i].CertificateID = pLicense->CertificateID;
  482. Licenses[i].Source = pLicense->Source;
  483. Licenses[i].ExpirationDate = pLicense->ExpirationDate;
  484. Licenses[i].MaxQuantity = pLicense->MaxQuantity;
  485. Licenses[i].Vendor = pLicense->Vendor;
  486. memcpy( Licenses[i].Secrets, pLicense->Secrets, LLS_NUM_SECRETS * sizeof( *pLicense->Secrets ) );
  487. }
  488. }
  489. *pLicenses = Licenses;
  490. *pLicenseTableSize = TotalRecords;
  491. return Status;
  492. } // LicenseListPack
  493. /////////////////////////////////////////////////////////////////////////
  494. VOID
  495. LicenseListUnpack (
  496. ULONG LicenseServiceTableSize,
  497. PPACK_LICENSE_SERVICE_RECORD LicenseServices,
  498. ULONG LicenseTableSize,
  499. PPACK_LICENSE_PURCHASE_RECORD Licenses,
  500. ULONG PerServerLicenseServiceTableSize,
  501. PPACK_LICENSE_SERVICE_RECORD PerServerLicenseServices
  502. )
  503. /*++
  504. Routine Description:
  505. Arguments:
  506. Return Value:
  507. --*/
  508. {
  509. NTSTATUS Status = STATUS_SUCCESS;
  510. ULONG i;
  511. PPACK_LICENSE_PURCHASE_RECORD pLicense;
  512. LPTSTR ServiceName;
  513. #if DBG
  514. if (TraceFlags & TRACE_FUNCTION_TRACE)
  515. dprintf(TEXT("LicenseListUnpack: Service[%lu] PerServerService[%lu] License[%lu]\n"), LicenseServiceTableSize, PerServerLicenseServiceTableSize, LicenseTableSize);
  516. #endif
  517. //
  518. // Walk services table, adding any new services to our local table.
  519. // Fix up the index pointers to match our local services.
  520. //
  521. RtlAcquireResourceExclusive(&LicenseListLock, TRUE);
  522. for (i = 0; i < LicenseTableSize; i++)
  523. {
  524. pLicense = &Licenses[i];
  525. ServiceName = NULL;
  526. if ( pLicense->AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SERVER )
  527. {
  528. if ( pLicense->PerServerService < PerServerLicenseServiceTableSize )
  529. {
  530. ServiceName = PerServerLicenseServices[ pLicense->PerServerService ].ServiceName;
  531. }
  532. else
  533. {
  534. ASSERT( FALSE );
  535. }
  536. }
  537. if ( ( NULL == ServiceName ) && ( pLicense->AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SEAT ) )
  538. {
  539. if ( pLicense->Service < LicenseServiceTableSize )
  540. {
  541. ServiceName = LicenseServices[ pLicense->Service ].ServiceName;
  542. }
  543. else
  544. {
  545. ASSERT( FALSE );
  546. }
  547. }
  548. if ( NULL == ServiceName )
  549. {
  550. ASSERT( FALSE );
  551. }
  552. else
  553. {
  554. Status = LicenseAdd( ServiceName, pLicense->Vendor, pLicense->NumberLicenses, pLicense->MaxQuantity, pLicense->Admin, pLicense->Comment, pLicense->Date, pLicense->AllowedModes, pLicense->CertificateID, pLicense->Source, pLicense->ExpirationDate, pLicense->Secrets );
  555. if (Status != STATUS_SUCCESS)
  556. {
  557. #ifdef DBG
  558. dprintf(TEXT("LicenseAdd failed: 0x%lX\n"), Status);
  559. #endif
  560. // ASSERT(FALSE);
  561. }
  562. }
  563. if (i % 100 == 0) ReportStatusToSCMgr( SERVICE_START_PENDING, NO_ERROR, NSERVICEWAITHINT);
  564. }
  565. RtlReleaseResource(&LicenseListLock);
  566. } // LicenseListUnpack
  567. /////////////////////////////////////////////////////////////////////////
  568. NTSTATUS
  569. LicenseListStringsPack (
  570. ULONG LicenseServiceTableSize,
  571. PPACK_LICENSE_SERVICE_RECORD LicenseServices,
  572. ULONG *pLicenseServiceStringSize,
  573. LPTSTR *pLicenseServiceStrings,
  574. ULONG LicenseTableSize,
  575. PPACK_LICENSE_PURCHASE_RECORD Licenses,
  576. ULONG *pLicenseStringSize,
  577. LPTSTR *pLicenseStrings,
  578. ULONG PerServerLicenseServiceTableSize,
  579. PPACK_LICENSE_SERVICE_RECORD PerServerLicenseServices,
  580. ULONG *pPerServerLicenseServiceStringSize,
  581. LPTSTR *pPerServerLicenseServiceStrings
  582. )
  583. /*++
  584. Routine Description:
  585. Arguments:
  586. Return Value:
  587. --*/
  588. {
  589. NTSTATUS Status = STATUS_SUCCESS;
  590. ULONG i;
  591. ULONG StringSize;
  592. PPACK_LICENSE_SERVICE_RECORD pSvc;
  593. PPACK_LICENSE_PURCHASE_RECORD pLicense;
  594. LPTSTR LicenseServiceStrings = NULL;
  595. LPTSTR LicenseStrings = NULL;
  596. TCHAR *pStr;
  597. LPTSTR PerServerLicenseServiceStrings = NULL;
  598. #if DBG
  599. if (TraceFlags & TRACE_FUNCTION_TRACE)
  600. dprintf(TEXT("LicenseListStringsPack\n"));
  601. #endif
  602. ASSERT(pLicenseServiceStrings != NULL);
  603. ASSERT(pLicenseServiceStringSize != NULL);
  604. *pLicenseServiceStrings = NULL;
  605. *pLicenseServiceStringSize = 0;
  606. ASSERT(pLicenseStrings != NULL);
  607. ASSERT(pLicenseStringSize != NULL);
  608. *pLicenseStrings = NULL;
  609. *pLicenseStringSize = 0;
  610. ASSERT(pPerServerLicenseServiceStrings != NULL);
  611. ASSERT(pPerServerLicenseServiceStringSize != NULL);
  612. *pPerServerLicenseServiceStrings = NULL;
  613. *pPerServerLicenseServiceStringSize = 0;
  614. //////////////////////////////////////////////////////////////////
  615. //
  616. // Do License Service Strings
  617. //
  618. //
  619. // First walk the list adding up string sizes - to calculate our buff size
  620. //
  621. StringSize = 0;
  622. for (i = 0; i < LicenseServiceTableSize; i++) {
  623. pSvc = &LicenseServices[i];
  624. StringSize = StringSize + lstrlen(pSvc->ServiceName) + 1;
  625. }
  626. //
  627. // Make sure there is anything to replicate
  628. //
  629. if (StringSize > 0) {
  630. //
  631. // Create our buffer to hold all of the garbage
  632. //
  633. LicenseServiceStrings = MIDL_user_allocate(StringSize * sizeof(TCHAR));
  634. if (LicenseServiceStrings == NULL) {
  635. ASSERT(FALSE);
  636. return STATUS_NO_MEMORY;
  637. }
  638. //
  639. // Fill in the buffer
  640. //
  641. pStr = LicenseServiceStrings;
  642. for (i = 0; i < LicenseServiceTableSize; i++) {
  643. pSvc = &LicenseServices[i];
  644. lstrcpy(pStr, pSvc->ServiceName);
  645. pStr = &pStr[lstrlen(pSvc->ServiceName) + 1];
  646. }
  647. }
  648. *pLicenseServiceStrings = LicenseServiceStrings;
  649. *pLicenseServiceStringSize = StringSize;
  650. //////////////////////////////////////////////////////////////////
  651. //
  652. // Do Per Server License Service Strings
  653. //
  654. //
  655. // First walk the list adding up string sizes - to calculate our buff size
  656. //
  657. StringSize = 0;
  658. for (i = 0; i < PerServerLicenseServiceTableSize; i++) {
  659. pSvc = &PerServerLicenseServices[i];
  660. StringSize = StringSize + lstrlen(pSvc->ServiceName) + 1;
  661. }
  662. //
  663. // Make sure there is anything to replicate
  664. //
  665. if (StringSize > 0) {
  666. //
  667. // Create our buffer to hold all of the garbage
  668. //
  669. PerServerLicenseServiceStrings = MIDL_user_allocate(StringSize * sizeof(TCHAR));
  670. if (PerServerLicenseServiceStrings == NULL)
  671. {
  672. ASSERT(FALSE);
  673. //
  674. // Clean up already alloc'd information
  675. //
  676. if (LicenseServiceStrings != NULL)
  677. MIDL_user_free(LicenseServiceStrings);
  678. *pLicenseServiceStrings = NULL;
  679. *pLicenseServiceStringSize = 0;
  680. return STATUS_NO_MEMORY;
  681. }
  682. //
  683. // Fill in the buffer
  684. //
  685. pStr = PerServerLicenseServiceStrings;
  686. for (i = 0; i < PerServerLicenseServiceTableSize; i++)
  687. {
  688. pSvc = &PerServerLicenseServices[i];
  689. lstrcpy(pStr, pSvc->ServiceName);
  690. pStr = &pStr[lstrlen(pSvc->ServiceName) + 1];
  691. }
  692. }
  693. *pPerServerLicenseServiceStrings = PerServerLicenseServiceStrings;
  694. *pPerServerLicenseServiceStringSize = StringSize;
  695. //////////////////////////////////////////////////////////////////
  696. //
  697. // Now Do License Purchase Strings
  698. //
  699. //
  700. // First walk the list adding up string sizes - to calculate our buff size
  701. //
  702. StringSize = 0;
  703. for (i = 0; i < LicenseTableSize; i++) {
  704. pLicense = &Licenses[i];
  705. StringSize = StringSize + lstrlen(pLicense->Vendor) + 1;
  706. StringSize = StringSize + lstrlen(pLicense->Admin) + 1;
  707. StringSize = StringSize + lstrlen(pLicense->Comment) + 1;
  708. StringSize = StringSize + lstrlen(pLicense->Source) + 1;
  709. }
  710. //
  711. // Make sure there is anything to replicate
  712. //
  713. if (StringSize > 0) {
  714. //
  715. // Create our buffer to hold all of the garbage
  716. //
  717. LicenseStrings = MIDL_user_allocate(StringSize * sizeof(TCHAR));
  718. if (LicenseStrings == NULL) {
  719. ASSERT(FALSE);
  720. //
  721. // Clean up already alloc'd information
  722. //
  723. if (LicenseServiceStrings != NULL)
  724. MIDL_user_free(LicenseServiceStrings);
  725. if (PerServerLicenseServiceStrings != NULL)
  726. MIDL_user_free(PerServerLicenseServiceStrings);
  727. *pLicenseServiceStrings = NULL;
  728. *pLicenseServiceStringSize = 0;
  729. *pPerServerLicenseServiceStrings = NULL;
  730. *pPerServerLicenseServiceStringSize = 0;
  731. return STATUS_NO_MEMORY;
  732. }
  733. //
  734. // Fill in the buffer
  735. //
  736. pStr = LicenseStrings;
  737. for (i = 0; i < LicenseTableSize; i++) {
  738. pLicense = &Licenses[i];
  739. lstrcpy(pStr, pLicense->Vendor);
  740. pStr = &pStr[lstrlen(pLicense->Vendor) + 1];
  741. lstrcpy(pStr, pLicense->Admin);
  742. pStr = &pStr[lstrlen(pLicense->Admin) + 1];
  743. lstrcpy(pStr, pLicense->Comment);
  744. pStr = &pStr[lstrlen(pLicense->Comment) + 1];
  745. lstrcpy(pStr, pLicense->Source);
  746. pStr = &pStr[lstrlen(pLicense->Source) + 1];
  747. }
  748. }
  749. *pLicenseStrings = LicenseStrings;
  750. *pLicenseStringSize = StringSize;
  751. return Status;
  752. } // LicenseListStringsPack
  753. /////////////////////////////////////////////////////////////////////////
  754. VOID
  755. LicenseListStringsUnpack (
  756. ULONG LicenseServiceTableSize,
  757. PPACK_LICENSE_SERVICE_RECORD LicenseServices,
  758. ULONG LicenseServiceStringSize,
  759. LPTSTR LicenseServiceStrings,
  760. ULONG LicenseTableSize,
  761. PPACK_LICENSE_PURCHASE_RECORD Licenses,
  762. ULONG LicenseStringSize,
  763. LPTSTR LicenseStrings,
  764. ULONG PerServerLicenseServiceTableSize,
  765. PPACK_LICENSE_SERVICE_RECORD PerServerLicenseServices,
  766. ULONG PerServerLicenseServiceStringSize,
  767. LPTSTR PerServerLicenseServiceStrings
  768. )
  769. /*++
  770. Routine Description:
  771. Arguments:
  772. Return Value:
  773. --*/
  774. {
  775. ULONG i;
  776. PPACK_LICENSE_SERVICE_RECORD pSvc;
  777. PPACK_LICENSE_PURCHASE_RECORD pLicense;
  778. TCHAR *pStr;
  779. #if DBG
  780. if (TraceFlags & TRACE_FUNCTION_TRACE)
  781. dprintf(TEXT("LicenseListStringsUnpack\n"));
  782. #endif
  783. //
  784. // First do per seat license service strings
  785. //
  786. pStr = LicenseServiceStrings;
  787. for (i = 0; i < LicenseServiceTableSize; i++) {
  788. pSvc = &LicenseServices[i];
  789. pSvc->ServiceName = pStr;
  790. //
  791. // Move to end of current string
  792. //
  793. while (*pStr != TEXT('\0'))
  794. pStr++;
  795. // now go past ending NULL
  796. pStr++;
  797. }
  798. //
  799. // Then do per server license service strings
  800. //
  801. pStr = PerServerLicenseServiceStrings;
  802. for (i = 0; i < PerServerLicenseServiceTableSize; i++) {
  803. pSvc = &PerServerLicenseServices[i];
  804. pSvc->ServiceName = pStr;
  805. //
  806. // Move to end of current string
  807. //
  808. while (*pStr != TEXT('\0'))
  809. pStr++;
  810. // now go past ending NULL
  811. pStr++;
  812. }
  813. //
  814. // Now do license purchase strings
  815. //
  816. pStr = LicenseStrings;
  817. for (i = 0; i < LicenseTableSize; i++) {
  818. pLicense = &Licenses[i];
  819. pLicense->Vendor = pStr;
  820. //
  821. // Move to end of current string
  822. //
  823. while (*pStr != TEXT('\0'))
  824. pStr++;
  825. // now go past ending NULL
  826. pStr++;
  827. pLicense->Admin = pStr;
  828. //
  829. // Move to end of current string
  830. //
  831. while (*pStr != TEXT('\0'))
  832. pStr++;
  833. // now go past ending NULL
  834. pStr++;
  835. pLicense->Comment = pStr;
  836. //
  837. // Move to end of current string
  838. //
  839. while (*pStr != TEXT('\0'))
  840. pStr++;
  841. // now go past ending NULL
  842. pStr++;
  843. pLicense->Source = pStr;
  844. //
  845. // Move to end of current string
  846. //
  847. while (*pStr != TEXT('\0'))
  848. pStr++;
  849. // now go past ending NULL
  850. pStr++;
  851. }
  852. } // LicenseListStringsUnpack
  853. /////////////////////////////////////////////////////////////////////////
  854. VOID
  855. LicenseListLoad()
  856. /*++
  857. Routine Description:
  858. Arguments:
  859. None.
  860. Return Value:
  861. None.
  862. --*/
  863. {
  864. BOOL ret;
  865. DWORD Version, DataSize;
  866. NTSTATUS Status = STATUS_SUCCESS;
  867. HANDLE hFile = NULL;
  868. ULONG LicenseServiceTableSize;
  869. PPACK_LICENSE_SERVICE_RECORD LicenseServices = NULL;
  870. ULONG LicenseServiceStringSize;
  871. LPTSTR LicenseServiceStrings = NULL;
  872. ULONG PerServerLicenseServiceTableSize;
  873. PPACK_LICENSE_SERVICE_RECORD PerServerLicenseServices = NULL;
  874. ULONG PerServerLicenseServiceStringSize;
  875. LPTSTR PerServerLicenseServiceStrings = NULL;
  876. ULONG LicenseTableSize;
  877. PPACK_LICENSE_PURCHASE_RECORD Licenses = NULL;
  878. ULONG LicenseStringSize;
  879. LPTSTR LicenseStrings = NULL;
  880. LICENSE_FILE_HEADER FileHeader;
  881. DWORD BytesRead;
  882. #if DBG
  883. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_DATABASE))
  884. dprintf(TEXT("LLS TRACE: LicenseListLoad\n"));
  885. #endif
  886. //
  887. // Check if we already have file open
  888. //
  889. if (PurchaseFile != NULL) {
  890. CloseHandle(PurchaseFile);
  891. PurchaseFile = NULL;
  892. }
  893. //
  894. // If nothing to load then get-out
  895. //
  896. if (!FileExists(LicenseFileName))
  897. goto LicenseListLoadExit;
  898. //
  899. // Check the init header
  900. //
  901. Version = DataSize = 0;
  902. PurchaseFile = LlsFileCheck(LicenseFileName, &Version, &DataSize );
  903. if (PurchaseFile == NULL) {
  904. Status = GetLastError();
  905. goto LicenseListLoadExit;
  906. }
  907. if ( ( Version == LICENSE_FILE_VERSION_0 ) && ( DataSize == sizeof(LICENSE_FILE_HEADER_0) ) ) {
  908. CloseHandle(PurchaseFile);
  909. PurchaseFile = NULL;
  910. LicenseListLoadOld();
  911. return;
  912. }
  913. if ( ( Version != LICENSE_FILE_VERSION ) || ( DataSize != sizeof(LICENSE_FILE_HEADER) ) ) {
  914. Status = STATUS_FILE_INVALID;
  915. goto LicenseListLoadExit;
  916. }
  917. //
  918. // The init header checks out, so load the license header and data blocks
  919. //
  920. hFile = PurchaseFile;
  921. ret = ReadFile(hFile, &FileHeader, sizeof(LICENSE_FILE_HEADER), &BytesRead, NULL);
  922. LicenseServiceTableSize = 0;
  923. LicenseServiceStringSize = 0;
  924. LicenseTableSize = 0;
  925. LicenseStringSize = 0;
  926. if (ret) {
  927. //
  928. // Run through and allocate space to read data blocks into
  929. //
  930. if (FileHeader.LicenseServiceTableSize != 0) {
  931. LicenseServiceTableSize = FileHeader.LicenseServiceTableSize / sizeof(PACK_LICENSE_SERVICE_RECORD);
  932. LicenseServices = MIDL_user_allocate(FileHeader.LicenseServiceTableSize);
  933. if ( LicenseServices == NULL ) {
  934. Status = STATUS_NO_MEMORY;
  935. goto LicenseListLoadExit;
  936. }
  937. }
  938. if (FileHeader.LicenseServiceStringSize != 0) {
  939. LicenseServiceStringSize = FileHeader.LicenseServiceStringSize / sizeof(TCHAR);
  940. LicenseServiceStrings = MIDL_user_allocate(FileHeader.LicenseServiceStringSize);
  941. if ( LicenseServiceStrings == NULL ) {
  942. Status = STATUS_NO_MEMORY;
  943. goto LicenseListLoadExit;
  944. }
  945. }
  946. if (FileHeader.LicenseServiceTableSize != 0) {
  947. PerServerLicenseServiceTableSize = FileHeader.PerServerLicenseServiceTableSize / sizeof(PACK_LICENSE_SERVICE_RECORD);
  948. PerServerLicenseServices = MIDL_user_allocate(FileHeader.PerServerLicenseServiceTableSize);
  949. if ( PerServerLicenseServices == NULL ) {
  950. Status = STATUS_NO_MEMORY;
  951. goto LicenseListLoadExit;
  952. }
  953. }
  954. if (FileHeader.PerServerLicenseServiceStringSize != 0) {
  955. PerServerLicenseServiceStringSize = FileHeader.PerServerLicenseServiceStringSize / sizeof(TCHAR);
  956. PerServerLicenseServiceStrings = MIDL_user_allocate(FileHeader.PerServerLicenseServiceStringSize);
  957. if ( PerServerLicenseServiceStrings == NULL ) {
  958. Status = STATUS_NO_MEMORY;
  959. goto LicenseListLoadExit;
  960. }
  961. }
  962. if (FileHeader.LicenseTableSize != 0) {
  963. LicenseTableSize = FileHeader.LicenseTableSize / sizeof(PACK_LICENSE_PURCHASE_RECORD);
  964. Licenses = MIDL_user_allocate(FileHeader.LicenseTableSize);
  965. if ( Licenses == NULL ) {
  966. Status = STATUS_NO_MEMORY;
  967. goto LicenseListLoadExit;
  968. }
  969. }
  970. if (FileHeader.LicenseStringSize != 0) {
  971. LicenseStringSize = FileHeader.LicenseStringSize / sizeof(TCHAR);
  972. LicenseStrings = MIDL_user_allocate(FileHeader.LicenseStringSize);
  973. if ( LicenseStrings == NULL ) {
  974. Status = STATUS_NO_MEMORY;
  975. goto LicenseListLoadExit;
  976. }
  977. }
  978. }
  979. if (ret && (FileHeader.LicenseServiceTableSize != 0) )
  980. ret = ReadFile(hFile, LicenseServices, FileHeader.LicenseServiceTableSize, &BytesRead, NULL);
  981. if (ret && (FileHeader.LicenseServiceStringSize != 0) )
  982. ret = ReadFile(hFile, LicenseServiceStrings, FileHeader.LicenseServiceStringSize, &BytesRead, NULL);
  983. if (ret && (FileHeader.PerServerLicenseServiceTableSize != 0) )
  984. ret = ReadFile(hFile, PerServerLicenseServices, FileHeader.PerServerLicenseServiceTableSize, &BytesRead, NULL);
  985. if (ret && (FileHeader.PerServerLicenseServiceStringSize != 0) )
  986. ret = ReadFile(hFile, PerServerLicenseServiceStrings, FileHeader.PerServerLicenseServiceStringSize, &BytesRead, NULL);
  987. if (ret && (FileHeader.LicenseTableSize != 0) )
  988. ret = ReadFile(hFile, Licenses, FileHeader.LicenseTableSize, &BytesRead, NULL);
  989. if (ret && (FileHeader.LicenseStringSize != 0) )
  990. ret = ReadFile(hFile, LicenseStrings, FileHeader.LicenseStringSize, &BytesRead, NULL);
  991. if (!ret) {
  992. Status = GetLastError();
  993. goto LicenseListLoadExit;
  994. }
  995. //
  996. // Decrypt the data
  997. //
  998. Status = DeBlock(LicenseServices, FileHeader.LicenseServiceTableSize);
  999. if (Status == STATUS_SUCCESS)
  1000. Status = DeBlock(LicenseServiceStrings, FileHeader.LicenseServiceStringSize);
  1001. if (Status == STATUS_SUCCESS)
  1002. Status = DeBlock(PerServerLicenseServices, FileHeader.PerServerLicenseServiceTableSize);
  1003. if (Status == STATUS_SUCCESS)
  1004. Status = DeBlock(PerServerLicenseServiceStrings, FileHeader.PerServerLicenseServiceStringSize);
  1005. if (Status == STATUS_SUCCESS)
  1006. Status = DeBlock(Licenses, FileHeader.LicenseTableSize);
  1007. if (Status == STATUS_SUCCESS)
  1008. Status = DeBlock(LicenseStrings, FileHeader.LicenseStringSize);
  1009. if (Status != STATUS_SUCCESS)
  1010. goto LicenseListLoadExit;
  1011. //
  1012. // Unpack the string data
  1013. //
  1014. LicenseListStringsUnpack( LicenseServiceTableSize, LicenseServices,
  1015. LicenseServiceStringSize, LicenseServiceStrings,
  1016. LicenseTableSize, Licenses,
  1017. LicenseStringSize, LicenseStrings,
  1018. PerServerLicenseServiceTableSize, PerServerLicenseServices,
  1019. PerServerLicenseServiceStringSize, PerServerLicenseServiceStrings
  1020. );
  1021. //
  1022. // Unpack the license data
  1023. //
  1024. LicenseListUnpack( LicenseServiceTableSize, LicenseServices, LicenseTableSize, Licenses, PerServerLicenseServiceTableSize, PerServerLicenseServices );
  1025. LicenseListLoadExit:
  1026. // Note: Don't close the License Purchase File (keep it locked).
  1027. //
  1028. // Run through our tables and clean them up
  1029. //
  1030. if (LicenseServices != NULL)
  1031. MIDL_user_free(LicenseServices);
  1032. if (LicenseServiceStrings != NULL)
  1033. MIDL_user_free(LicenseServiceStrings);
  1034. if (PerServerLicenseServices != NULL)
  1035. MIDL_user_free(PerServerLicenseServices);
  1036. if (PerServerLicenseServiceStrings != NULL)
  1037. MIDL_user_free(PerServerLicenseServiceStrings);
  1038. if (Licenses != NULL)
  1039. MIDL_user_free(Licenses);
  1040. if (LicenseStrings != NULL)
  1041. MIDL_user_free(LicenseStrings);
  1042. //
  1043. // If there was an error log it.
  1044. //
  1045. if (Status != STATUS_SUCCESS)
  1046. LogEvent(LLS_EVENT_LOAD_LICENSE, 0, NULL, Status);
  1047. } // LicenseListLoad
  1048. /////////////////////////////////////////////////////////////////////////
  1049. NTSTATUS
  1050. LicenseListSave()
  1051. /*++
  1052. Routine Description:
  1053. Arguments:
  1054. None.
  1055. Return Value:
  1056. None.
  1057. --*/
  1058. {
  1059. BOOL ret = TRUE;
  1060. NTSTATUS Status = STATUS_SUCCESS;
  1061. HANDLE hFile = NULL;
  1062. ULONG LicenseServiceTableSize;
  1063. PPACK_LICENSE_SERVICE_RECORD LicenseServices = NULL;
  1064. ULONG LicenseServiceStringSize;
  1065. LPTSTR LicenseServiceStrings = NULL;
  1066. ULONG PerServerLicenseServiceTableSize;
  1067. PPACK_LICENSE_SERVICE_RECORD PerServerLicenseServices = NULL;
  1068. ULONG PerServerLicenseServiceStringSize;
  1069. LPTSTR PerServerLicenseServiceStrings = NULL;
  1070. ULONG LicenseTableSize;
  1071. PPACK_LICENSE_PURCHASE_RECORD Licenses = NULL;
  1072. ULONG LicenseStringSize;
  1073. LPTSTR LicenseStrings = NULL;
  1074. LICENSE_FILE_HEADER FileHeader;
  1075. DWORD BytesWritten;
  1076. #if DBG
  1077. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_DATABASE))
  1078. dprintf(TEXT("LLS TRACE: LicenseListSave\n"));
  1079. #endif
  1080. RtlAcquireResourceExclusive(&LicenseListLock, TRUE);
  1081. //
  1082. // Check if we already have file open
  1083. //
  1084. if (PurchaseFile != NULL) {
  1085. CloseHandle(PurchaseFile);
  1086. PurchaseFile = NULL;
  1087. }
  1088. //
  1089. // If nothing to save then get-out
  1090. //
  1091. if ( (LicenseServiceListSize == 0) && (PerServerLicenseServiceListSize == 0) )
  1092. goto LicenseListSaveExit;
  1093. //
  1094. // Pack the license data
  1095. //
  1096. Status = LicenseListPack( &LicenseServiceTableSize, &LicenseServices, &LicenseTableSize, &Licenses, &PerServerLicenseServiceTableSize, &PerServerLicenseServices );
  1097. if (Status != STATUS_SUCCESS)
  1098. goto LicenseListSaveExit;
  1099. //
  1100. // Now pack the String data
  1101. //
  1102. Status = LicenseListStringsPack( LicenseServiceTableSize, LicenseServices,
  1103. &LicenseServiceStringSize, &LicenseServiceStrings,
  1104. LicenseTableSize, Licenses,
  1105. &LicenseStringSize, &LicenseStrings,
  1106. PerServerLicenseServiceTableSize, PerServerLicenseServices,
  1107. &PerServerLicenseServiceStringSize, &PerServerLicenseServiceStrings );
  1108. if (Status != STATUS_SUCCESS)
  1109. goto LicenseListSaveExit;
  1110. //
  1111. // Fill out the file header - sizes are byte sizes
  1112. //
  1113. FileHeader.LicenseServiceTableSize = LicenseServiceTableSize * sizeof(PACK_LICENSE_SERVICE_RECORD);
  1114. FileHeader.LicenseServiceStringSize = LicenseServiceStringSize * sizeof(TCHAR);
  1115. FileHeader.PerServerLicenseServiceTableSize = PerServerLicenseServiceTableSize * sizeof(PACK_LICENSE_SERVICE_RECORD);
  1116. FileHeader.PerServerLicenseServiceStringSize = PerServerLicenseServiceStringSize * sizeof(TCHAR);
  1117. FileHeader.LicenseTableSize = LicenseTableSize * sizeof(PACK_LICENSE_PURCHASE_RECORD);
  1118. FileHeader.LicenseStringSize = LicenseStringSize * sizeof(TCHAR);
  1119. //
  1120. // Encrypt the data before saving it out.
  1121. //
  1122. Status = EBlock(LicenseServices, FileHeader.LicenseServiceTableSize);
  1123. if (Status == STATUS_SUCCESS)
  1124. Status = EBlock(LicenseServiceStrings, FileHeader.LicenseServiceStringSize);
  1125. if (Status == STATUS_SUCCESS)
  1126. Status = EBlock(PerServerLicenseServices, FileHeader.PerServerLicenseServiceTableSize);
  1127. if (Status == STATUS_SUCCESS)
  1128. Status = EBlock(PerServerLicenseServiceStrings, FileHeader.PerServerLicenseServiceStringSize);
  1129. if (Status == STATUS_SUCCESS)
  1130. Status = EBlock(Licenses, FileHeader.LicenseTableSize);
  1131. if (Status == STATUS_SUCCESS)
  1132. Status = EBlock(LicenseStrings, FileHeader.LicenseStringSize);
  1133. if (Status != STATUS_SUCCESS)
  1134. goto LicenseListSaveExit;
  1135. //
  1136. // Save out the header record
  1137. //
  1138. PurchaseFile = LlsFileInit(LicenseFileName, LICENSE_FILE_VERSION, sizeof(LICENSE_FILE_HEADER) );
  1139. if (PurchaseFile == NULL) {
  1140. Status = GetLastError();
  1141. goto LicenseListSaveExit;
  1142. }
  1143. //
  1144. // Now write out all the data blocks
  1145. //
  1146. hFile = PurchaseFile;
  1147. ret = WriteFile(hFile, &FileHeader, sizeof(LICENSE_FILE_HEADER), &BytesWritten, NULL);
  1148. if (ret && (LicenseServices != NULL) && (FileHeader.LicenseServiceTableSize != 0))
  1149. ret = WriteFile(hFile, LicenseServices, FileHeader.LicenseServiceTableSize, &BytesWritten, NULL);
  1150. if (ret && (LicenseServiceStrings != NULL) && (FileHeader.LicenseServiceStringSize != 0))
  1151. ret = WriteFile(hFile, LicenseServiceStrings, FileHeader.LicenseServiceStringSize, &BytesWritten, NULL);
  1152. if (ret && (PerServerLicenseServices != NULL) && (FileHeader.PerServerLicenseServiceTableSize != 0))
  1153. ret = WriteFile(hFile, PerServerLicenseServices, FileHeader.PerServerLicenseServiceTableSize, &BytesWritten, NULL);
  1154. if (ret && (PerServerLicenseServiceStrings != NULL) && (FileHeader.PerServerLicenseServiceStringSize != 0))
  1155. ret = WriteFile(hFile, PerServerLicenseServiceStrings, FileHeader.PerServerLicenseServiceStringSize, &BytesWritten, NULL);
  1156. if (ret && (Licenses != NULL) && (FileHeader.LicenseTableSize != 0))
  1157. ret = WriteFile(hFile, Licenses, FileHeader.LicenseTableSize, &BytesWritten, NULL);
  1158. if (ret && (LicenseStrings != NULL) && (FileHeader.LicenseStringSize != 0))
  1159. ret = WriteFile(hFile, LicenseStrings, FileHeader.LicenseStringSize, &BytesWritten, NULL);
  1160. if (!ret)
  1161. Status = GetLastError();
  1162. LicenseListSaveExit:
  1163. RtlReleaseResource(&LicenseListLock);
  1164. // Note: Don't close the License Purchase File (keep it locked).
  1165. if (hFile != NULL)
  1166. FlushFileBuffers(hFile);
  1167. //
  1168. // Run through our tables and clean them up
  1169. //
  1170. if (LicenseServices != NULL)
  1171. MIDL_user_free(LicenseServices);
  1172. if (LicenseServiceStrings != NULL)
  1173. MIDL_user_free(LicenseServiceStrings);
  1174. if (PerServerLicenseServices != NULL)
  1175. MIDL_user_free(PerServerLicenseServices);
  1176. if (PerServerLicenseServiceStrings != NULL)
  1177. MIDL_user_free(PerServerLicenseServiceStrings);
  1178. if (Licenses != NULL)
  1179. MIDL_user_free(Licenses);
  1180. if (LicenseStrings != NULL)
  1181. MIDL_user_free(LicenseStrings);
  1182. //
  1183. // If there was an error log it.
  1184. //
  1185. if (Status != STATUS_SUCCESS)
  1186. LogEvent(LLS_EVENT_SAVE_LICENSE, 0, NULL, Status);
  1187. return Status;
  1188. } // LicenseListSave
  1189. /////////////////////////////////////////////////////////////////////////
  1190. // Mapping List
  1191. //
  1192. /////////////////////////////////////////////////////////////////////////
  1193. NTSTATUS
  1194. MappingListPack (
  1195. ULONG *pMappingUserTableSize,
  1196. PPACK_MAPPING_USER_RECORD *pMappingUsers,
  1197. ULONG *pMappingTableSize,
  1198. PPACK_MAPPING_RECORD *pMappings
  1199. )
  1200. /*++
  1201. Routine Description:
  1202. Arguments:
  1203. Return Value:
  1204. --*/
  1205. {
  1206. NTSTATUS Status = STATUS_SUCCESS;
  1207. PPACK_MAPPING_USER_RECORD MappingUsers = NULL;
  1208. PPACK_MAPPING_RECORD Mappings = NULL;
  1209. ULONG i, j, k;
  1210. ULONG TotalRecords = 0;
  1211. PMAPPING_RECORD pMapping;
  1212. #if DBG
  1213. if (TraceFlags & TRACE_FUNCTION_TRACE)
  1214. dprintf(TEXT("LLS TRACE: MappingListPack\n"));
  1215. #endif
  1216. ASSERT(pMappingUsers != NULL);
  1217. ASSERT(pMappingUserTableSize != NULL);
  1218. *pMappingUsers = NULL;
  1219. *pMappingUserTableSize = 0;
  1220. ASSERT(pMappings != NULL);
  1221. ASSERT(pMappingTableSize != NULL);
  1222. *pMappings = NULL;
  1223. *pMappingTableSize = 0;
  1224. //////////////////////////////////////////////////////////////////
  1225. //
  1226. // Do Mapping User Table First
  1227. //
  1228. TotalRecords = 0;
  1229. //
  1230. // Make sure there is anything to replicate
  1231. //
  1232. for (i = 0; i < MappingListSize; i++)
  1233. TotalRecords += MappingList[i]->NumMembers;
  1234. if (TotalRecords > 0) {
  1235. //
  1236. // Create our buffer to hold all of the garbage
  1237. //
  1238. MappingUsers = MIDL_user_allocate(TotalRecords * sizeof(PACK_MAPPING_USER_RECORD));
  1239. if (MappingUsers == NULL) {
  1240. ASSERT(FALSE);
  1241. return STATUS_NO_MEMORY;
  1242. }
  1243. //
  1244. // Fill in the buffer - walk the Mapping tree
  1245. //
  1246. k = 0;
  1247. for (i = 0; i < MappingListSize; i++) {
  1248. pMapping = MappingList[i];
  1249. for (j = 0; j < pMapping->NumMembers; j++) {
  1250. MappingUsers[k].Mapping = i;
  1251. MappingUsers[k].Name = pMapping->Members[j];
  1252. k++;
  1253. }
  1254. }
  1255. }
  1256. *pMappingUsers = MappingUsers;
  1257. *pMappingUserTableSize = TotalRecords;
  1258. //////////////////////////////////////////////////////////////////
  1259. //
  1260. // Now Do Mapping Records
  1261. //
  1262. TotalRecords = MappingListSize;
  1263. //
  1264. // Make sure there is anything to replicate
  1265. //
  1266. if (TotalRecords > 0) {
  1267. //
  1268. // Create our buffer to hold all of the garbage
  1269. //
  1270. Mappings = MIDL_user_allocate(TotalRecords * sizeof(PACK_MAPPING_RECORD));
  1271. if (Mappings == NULL) {
  1272. ASSERT(FALSE);
  1273. //
  1274. // Clean up already alloc'd information
  1275. //
  1276. if (MappingUsers != NULL)
  1277. MIDL_user_free(MappingUsers);
  1278. *pMappingUsers = NULL;
  1279. *pMappingUserTableSize = 0;
  1280. return STATUS_NO_MEMORY;
  1281. }
  1282. //
  1283. // Fill in the buffer - walk the License Purchase tree
  1284. //
  1285. for (i = 0; i < MappingListSize; i++) {
  1286. pMapping = MappingList[i];
  1287. Mappings[i].Name = pMapping->Name;
  1288. Mappings[i].Comment = pMapping->Comment;
  1289. Mappings[i].Licenses = pMapping->Licenses;
  1290. }
  1291. }
  1292. *pMappings = Mappings;
  1293. *pMappingTableSize = TotalRecords;
  1294. return Status;
  1295. } // MappingListPack
  1296. /////////////////////////////////////////////////////////////////////////
  1297. VOID
  1298. MappingListUnpack (
  1299. ULONG MappingUserTableSize,
  1300. PPACK_MAPPING_USER_RECORD MappingUsers,
  1301. ULONG MappingTableSize,
  1302. PPACK_MAPPING_RECORD Mappings
  1303. )
  1304. /*++
  1305. Routine Description:
  1306. Arguments:
  1307. Return Value:
  1308. --*/
  1309. {
  1310. NTSTATUS Status;
  1311. ULONG i;
  1312. PPACK_MAPPING_USER_RECORD pUsr;
  1313. PPACK_MAPPING_RECORD pMapping;
  1314. PMAPPING_RECORD pMap;
  1315. #if DBG
  1316. if (TraceFlags & TRACE_FUNCTION_TRACE)
  1317. dprintf(TEXT("MappingListUnpack: Mappings[%lu] TotalUsers[%lu]\n"), MappingTableSize, MappingUserTableSize);
  1318. #endif
  1319. RtlAcquireResourceExclusive(&MappingListLock, TRUE);
  1320. //
  1321. // Add the Mappings first
  1322. //
  1323. for (i = 0; i < MappingTableSize; i++) {
  1324. pMapping = &Mappings[i];
  1325. pMap = MappingListAdd(pMapping->Name, pMapping->Comment, pMapping->Licenses,NULL);
  1326. if (i % 100 == 0) ReportStatusToSCMgr( SERVICE_START_PENDING, NO_ERROR, NSERVICEWAITHINT);
  1327. }
  1328. //
  1329. // Now add the users to the mappings...
  1330. //
  1331. for (i = 0; i < MappingUserTableSize; i++) {
  1332. pUsr = &MappingUsers[i];
  1333. pMap = NULL;
  1334. if (pUsr->Mapping < MappingTableSize)
  1335. pMap = MappingUserListAdd(Mappings[pUsr->Mapping].Name, pUsr->Name);
  1336. #if DBG
  1337. if (pMap == NULL) {
  1338. dprintf(TEXT("pMap: 0x%lX pUsr->Mapping: %lu MappingTableSize: %lu\n"), pMap, pUsr->Mapping, MappingTableSize);
  1339. ASSERT(FALSE);
  1340. }
  1341. #endif
  1342. if (i % 100 == 0) ReportStatusToSCMgr( SERVICE_START_PENDING, NO_ERROR, NSERVICEWAITHINT);
  1343. }
  1344. RtlReleaseResource(&MappingListLock);
  1345. } // MappingListUnpack
  1346. /////////////////////////////////////////////////////////////////////////
  1347. NTSTATUS
  1348. MappingListStringsPack (
  1349. ULONG MappingUserTableSize,
  1350. PPACK_MAPPING_USER_RECORD MappingUsers,
  1351. ULONG *pMappingUserStringSize,
  1352. LPTSTR *pMappingUserStrings,
  1353. ULONG MappingTableSize,
  1354. PPACK_MAPPING_RECORD Mappings,
  1355. ULONG *pMappingStringSize,
  1356. LPTSTR *pMappingStrings
  1357. )
  1358. /*++
  1359. Routine Description:
  1360. Arguments:
  1361. Return Value:
  1362. --*/
  1363. {
  1364. NTSTATUS Status = STATUS_SUCCESS;
  1365. ULONG i;
  1366. ULONG StringSize;
  1367. PPACK_MAPPING_USER_RECORD pUsr;
  1368. PPACK_MAPPING_RECORD pMapping;
  1369. LPTSTR MappingUserStrings = NULL;
  1370. LPTSTR MappingStrings = NULL;
  1371. TCHAR *pStr;
  1372. #if DBG
  1373. if (TraceFlags & TRACE_FUNCTION_TRACE)
  1374. dprintf(TEXT("MappingListStringsPack\n"));
  1375. #endif
  1376. ASSERT(pMappingUserStrings != NULL);
  1377. ASSERT(pMappingUserStringSize != NULL);
  1378. *pMappingUserStrings = NULL;
  1379. *pMappingUserStringSize = 0;
  1380. ASSERT(pMappingStrings != NULL);
  1381. ASSERT(pMappingStringSize != NULL);
  1382. *pMappingStrings = NULL;
  1383. *pMappingStringSize = 0;
  1384. //////////////////////////////////////////////////////////////////
  1385. //
  1386. // Do Mapping User Strings
  1387. //
  1388. //
  1389. // First walk the list adding up string sizes - to calculate our buff size
  1390. //
  1391. StringSize = 0;
  1392. for (i = 0; i < MappingUserTableSize; i++) {
  1393. pUsr = &MappingUsers[i];
  1394. StringSize = StringSize + lstrlen(pUsr->Name) + 1;
  1395. }
  1396. //
  1397. // Make sure there is anything to replicate
  1398. //
  1399. if (StringSize > 0) {
  1400. //
  1401. // Create our buffer to hold all of the garbage
  1402. //
  1403. MappingUserStrings = MIDL_user_allocate(StringSize * sizeof(TCHAR));
  1404. if (MappingUserStrings == NULL) {
  1405. ASSERT(FALSE);
  1406. return STATUS_NO_MEMORY;
  1407. }
  1408. //
  1409. // Fill in the buffer
  1410. //
  1411. pStr = MappingUserStrings;
  1412. for (i = 0; i < MappingUserTableSize; i++) {
  1413. pUsr = &MappingUsers[i];
  1414. lstrcpy(pStr, pUsr->Name);
  1415. pStr = &pStr[lstrlen(pUsr->Name) + 1];
  1416. }
  1417. }
  1418. *pMappingUserStrings = MappingUserStrings;
  1419. *pMappingUserStringSize = StringSize;
  1420. //////////////////////////////////////////////////////////////////
  1421. //
  1422. // Now Do Mapping Strings
  1423. //
  1424. //
  1425. // First walk the list adding up string sizes - to calculate our buff size
  1426. //
  1427. StringSize = 0;
  1428. for (i = 0; i < MappingTableSize; i++) {
  1429. pMapping = &Mappings[i];
  1430. StringSize = StringSize + lstrlen(pMapping->Name) + 1;
  1431. StringSize = StringSize + lstrlen(pMapping->Comment) + 1;
  1432. }
  1433. //
  1434. // Make sure there is anything to replicate
  1435. //
  1436. if (StringSize > 0) {
  1437. //
  1438. // Create our buffer to hold all of the garbage
  1439. //
  1440. MappingStrings = MIDL_user_allocate(StringSize * sizeof(TCHAR));
  1441. if (MappingStrings == NULL) {
  1442. ASSERT(FALSE);
  1443. //
  1444. // Clean up already alloc'd information
  1445. //
  1446. if (MappingUserStrings != NULL)
  1447. MIDL_user_free(MappingUserStrings);
  1448. *pMappingUserStrings = NULL;
  1449. *pMappingUserStringSize = 0;
  1450. return STATUS_NO_MEMORY;
  1451. }
  1452. //
  1453. // Fill in the buffer
  1454. //
  1455. pStr = MappingStrings;
  1456. for (i = 0; i < MappingTableSize; i++) {
  1457. pMapping = &Mappings[i];
  1458. lstrcpy(pStr, pMapping->Name);
  1459. pStr = &pStr[lstrlen(pMapping->Name) + 1];
  1460. lstrcpy(pStr, pMapping->Comment);
  1461. pStr = &pStr[lstrlen(pMapping->Comment) + 1];
  1462. }
  1463. }
  1464. *pMappingStrings = MappingStrings;
  1465. *pMappingStringSize = StringSize;
  1466. return Status;
  1467. } // MappingListStringsPack
  1468. /////////////////////////////////////////////////////////////////////////
  1469. VOID
  1470. MappingListStringsUnpack (
  1471. ULONG MappingUserTableSize,
  1472. PPACK_MAPPING_USER_RECORD MappingUsers,
  1473. ULONG MappingUserStringSize,
  1474. LPTSTR MappingUserStrings,
  1475. ULONG MappingTableSize,
  1476. PPACK_MAPPING_RECORD Mappings,
  1477. ULONG MappingStringSize,
  1478. LPTSTR MappingStrings
  1479. )
  1480. /*++
  1481. Routine Description:
  1482. Arguments:
  1483. Return Value:
  1484. --*/
  1485. {
  1486. ULONG i;
  1487. PPACK_MAPPING_USER_RECORD pUsr;
  1488. PPACK_MAPPING_RECORD pMapping;
  1489. TCHAR *pStr;
  1490. #if DBG
  1491. if (TraceFlags & TRACE_FUNCTION_TRACE)
  1492. dprintf(TEXT("MappingListStringsUnpack\n"));
  1493. #endif
  1494. //
  1495. // First do license service strings
  1496. //
  1497. pStr = MappingUserStrings;
  1498. for (i = 0; i < MappingUserTableSize; i++) {
  1499. pUsr = &MappingUsers[i];
  1500. pUsr->Name = pStr;
  1501. //
  1502. // Move to end of current string
  1503. //
  1504. while (*pStr != TEXT('\0'))
  1505. pStr++;
  1506. // now go past ending NULL
  1507. pStr++;
  1508. }
  1509. //
  1510. // Now do license purchase strings
  1511. //
  1512. pStr = MappingStrings;
  1513. for (i = 0; i < MappingTableSize; i++) {
  1514. pMapping = &Mappings[i];
  1515. pMapping->Name = pStr;
  1516. //
  1517. // Move to end of current string
  1518. //
  1519. while (*pStr != TEXT('\0'))
  1520. pStr++;
  1521. // now go past ending NULL
  1522. pStr++;
  1523. pMapping->Comment = pStr;
  1524. //
  1525. // Move to end of current string
  1526. //
  1527. while (*pStr != TEXT('\0'))
  1528. pStr++;
  1529. // now go past ending NULL
  1530. pStr++;
  1531. }
  1532. } // MappingListStringsUnpack
  1533. /////////////////////////////////////////////////////////////////////////
  1534. VOID
  1535. MappingListLoad()
  1536. /*++
  1537. Routine Description:
  1538. Arguments:
  1539. None.
  1540. Return Value:
  1541. None.
  1542. --*/
  1543. {
  1544. BOOL ret;
  1545. DWORD Version, DataSize;
  1546. NTSTATUS Status = STATUS_SUCCESS;
  1547. HANDLE hFile = NULL;
  1548. ULONG MappingUserTableSize;
  1549. PPACK_MAPPING_USER_RECORD MappingUsers = NULL;
  1550. ULONG MappingUserStringSize;
  1551. LPTSTR MappingUserStrings = NULL;
  1552. ULONG MappingTableSize;
  1553. PPACK_MAPPING_RECORD Mappings = NULL;
  1554. ULONG MappingStringSize;
  1555. LPTSTR MappingStrings = NULL;
  1556. MAPPING_FILE_HEADER FileHeader;
  1557. DWORD BytesRead;
  1558. #if DBG
  1559. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_DATABASE))
  1560. dprintf(TEXT("LLS TRACE: MappingListLoad\n"));
  1561. #endif
  1562. //
  1563. // If nothing to load then get-out
  1564. //
  1565. if (!FileExists(MappingFileName))
  1566. goto MappingListLoadExit;
  1567. //
  1568. // Check the init header
  1569. //
  1570. Version = DataSize = 0;
  1571. hFile = LlsFileCheck(MappingFileName, &Version, &DataSize );
  1572. if (hFile == NULL) {
  1573. Status = GetLastError();
  1574. goto MappingListLoadExit;
  1575. }
  1576. if ((Version != MAPPING_FILE_VERSION) || (DataSize != sizeof(MAPPING_FILE_HEADER))) {
  1577. Status = STATUS_FILE_INVALID;
  1578. goto MappingListLoadExit;
  1579. }
  1580. //
  1581. // The init header checks out, so load the license header and data blocks
  1582. //
  1583. ret = ReadFile(hFile, &FileHeader, sizeof(MAPPING_FILE_HEADER), &BytesRead, NULL);
  1584. MappingUserTableSize = 0;
  1585. MappingUserStringSize = 0;
  1586. MappingTableSize = 0;
  1587. MappingStringSize = 0;
  1588. if (ret) {
  1589. //
  1590. // Run through and allocate space to read data blocks into
  1591. //
  1592. if (FileHeader.MappingUserTableSize != 0) {
  1593. MappingUserTableSize = FileHeader.MappingUserTableSize / sizeof(PACK_MAPPING_USER_RECORD);
  1594. MappingUsers = MIDL_user_allocate(FileHeader.MappingUserTableSize);
  1595. if ( MappingUsers == NULL ) {
  1596. Status = STATUS_NO_MEMORY;
  1597. goto MappingListLoadExit;
  1598. }
  1599. }
  1600. if (FileHeader.MappingUserStringSize != 0) {
  1601. MappingUserStringSize = FileHeader.MappingUserStringSize / sizeof(TCHAR);
  1602. MappingUserStrings = MIDL_user_allocate(FileHeader.MappingUserStringSize);
  1603. if ( MappingUserStrings == NULL ) {
  1604. Status = STATUS_NO_MEMORY;
  1605. goto MappingListLoadExit;
  1606. }
  1607. }
  1608. if (FileHeader.MappingTableSize != 0) {
  1609. MappingTableSize = FileHeader.MappingTableSize / sizeof(PACK_MAPPING_RECORD);
  1610. Mappings = MIDL_user_allocate(FileHeader.MappingTableSize);
  1611. if ( Mappings == NULL ) {
  1612. Status = STATUS_NO_MEMORY;
  1613. goto MappingListLoadExit;
  1614. }
  1615. }
  1616. if (FileHeader.MappingStringSize != 0) {
  1617. MappingStringSize = FileHeader.MappingStringSize / sizeof(TCHAR);
  1618. MappingStrings = MIDL_user_allocate(FileHeader.MappingStringSize);
  1619. if ( MappingStrings == NULL ) {
  1620. Status = STATUS_NO_MEMORY;
  1621. goto MappingListLoadExit;
  1622. }
  1623. }
  1624. }
  1625. if (ret && (FileHeader.MappingUserTableSize != 0) )
  1626. ret = ReadFile(hFile, MappingUsers, FileHeader.MappingUserTableSize, &BytesRead, NULL);
  1627. if (ret && (FileHeader.MappingUserStringSize != 0) )
  1628. ret = ReadFile(hFile, MappingUserStrings, FileHeader.MappingUserStringSize, &BytesRead, NULL);
  1629. if (ret && (FileHeader.MappingTableSize != 0) )
  1630. ret = ReadFile(hFile, Mappings, FileHeader.MappingTableSize, &BytesRead, NULL);
  1631. if (ret && (FileHeader.MappingStringSize != 0) )
  1632. ret = ReadFile(hFile, MappingStrings, FileHeader.MappingStringSize, &BytesRead, NULL);
  1633. if (!ret) {
  1634. Status = GetLastError();
  1635. goto MappingListLoadExit;
  1636. }
  1637. //
  1638. // Decrypt the data
  1639. //
  1640. Status = DeBlock(MappingUsers, FileHeader.MappingUserTableSize);
  1641. if (Status == STATUS_SUCCESS)
  1642. Status = DeBlock(MappingUserStrings, FileHeader.MappingUserStringSize);
  1643. if (Status == STATUS_SUCCESS)
  1644. Status = DeBlock(Mappings, FileHeader.MappingTableSize);
  1645. if (Status == STATUS_SUCCESS)
  1646. Status = DeBlock(MappingStrings, FileHeader.MappingStringSize);
  1647. if (Status != STATUS_SUCCESS)
  1648. goto MappingListLoadExit;
  1649. //
  1650. // Unpack the string data
  1651. //
  1652. MappingListStringsUnpack( MappingUserTableSize, MappingUsers,
  1653. MappingUserStringSize, MappingUserStrings,
  1654. MappingTableSize, Mappings,
  1655. MappingStringSize, MappingStrings );
  1656. //
  1657. // Unpack the data
  1658. //
  1659. MappingListUnpack( MappingUserTableSize, MappingUsers, MappingTableSize, Mappings );
  1660. MappingListLoadExit:
  1661. if (hFile != NULL)
  1662. CloseHandle(hFile);
  1663. //
  1664. // Run through our tables and clean them up
  1665. //
  1666. if (MappingUsers != NULL)
  1667. MIDL_user_free(MappingUsers);
  1668. if (MappingUserStrings != NULL)
  1669. MIDL_user_free(MappingUserStrings);
  1670. if (Mappings != NULL)
  1671. MIDL_user_free(Mappings);
  1672. if (MappingStrings != NULL)
  1673. MIDL_user_free(MappingStrings);
  1674. //
  1675. // If there was an error log it.
  1676. //
  1677. if (Status != STATUS_SUCCESS)
  1678. LogEvent(LLS_EVENT_LOAD_MAPPING, 0, NULL, Status);
  1679. } // MappingListLoad
  1680. /////////////////////////////////////////////////////////////////////////
  1681. NTSTATUS
  1682. MappingListSave()
  1683. /*++
  1684. Routine Description:
  1685. Arguments:
  1686. None.
  1687. Return Value:
  1688. None.
  1689. --*/
  1690. {
  1691. BOOL ret = TRUE;
  1692. NTSTATUS Status = STATUS_SUCCESS;
  1693. HANDLE hFile = NULL;
  1694. ULONG MappingUserTableSize;
  1695. PPACK_MAPPING_USER_RECORD MappingUsers = NULL;
  1696. ULONG MappingUserStringSize;
  1697. LPTSTR MappingUserStrings = NULL;
  1698. ULONG MappingTableSize;
  1699. PPACK_MAPPING_RECORD Mappings = NULL;
  1700. ULONG MappingStringSize;
  1701. LPTSTR MappingStrings = NULL;
  1702. MAPPING_FILE_HEADER FileHeader;
  1703. DWORD BytesWritten;
  1704. #if DBG
  1705. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_DATABASE))
  1706. dprintf(TEXT("LLS TRACE: MappingListSave\n"));
  1707. #endif
  1708. RtlAcquireResourceExclusive(&MappingListLock, TRUE);
  1709. //
  1710. // If nothing to save then get-out
  1711. //
  1712. if (MappingListSize == 0)
  1713. goto MappingListSaveExit;
  1714. //
  1715. // Pack the data
  1716. //
  1717. Status = MappingListPack( &MappingUserTableSize, &MappingUsers, &MappingTableSize, &Mappings );
  1718. if (Status != STATUS_SUCCESS)
  1719. goto MappingListSaveExit;
  1720. //
  1721. // Now pack the String data
  1722. //
  1723. Status = MappingListStringsPack( MappingUserTableSize, MappingUsers,
  1724. &MappingUserStringSize, &MappingUserStrings,
  1725. MappingTableSize, Mappings,
  1726. &MappingStringSize, &MappingStrings );
  1727. if (Status != STATUS_SUCCESS)
  1728. goto MappingListSaveExit;
  1729. //
  1730. // Fill out the file header - sizes are byte sizes
  1731. //
  1732. FileHeader.MappingUserTableSize = MappingUserTableSize * sizeof(PACK_MAPPING_USER_RECORD);
  1733. FileHeader.MappingUserStringSize = MappingUserStringSize * sizeof(TCHAR);
  1734. FileHeader.MappingTableSize = MappingTableSize * sizeof(PACK_MAPPING_RECORD);
  1735. FileHeader.MappingStringSize = MappingStringSize * sizeof(TCHAR);
  1736. //
  1737. // Encrypt the data before saving it out.
  1738. //
  1739. Status = EBlock(MappingUsers, FileHeader.MappingUserTableSize);
  1740. if (Status == STATUS_SUCCESS)
  1741. Status = EBlock(MappingUserStrings, FileHeader.MappingUserStringSize);
  1742. if (Status == STATUS_SUCCESS)
  1743. Status = EBlock(Mappings, FileHeader.MappingTableSize);
  1744. if (Status == STATUS_SUCCESS)
  1745. Status = EBlock(MappingStrings, FileHeader.MappingStringSize);
  1746. if (Status != STATUS_SUCCESS)
  1747. goto MappingListSaveExit;
  1748. //
  1749. // Save out the header record
  1750. //
  1751. hFile = LlsFileInit(MappingFileName, MAPPING_FILE_VERSION, sizeof(MAPPING_FILE_HEADER) );
  1752. if (hFile == NULL) {
  1753. Status = GetLastError();
  1754. goto MappingListSaveExit;
  1755. }
  1756. //
  1757. // Now write out all the data blocks
  1758. //
  1759. ret = WriteFile(hFile, &FileHeader, sizeof(MAPPING_FILE_HEADER), &BytesWritten, NULL);
  1760. if (ret && (MappingUsers != NULL) && (FileHeader.MappingUserTableSize != 0))
  1761. ret = WriteFile(hFile, MappingUsers, FileHeader.MappingUserTableSize, &BytesWritten, NULL);
  1762. if (ret && (MappingUserStrings != NULL) && (FileHeader.MappingUserStringSize != 0))
  1763. ret = WriteFile(hFile, MappingUserStrings, FileHeader.MappingUserStringSize, &BytesWritten, NULL);
  1764. if (ret && (Mappings != NULL) && (FileHeader.MappingTableSize != 0))
  1765. ret = WriteFile(hFile, Mappings, FileHeader.MappingTableSize, &BytesWritten, NULL);
  1766. if (ret && (MappingStrings != NULL) && (FileHeader.MappingStringSize != 0))
  1767. ret = WriteFile(hFile, MappingStrings, FileHeader.MappingStringSize, &BytesWritten, NULL);
  1768. if (!ret)
  1769. Status = GetLastError();
  1770. MappingListSaveExit:
  1771. RtlReleaseResource(&MappingListLock);
  1772. if (hFile != NULL)
  1773. CloseHandle(hFile);
  1774. //
  1775. // Run through our tables and clean them up
  1776. //
  1777. if (MappingUsers != NULL)
  1778. MIDL_user_free(MappingUsers);
  1779. if (MappingUserStrings != NULL)
  1780. MIDL_user_free(MappingUserStrings);
  1781. if (Mappings != NULL)
  1782. MIDL_user_free(Mappings);
  1783. if (MappingStrings != NULL)
  1784. MIDL_user_free(MappingStrings);
  1785. //
  1786. // If there was an error log it.
  1787. //
  1788. if (Status != STATUS_SUCCESS)
  1789. LogEvent(LLS_EVENT_SAVE_MAPPING, 0, NULL, Status);
  1790. return Status;
  1791. } // MappingListSave
  1792. /////////////////////////////////////////////////////////////////////////
  1793. // User List
  1794. //
  1795. /////////////////////////////////////////////////////////////////////////
  1796. NTSTATUS
  1797. UserListPack (
  1798. DWORD LastReplicated,
  1799. ULONG UserLevel,
  1800. ULONG *pUserTableSize,
  1801. LPVOID *pUsers
  1802. )
  1803. /*++
  1804. Routine Description:
  1805. Arguments:
  1806. Return Value:
  1807. --*/
  1808. {
  1809. NTSTATUS Status = STATUS_SUCCESS;
  1810. LPVOID Users = NULL;
  1811. ULONG i, j, k;
  1812. ULONG TotalRecords = 0;
  1813. PUSER_RECORD pUser;
  1814. #if DBG
  1815. if (TraceFlags & TRACE_FUNCTION_TRACE)
  1816. dprintf(TEXT("LLS TRACE: UserListPack\n"));
  1817. #endif
  1818. ASSERT(pUsers != NULL);
  1819. ASSERT(pUserTableSize != NULL);
  1820. *pUsers = NULL;
  1821. *pUserTableSize = 0;
  1822. //
  1823. // Now walk our tree and figure out how many records we must send.
  1824. //
  1825. i = 0;
  1826. TotalRecords = 0;
  1827. while (i < UserListNumEntries) {
  1828. pUser = LLSGetElementGenericTable(&UserList, i);
  1829. if (pUser != NULL) {
  1830. //
  1831. // Walk each service under each user
  1832. //
  1833. RtlEnterCriticalSection(&pUser->ServiceTableLock);
  1834. for (j = 0; j < pUser->ServiceTableSize; j++)
  1835. if ( (pUser->Services[j].AccessCount > 0) || (pUser->Services[j].LastAccess > LastReplicated) )
  1836. TotalRecords++;
  1837. RtlLeaveCriticalSection(&pUser->ServiceTableLock);
  1838. }
  1839. i++;
  1840. }
  1841. #if DBG
  1842. if (TraceFlags & TRACE_REPLICATION)
  1843. dprintf(TEXT(" LLS Packing %lu User Records\n"), TotalRecords);
  1844. #endif
  1845. //
  1846. // Make sure there is anything to replicate
  1847. //
  1848. if (TotalRecords > 0) {
  1849. //
  1850. // Create our buffer to hold all of the garbage
  1851. //
  1852. Users = MIDL_user_allocate(TotalRecords * ( UserLevel ? sizeof(REPL_USER_RECORD_1)
  1853. : sizeof(REPL_USER_RECORD_0) ) );
  1854. if (Users == NULL) {
  1855. ASSERT(FALSE);
  1856. return STATUS_NO_MEMORY;
  1857. }
  1858. //
  1859. // Fill in the buffer - walk the user tree
  1860. //
  1861. i = 0;
  1862. j = 0;
  1863. while ((i < UserListNumEntries) && (j < TotalRecords)) {
  1864. pUser = LLSGetElementGenericTable(&UserList, i);
  1865. if (pUser != NULL) {
  1866. //
  1867. // Walk each service under each user
  1868. //
  1869. k = 0;
  1870. RtlEnterCriticalSection(&pUser->ServiceTableLock);
  1871. while (k < pUser->ServiceTableSize) {
  1872. if ( (pUser->Services[k].AccessCount > 0) || (pUser->Services[k].LastAccess > LastReplicated) ) {
  1873. if ( 0 == UserLevel )
  1874. {
  1875. ((PREPL_USER_RECORD_0)Users)[j].Name = pUser->UserID;
  1876. ((PREPL_USER_RECORD_0)Users)[j].Service = pUser->Services[k].Service->Index;
  1877. ((PREPL_USER_RECORD_0)Users)[j].AccessCount = pUser->Services[k].AccessCount;
  1878. ((PREPL_USER_RECORD_0)Users)[j].LastAccess = pUser->Services[k].LastAccess;
  1879. }
  1880. else
  1881. {
  1882. ((PREPL_USER_RECORD_1)Users)[j].Name = pUser->UserID;
  1883. ((PREPL_USER_RECORD_1)Users)[j].Service = pUser->Services[k].Service->Index;
  1884. ((PREPL_USER_RECORD_1)Users)[j].AccessCount = pUser->Services[k].AccessCount;
  1885. ((PREPL_USER_RECORD_1)Users)[j].LastAccess = pUser->Services[k].LastAccess;
  1886. ((PREPL_USER_RECORD_1)Users)[j].Flags = pUser->Flags;
  1887. }
  1888. //
  1889. // Reset access count so we don't increment forever
  1890. //
  1891. if (LastReplicated != 0)
  1892. pUser->Services[k].AccessCount = 0;
  1893. j++;
  1894. }
  1895. k++;
  1896. }
  1897. RtlLeaveCriticalSection(&pUser->ServiceTableLock);
  1898. }
  1899. i++;
  1900. }
  1901. } // User Records
  1902. #if DBG
  1903. if (TraceFlags & TRACE_REPLICATION)
  1904. dprintf(TEXT("UserListPack: [%lu]\n"), TotalRecords);
  1905. #endif
  1906. *pUsers = Users;
  1907. *pUserTableSize = TotalRecords;
  1908. return Status;
  1909. } // UserListPack
  1910. /////////////////////////////////////////////////////////////////////////
  1911. VOID
  1912. UserListUnpack (
  1913. ULONG ServiceTableSize,
  1914. PREPL_SERVICE_RECORD Services,
  1915. ULONG ServerTableSize,
  1916. PREPL_SERVER_RECORD Servers,
  1917. ULONG ServerServiceTableSize,
  1918. PREPL_SERVER_SERVICE_RECORD ServerServices,
  1919. ULONG UserLevel,
  1920. ULONG UserTableSize,
  1921. LPVOID Users
  1922. )
  1923. /*++
  1924. Routine Description:
  1925. Arguments:
  1926. Return Value:
  1927. --*/
  1928. {
  1929. NTSTATUS Status = STATUS_SUCCESS;
  1930. ULONG i;
  1931. PUSER_RECORD pUser;
  1932. PREPL_USER_RECORD_0 pReplUser0 = NULL;
  1933. PREPL_USER_RECORD_1 pReplUser1 = NULL;
  1934. PADD_CACHE pAdd = NULL;
  1935. PADD_CACHE tAdd = NULL;
  1936. PADD_CACHE lAdd = NULL;
  1937. ULONG CacheSize = 0;
  1938. ULONG DataLength;
  1939. LPTSTR NewName;
  1940. #if DBG
  1941. if (TraceFlags & (TRACE_REPLICATION | TRACE_FUNCTION_TRACE))
  1942. dprintf(TEXT("UserListUnpack: [%lu]\n"), UserTableSize);
  1943. #endif
  1944. //
  1945. // Walk User table. First fixup service pointers to our local service
  1946. // table. Next create a big add cache list to dump onto our add-cache
  1947. // queue.
  1948. //
  1949. for (i = 0; i < UserTableSize; i++) {
  1950. //
  1951. // Update Index
  1952. //
  1953. if ( 0 == UserLevel )
  1954. {
  1955. pReplUser0 = &( (PREPL_USER_RECORD_0) Users)[i];
  1956. pReplUser0->Service = Services[pReplUser0->Service].Index;
  1957. //
  1958. // Validate the user name.
  1959. //
  1960. // NB : Strange this code is necessary, but occasionally the names
  1961. // received via replication are invalid. Maintain this code
  1962. // for safety until the original problem is completely fixed.
  1963. //
  1964. if (!ValidateDN(pReplUser0->Name))
  1965. {
  1966. //
  1967. // TBD : Log event noting rejected name.
  1968. //
  1969. #if DBG
  1970. dprintf(TEXT("LS: Rejecting invalid user name = \"%s\"\n"),
  1971. pReplUser0->Name);
  1972. #endif
  1973. continue;
  1974. }
  1975. }
  1976. else
  1977. {
  1978. pReplUser1 = &( (PREPL_USER_RECORD_1) Users)[i];
  1979. pReplUser1->Service = Services[pReplUser1->Service].Index;
  1980. //
  1981. // Validate the user name.
  1982. //
  1983. // NB : Strange this code is necessary, but occasionally the names
  1984. // received via replication are invalid. Maintain this code
  1985. // for safety until the original problem is completely fixed.
  1986. //
  1987. if (!ValidateDN(pReplUser1->Name))
  1988. {
  1989. //
  1990. // TBD : Log event noting rejected name.
  1991. //
  1992. #if DBG
  1993. dprintf(TEXT("LS: Rejecting invalid user name = \"%s\"\n"),
  1994. pReplUser1->Name);
  1995. #endif
  1996. continue;
  1997. }
  1998. }
  1999. //
  2000. // Now create Add Cache object
  2001. //
  2002. tAdd = LocalAlloc(LPTR, sizeof(ADD_CACHE));
  2003. if (tAdd != NULL) {
  2004. if ( 0 == UserLevel )
  2005. {
  2006. DataLength = (lstrlen(pReplUser0->Name) + 1) * sizeof(TCHAR);
  2007. }
  2008. else
  2009. {
  2010. DataLength = (lstrlen(pReplUser1->Name) + 1) * sizeof(TCHAR);
  2011. }
  2012. NewName = LocalAlloc( LPTR, DataLength);
  2013. if (NewName == NULL) {
  2014. LocalFree(tAdd);
  2015. ASSERT(FALSE);
  2016. } else {
  2017. tAdd->Data = NewName;
  2018. tAdd->DataType = DATA_TYPE_USERNAME;
  2019. tAdd->DataLength = DataLength;
  2020. if ( 0 == UserLevel )
  2021. {
  2022. lstrcpy( NewName, pReplUser0->Name );
  2023. tAdd->AccessCount = pReplUser0->AccessCount;
  2024. tAdd->LastAccess = pReplUser0->LastAccess;
  2025. tAdd->Flags = LLS_FLAG_SUITE_AUTO;
  2026. RtlAcquireResourceShared(&MasterServiceListLock, TRUE);
  2027. tAdd->Service = MasterServiceTable[pReplUser0->Service];
  2028. RtlReleaseResource(&MasterServiceListLock);
  2029. }
  2030. else
  2031. {
  2032. lstrcpy( NewName, pReplUser1->Name );
  2033. tAdd->AccessCount = pReplUser1->AccessCount;
  2034. tAdd->LastAccess = pReplUser1->LastAccess;
  2035. tAdd->Flags = pReplUser1->Flags & ( LLS_FLAG_SUITE_USE | LLS_FLAG_SUITE_AUTO );
  2036. RtlAcquireResourceShared(&MasterServiceListLock, TRUE);
  2037. tAdd->Service = MasterServiceTable[pReplUser1->Service];
  2038. RtlReleaseResource(&MasterServiceListLock);
  2039. }
  2040. //
  2041. // Now add it to our cache
  2042. //
  2043. tAdd->prev = pAdd;
  2044. pAdd = tAdd;
  2045. //
  2046. // Keep track of first on (bottom on stack) so we can append
  2047. // it onto the real add cache.
  2048. //
  2049. if (lAdd == NULL)
  2050. lAdd = pAdd;
  2051. CacheSize++;
  2052. }
  2053. } else {
  2054. ASSERT(FALSE);
  2055. }
  2056. if (i % 100 == 0) ReportStatusToSCMgr( SERVICE_START_PENDING, NO_ERROR, NSERVICEWAITHINT);
  2057. }
  2058. //
  2059. // Now that we've walked through all the users - update the actual
  2060. // Add Cache.
  2061. //
  2062. if (pAdd != NULL) {
  2063. RtlEnterCriticalSection(&AddCacheLock);
  2064. lAdd->prev = AddCache;
  2065. AddCache = pAdd;
  2066. AddCacheSize += CacheSize;
  2067. RtlLeaveCriticalSection(&AddCacheLock);
  2068. //
  2069. // Now must signal the event so we can pull off the new record.
  2070. //
  2071. Status = NtSetEvent( LLSAddCacheEvent, NULL );
  2072. ASSERT(NT_SUCCESS(Status));
  2073. }
  2074. } // UserListUnpack
  2075. //
  2076. // Illegal user/domain characters.
  2077. //
  2078. #define CTRL_CHARS_0 TEXT( "\001\002\003\004\005\006\007")
  2079. #define CTRL_CHARS_1 TEXT("\010\011\012\013\014\015\016\017")
  2080. #define CTRL_CHARS_2 TEXT("\020\021\022\023\024\025\026\027")
  2081. #define CTRL_CHARS_3 TEXT("\030\031\032\033\034\035\036\037")
  2082. #define CTRL_CHARS_STR CTRL_CHARS_0 CTRL_CHARS_1 CTRL_CHARS_2 CTRL_CHARS_3
  2083. #define ILLEGAL_NAME_CHARS_STR TEXT("\"/\\[]:|<>+=;,?") CTRL_CHARS_STR
  2084. static const TCHAR szUserIllegalChars[] = ILLEGAL_NAME_CHARS_STR TEXT("*");
  2085. static const TCHAR szDomainIllegalChars[] = ILLEGAL_NAME_CHARS_STR TEXT("*") TEXT(" ");
  2086. /////////////////////////////////////////////////////////////////////////
  2087. BOOL
  2088. ValidateDN (
  2089. LPTSTR pszDN
  2090. )
  2091. /*++
  2092. Routine Description:
  2093. Arguments:
  2094. Return Value:
  2095. --*/
  2096. {
  2097. //
  2098. // NB : This code understands only NT4 usernames at present.
  2099. //
  2100. TCHAR szDN[MAX_USERNAME_LENGTH + MAX_DOMAINNAME_LENGTH + 2];
  2101. LPTSTR pszUserName;
  2102. LPTSTR pszDomainName;
  2103. LPTSTR pszBSlash;
  2104. SIZE_T ccUserNameLength;
  2105. SIZE_T ccDomainNameLength;
  2106. if (pszDN == NULL || !*pszDN) {
  2107. return FALSE;
  2108. }
  2109. //
  2110. // Use a local buffer for character replacement during check.
  2111. //
  2112. if (lstrlen(pszDN) < (MAX_USERNAME_LENGTH + MAX_DOMAINNAME_LENGTH + 2)) {
  2113. lstrcpyn(szDN, pszDN, MAX_USERNAME_LENGTH + MAX_DOMAINNAME_LENGTH + 2);
  2114. }
  2115. else {
  2116. return FALSE;
  2117. }
  2118. pszBSlash = STRRCHR(szDN, TEXT('\\'));
  2119. if (pszBSlash == NULL) {
  2120. return FALSE;
  2121. }
  2122. //
  2123. // Isolate user/domain names.
  2124. //
  2125. *pszBSlash = TEXT('\0');
  2126. pszUserName = pszBSlash + 1;
  2127. pszDomainName = szDN;
  2128. ccUserNameLength = lstrlen(pszUserName);
  2129. ccDomainNameLength = pszBSlash - pszDomainName;
  2130. //
  2131. // Check user/domain name length and the existence of invalid chars.
  2132. //
  2133. if (ccUserNameLength && ccUserNameLength <= MAX_USERNAME_LENGTH) {
  2134. if (STRCSPN(pszUserName, szUserIllegalChars) == ccUserNameLength) {
  2135. if (ccDomainNameLength <= MAX_DOMAINNAME_LENGTH) {
  2136. if (STRCSPN(pszDomainName,
  2137. szDomainIllegalChars) == ccDomainNameLength) {
  2138. return TRUE;
  2139. }
  2140. }
  2141. }
  2142. }
  2143. return FALSE;
  2144. }
  2145. /////////////////////////////////////////////////////////////////////////
  2146. NTSTATUS
  2147. UserListStringsPack (
  2148. ULONG UserLevel,
  2149. ULONG UserTableSize,
  2150. LPVOID Users,
  2151. ULONG *pUserStringSize,
  2152. LPTSTR *pUserStrings
  2153. )
  2154. /*++
  2155. Routine Description:
  2156. Arguments:
  2157. Return Value:
  2158. --*/
  2159. {
  2160. NTSTATUS Status = STATUS_SUCCESS;
  2161. ULONG i;
  2162. ULONG StringSize;
  2163. LPTSTR UserStrings = NULL;
  2164. TCHAR *pStr;
  2165. #if DBG
  2166. if (TraceFlags & TRACE_FUNCTION_TRACE)
  2167. dprintf(TEXT("UserListStringsPack\n"));
  2168. #endif
  2169. ASSERT(pUserStrings != NULL);
  2170. ASSERT(pUserStringSize != NULL);
  2171. *pUserStrings = NULL;
  2172. *pUserStringSize = 0;
  2173. //
  2174. // First walk the list adding up string sizes - to calculate our buff size
  2175. //
  2176. StringSize = 0;
  2177. for (i = 0; i < UserTableSize; i++) {
  2178. if ( 0 == UserLevel )
  2179. {
  2180. StringSize += 1 + lstrlen( ((PREPL_USER_RECORD_0) Users)[i].Name );
  2181. }
  2182. else
  2183. {
  2184. StringSize += 1 + lstrlen( ((PREPL_USER_RECORD_1) Users)[i].Name );
  2185. }
  2186. }
  2187. //
  2188. // Make sure there is anything to replicate
  2189. //
  2190. if (StringSize > 0) {
  2191. //
  2192. // Create our buffer to hold all of the garbage
  2193. //
  2194. UserStrings = MIDL_user_allocate(StringSize * sizeof(TCHAR));
  2195. if (UserStrings == NULL) {
  2196. ASSERT(FALSE);
  2197. return STATUS_NO_MEMORY;
  2198. }
  2199. //
  2200. // Fill in the buffer
  2201. //
  2202. pStr = UserStrings;
  2203. for (i = 0; i < UserTableSize; i++) {
  2204. if ( 0 == UserLevel )
  2205. {
  2206. lstrcpy( pStr, ((PREPL_USER_RECORD_0) Users)[i].Name );
  2207. }
  2208. else
  2209. {
  2210. lstrcpy( pStr, ((PREPL_USER_RECORD_1) Users)[i].Name );
  2211. }
  2212. pStr += 1 + lstrlen( pStr );
  2213. }
  2214. }
  2215. *pUserStrings = UserStrings;
  2216. *pUserStringSize = StringSize;
  2217. return Status;
  2218. } // UserListStringsPack
  2219. /////////////////////////////////////////////////////////////////////////
  2220. VOID
  2221. UserListStringsUnpack (
  2222. ULONG UserLevel,
  2223. ULONG UserTableSize,
  2224. LPVOID Users,
  2225. ULONG UserStringSize,
  2226. LPTSTR UserStrings
  2227. )
  2228. /*++
  2229. Routine Description:
  2230. Arguments:
  2231. Return Value:
  2232. --*/
  2233. {
  2234. ULONG i;
  2235. TCHAR *pStr;
  2236. #if DBG
  2237. if (TraceFlags & TRACE_FUNCTION_TRACE)
  2238. dprintf(TEXT("UserListStringsUnpack\n"));
  2239. #endif
  2240. pStr = UserStrings;
  2241. for (i = 0; i < UserTableSize; i++) {
  2242. if ( 0 == UserLevel )
  2243. {
  2244. ((PREPL_USER_RECORD_0) Users)[i].Name = pStr;
  2245. }
  2246. else
  2247. {
  2248. ((PREPL_USER_RECORD_1) Users)[i].Name = pStr;
  2249. }
  2250. //
  2251. // Move to end of current string
  2252. //
  2253. while (*pStr != TEXT('\0'))
  2254. pStr++;
  2255. // now go past ending NULL
  2256. pStr++;
  2257. }
  2258. } // UserListStringsUnpack
  2259. /////////////////////////////////////////////////////////////////////////
  2260. // Service List
  2261. //
  2262. /////////////////////////////////////////////////////////////////////////
  2263. NTSTATUS
  2264. ServiceListPack (
  2265. ULONG *pServiceTableSize,
  2266. PREPL_SERVICE_RECORD *pServices
  2267. )
  2268. /*++
  2269. Routine Description:
  2270. Arguments:
  2271. Return Value:
  2272. --*/
  2273. {
  2274. NTSTATUS Status = STATUS_SUCCESS;
  2275. PREPL_SERVICE_RECORD Services = NULL;
  2276. ULONG i;
  2277. ULONG TotalRecords = 0;
  2278. PMASTER_SERVICE_RECORD pService;
  2279. #if DBG
  2280. if (TraceFlags & TRACE_FUNCTION_TRACE)
  2281. dprintf(TEXT("LLS TRACE: ServiceListPack\n"));
  2282. #endif
  2283. ASSERT(pServices != NULL);
  2284. ASSERT(pServiceTableSize != NULL);
  2285. *pServices = NULL;
  2286. *pServiceTableSize = 0;
  2287. TotalRecords = MasterServiceListSize;
  2288. //
  2289. // Make sure there is anything to replicate
  2290. //
  2291. if (TotalRecords > 0) {
  2292. //
  2293. // Create our buffer to hold all of the garbage
  2294. //
  2295. Services = MIDL_user_allocate(TotalRecords * sizeof(REPL_SERVICE_RECORD));
  2296. if (Services == NULL) {
  2297. ASSERT(FALSE);
  2298. return STATUS_NO_MEMORY;
  2299. }
  2300. //
  2301. // Fill in the buffer - walk the user tree
  2302. //
  2303. for (i = 0; i < MasterServiceListSize; i++) {
  2304. pService = MasterServiceTable[i];
  2305. Services[i].Name = pService->Name;
  2306. Services[i].FamilyName = pService->Family->Name;
  2307. Services[i].Version = pService->Version;
  2308. Services[i].Index = pService->Index;
  2309. }
  2310. }
  2311. #if DBG
  2312. if (TraceFlags & TRACE_REPLICATION)
  2313. dprintf(TEXT("ServiceListPack: [%lu]\n"), TotalRecords);
  2314. #endif
  2315. *pServices = Services;
  2316. *pServiceTableSize = TotalRecords;
  2317. return Status;
  2318. } // ServiceListPack
  2319. /////////////////////////////////////////////////////////////////////////
  2320. VOID
  2321. ServiceListUnpack (
  2322. ULONG ServiceTableSize,
  2323. PREPL_SERVICE_RECORD Services,
  2324. ULONG ServerTableSize,
  2325. PREPL_SERVER_RECORD Servers,
  2326. ULONG ServerServiceTableSize,
  2327. PREPL_SERVER_SERVICE_RECORD ServerServices
  2328. )
  2329. /*++
  2330. Routine Description:
  2331. Arguments:
  2332. Return Value:
  2333. --*/
  2334. {
  2335. ULONG i, j;
  2336. PMASTER_SERVICE_RECORD pService;
  2337. PREPL_SERVICE_RECORD pSvc;
  2338. #if DBG
  2339. if (TraceFlags & (TRACE_REPLICATION | TRACE_FUNCTION_TRACE))
  2340. dprintf(TEXT("ServiceListUnpack: [%lu]\n"), ServiceTableSize);
  2341. #endif
  2342. //
  2343. // Walk services table, adding any new services to our local table.
  2344. // Fix up the index pointers to match our local services.
  2345. //
  2346. RtlAcquireResourceExclusive(&MasterServiceListLock, TRUE);
  2347. for (i = 0; i < ServiceTableSize; i++) {
  2348. pSvc = &Services[i];
  2349. pService = MasterServiceListAdd(pSvc->FamilyName, pSvc->Name, pSvc->Version );
  2350. if (pService != NULL) {
  2351. pSvc->Index = pService->Index;
  2352. //
  2353. // In case this got added from the local service list table and we
  2354. // didn't have a version # yet.
  2355. //
  2356. if ( (pService->Version == 0) && (pSvc->Version != 0) ) {
  2357. PMASTER_SERVICE_ROOT ServiceRoot = NULL;
  2358. //
  2359. // Fixup next pointer chain
  2360. //
  2361. ServiceRoot = pService->Family;
  2362. j = 0;
  2363. while ((j < ServiceRoot->ServiceTableSize) && (MasterServiceTable[ServiceRoot->Services[j]]->Version < pSvc->Version))
  2364. j++;
  2365. pService->next = 0;
  2366. pService->Version = pSvc->Version;
  2367. if (j > 0) {
  2368. if (MasterServiceTable[ServiceRoot->Services[j - 1]]->next == pService->Index + 1)
  2369. pService->next = 0;
  2370. else
  2371. pService->next = MasterServiceTable[ServiceRoot->Services[j - 1]]->next;
  2372. if (MasterServiceTable[ServiceRoot->Services[j - 1]] != pService)
  2373. MasterServiceTable[ServiceRoot->Services[j - 1]]->next = pService->Index + 1;
  2374. }
  2375. // Resort it in order of the versions
  2376. qsort((void *) ServiceRoot->Services, (size_t) ServiceRoot->ServiceTableSize, sizeof(ULONG), MServiceRecordCompare);
  2377. }
  2378. } else {
  2379. ASSERT(FALSE);
  2380. pSvc->Index = 0;
  2381. }
  2382. if (i % 100 == 0) ReportStatusToSCMgr( SERVICE_START_PENDING, NO_ERROR, NSERVICEWAITHINT);
  2383. }
  2384. RtlReleaseResource(&MasterServiceListLock);
  2385. } // ServiceListUnpack
  2386. /////////////////////////////////////////////////////////////////////////
  2387. NTSTATUS
  2388. ServiceListStringsPack (
  2389. ULONG ServiceTableSize,
  2390. PREPL_SERVICE_RECORD Services,
  2391. ULONG *pServiceStringSize,
  2392. LPTSTR *pServiceStrings
  2393. )
  2394. /*++
  2395. Routine Description:
  2396. Arguments:
  2397. Return Value:
  2398. --*/
  2399. {
  2400. NTSTATUS Status = STATUS_SUCCESS;
  2401. ULONG i;
  2402. ULONG StringSize;
  2403. PREPL_SERVICE_RECORD pService;
  2404. LPTSTR ServiceStrings = NULL;
  2405. TCHAR *pStr;
  2406. #if DBG
  2407. if (TraceFlags & TRACE_FUNCTION_TRACE)
  2408. dprintf(TEXT("ServiceListStringsPack\n"));
  2409. #endif
  2410. ASSERT(pServiceStrings != NULL);
  2411. ASSERT(pServiceStringSize != NULL);
  2412. *pServiceStrings = NULL;
  2413. *pServiceStringSize = 0;
  2414. //
  2415. // First walk the list adding up string sizes - to calculate our buff size
  2416. //
  2417. StringSize = 0;
  2418. for (i = 0; i < ServiceTableSize; i++) {
  2419. pService = &Services[i];
  2420. StringSize = StringSize + lstrlen(pService->Name) + 1;
  2421. StringSize = StringSize + lstrlen(pService->FamilyName) + 1;
  2422. }
  2423. //
  2424. // Make sure there is anything to replicate
  2425. //
  2426. if (StringSize > 0) {
  2427. //
  2428. // Create our buffer to hold all of the garbage
  2429. //
  2430. ServiceStrings = MIDL_user_allocate(StringSize * sizeof(TCHAR));
  2431. if (ServiceStrings == NULL) {
  2432. ASSERT(FALSE);
  2433. return STATUS_NO_MEMORY;
  2434. }
  2435. //
  2436. // Fill in the buffer
  2437. //
  2438. pStr = ServiceStrings;
  2439. for (i = 0; i < ServiceTableSize; i++) {
  2440. pService = &Services[i];
  2441. lstrcpy(pStr, pService->Name);
  2442. pStr = &pStr[lstrlen(pService->Name) + 1];
  2443. lstrcpy(pStr, pService->FamilyName);
  2444. pStr = &pStr[lstrlen(pService->FamilyName) + 1];
  2445. }
  2446. }
  2447. *pServiceStrings = ServiceStrings;
  2448. *pServiceStringSize = StringSize;
  2449. return Status;
  2450. } // ServiceListStringsPack
  2451. /////////////////////////////////////////////////////////////////////////
  2452. VOID
  2453. ServiceListStringsUnpack (
  2454. ULONG ServiceTableSize,
  2455. PREPL_SERVICE_RECORD Services,
  2456. ULONG ServiceStringSize,
  2457. LPTSTR ServiceStrings
  2458. )
  2459. /*++
  2460. Routine Description:
  2461. Arguments:
  2462. Return Value:
  2463. --*/
  2464. {
  2465. ULONG i;
  2466. PREPL_SERVICE_RECORD pService;
  2467. TCHAR *pStr;
  2468. #if DBG
  2469. if (TraceFlags & TRACE_FUNCTION_TRACE)
  2470. dprintf(TEXT("ServiceListStringsUnpack\n"));
  2471. #endif
  2472. pStr = ServiceStrings;
  2473. for (i = 0; i < ServiceTableSize; i++) {
  2474. pService = &Services[i];
  2475. pService->Name = pStr;
  2476. //
  2477. // Move to end of current string
  2478. //
  2479. while (*pStr != TEXT('\0'))
  2480. pStr++;
  2481. // now go past ending NULL
  2482. pStr++;
  2483. pService->FamilyName = pStr;
  2484. //
  2485. // Move to end of current string
  2486. //
  2487. while (*pStr != TEXT('\0'))
  2488. pStr++;
  2489. // now go past ending NULL
  2490. pStr++;
  2491. }
  2492. } // ServiceListStringsUnpack
  2493. /////////////////////////////////////////////////////////////////////////
  2494. // Server List
  2495. //
  2496. /////////////////////////////////////////////////////////////////////////
  2497. NTSTATUS
  2498. ServerListPack (
  2499. ULONG *pServerTableSize,
  2500. PREPL_SERVER_RECORD *pServers
  2501. )
  2502. /*++
  2503. Routine Description:
  2504. Arguments:
  2505. Return Value:
  2506. --*/
  2507. {
  2508. NTSTATUS Status = STATUS_SUCCESS;
  2509. PREPL_SERVER_RECORD Servers = NULL;
  2510. ULONG i;
  2511. ULONG TotalRecords = 0;
  2512. PSERVER_RECORD pServer;
  2513. #if DBG
  2514. if (TraceFlags & TRACE_FUNCTION_TRACE)
  2515. dprintf(TEXT("LLS TRACE: ServerListPack\n"));
  2516. #endif
  2517. ASSERT(pServers != NULL);
  2518. ASSERT(pServerTableSize != NULL);
  2519. *pServers = NULL;
  2520. *pServerTableSize = 0;
  2521. TotalRecords = ServerListSize;
  2522. //
  2523. // Make sure there is anything to replicate
  2524. //
  2525. if (TotalRecords > 0) {
  2526. //
  2527. // Create our buffer to hold all of the garbage
  2528. //
  2529. Servers = MIDL_user_allocate(TotalRecords * sizeof(REPL_SERVER_RECORD));
  2530. if (Servers == NULL) {
  2531. ASSERT(FALSE);
  2532. return STATUS_NO_MEMORY;
  2533. }
  2534. //
  2535. // Fill in the buffer - walk the user tree
  2536. //
  2537. for (i = 0; i < ServerListSize; i++) {
  2538. pServer = ServerTable[i];
  2539. Servers[i].Name = pServer->Name;
  2540. Servers[i].MasterServer = pServer->MasterServer;
  2541. Servers[i].Index = pServer->Index;
  2542. }
  2543. }
  2544. #if DBG
  2545. if (TraceFlags & TRACE_REPLICATION)
  2546. dprintf(TEXT("ServerListPack: [%lu]\n"), TotalRecords);
  2547. #endif
  2548. *pServers = Servers;;
  2549. *pServerTableSize = TotalRecords;
  2550. return Status;
  2551. } // ServerListPack
  2552. /////////////////////////////////////////////////////////////////////////
  2553. VOID
  2554. ServerListUnpack (
  2555. ULONG ServiceTableSize,
  2556. PREPL_SERVICE_RECORD Services,
  2557. ULONG ServerTableSize,
  2558. PREPL_SERVER_RECORD Servers,
  2559. ULONG ServerServiceTableSize,
  2560. PREPL_SERVER_SERVICE_RECORD ServerServices
  2561. )
  2562. /*++
  2563. Routine Description:
  2564. Arguments:
  2565. Return Value:
  2566. --*/
  2567. {
  2568. ULONG i;
  2569. PSERVER_RECORD pServer;
  2570. PREPL_SERVER_RECORD pSrv;
  2571. TCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  2572. #if DBG
  2573. if (TraceFlags & (TRACE_REPLICATION | TRACE_FUNCTION_TRACE))
  2574. dprintf(TEXT("ServerListUnpack: [%lu]\n"), ServerTableSize);
  2575. #endif
  2576. ComputerName[0] = 0;
  2577. //
  2578. // Walk server table, adding any new servers to our local table.
  2579. // Fix up the index pointers to match our local table and re-fix
  2580. // Service table pointers.
  2581. //
  2582. RtlEnterCriticalSection(&ConfigInfoLock);
  2583. if (ConfigInfo.ComputerName != NULL)
  2584. lstrcpy(ComputerName, ConfigInfo.ComputerName);
  2585. RtlLeaveCriticalSection(&ConfigInfoLock);
  2586. RtlAcquireResourceExclusive(&ServerListLock, TRUE);
  2587. for (i = 0; i < ServerTableSize; i++) {
  2588. pSrv = &Servers[i];
  2589. if (pSrv->MasterServer != 0)
  2590. pServer = ServerListAdd(pSrv->Name, Servers[pSrv->MasterServer - 1].Name);
  2591. else
  2592. pServer = ServerListAdd(pSrv->Name, ComputerName);
  2593. if (pServer != NULL)
  2594. pSrv->Index = pServer->Index;
  2595. else {
  2596. ASSERT(FALSE);
  2597. pSrv->Index = 0;
  2598. }
  2599. if (i % 100 == 0) ReportStatusToSCMgr( SERVICE_START_PENDING, NO_ERROR, NSERVICEWAITHINT);
  2600. }
  2601. RtlReleaseResource(&ServerListLock);
  2602. } // ServerListUnpack
  2603. /////////////////////////////////////////////////////////////////////////
  2604. NTSTATUS
  2605. ServerServiceListPack (
  2606. ULONG *pServerServiceTableSize,
  2607. PREPL_SERVER_SERVICE_RECORD *pServerServices
  2608. )
  2609. /*++
  2610. Routine Description:
  2611. Arguments:
  2612. Return Value:
  2613. --*/
  2614. {
  2615. NTSTATUS Status = STATUS_SUCCESS;
  2616. PREPL_SERVER_SERVICE_RECORD ServerServices = NULL;
  2617. ULONG i, j, k;
  2618. ULONG TotalRecords = 0;
  2619. PSERVER_RECORD pServer;
  2620. PSERVER_SERVICE_RECORD pServerService;
  2621. #if DBG
  2622. if (TraceFlags & TRACE_FUNCTION_TRACE)
  2623. dprintf(TEXT("LLS TRACE: ServerServiceListPack\n"));
  2624. #endif
  2625. ASSERT(pServerServices != NULL);
  2626. ASSERT(pServerServiceTableSize != NULL);
  2627. *pServerServices = NULL;
  2628. *pServerServiceTableSize = 0;
  2629. //
  2630. // Walk the ServerList and find all ServiceRecords
  2631. for (i = 0; i < ServerListSize; i++)
  2632. TotalRecords += ServerTable[i]->ServiceTableSize;
  2633. //
  2634. // Make sure there is anything to replicate
  2635. //
  2636. if (TotalRecords > 0) {
  2637. //
  2638. // Create our buffer to hold all of the garbage
  2639. //
  2640. ServerServices = MIDL_user_allocate(TotalRecords * sizeof(REPL_SERVER_SERVICE_RECORD));
  2641. if (ServerServices == NULL) {
  2642. ASSERT(FALSE);
  2643. return STATUS_NO_MEMORY;
  2644. }
  2645. //
  2646. // Fill in the buffer - walk the user tree
  2647. //
  2648. k = 0;
  2649. for (i = 0; i < ServerListSize; i++) {
  2650. pServer = ServerTable[i];
  2651. for (j = 0; j < pServer->ServiceTableSize; j++) {
  2652. ServerServices[k].Server = pServer->Index;
  2653. ServerServices[k].Service = pServer->Services[j]->Service;
  2654. ServerServices[k].MaxSessionCount = pServer->Services[j]->MaxSessionCount;
  2655. ServerServices[k].MaxSetSessionCount = pServer->Services[j]->MaxSetSessionCount;
  2656. ServerServices[k].HighMark = pServer->Services[j]->HighMark;
  2657. k++;
  2658. }
  2659. }
  2660. }
  2661. #if DBG
  2662. if (TraceFlags & TRACE_REPLICATION)
  2663. dprintf(TEXT("ServerServiceListPack: [%lu]\n"), TotalRecords);
  2664. #endif
  2665. *pServerServices = ServerServices;
  2666. *pServerServiceTableSize = TotalRecords;
  2667. return Status;
  2668. } // ServerServiceListPack
  2669. /////////////////////////////////////////////////////////////////////////
  2670. VOID
  2671. ServerServiceListUnpack (
  2672. ULONG ServiceTableSize,
  2673. PREPL_SERVICE_RECORD Services,
  2674. ULONG ServerTableSize,
  2675. PREPL_SERVER_RECORD Servers,
  2676. ULONG ServerServiceTableSize,
  2677. PREPL_SERVER_SERVICE_RECORD ServerServices
  2678. )
  2679. /*++
  2680. Routine Description:
  2681. Arguments:
  2682. Return Value:
  2683. --*/
  2684. {
  2685. ULONG i;
  2686. PSERVER_RECORD pServer;
  2687. PREPL_SERVER_SERVICE_RECORD pSrv;
  2688. PSERVER_SERVICE_RECORD pService;
  2689. PMASTER_SERVICE_RECORD pMasterService;
  2690. #if DBG
  2691. if (TraceFlags & (TRACE_REPLICATION | TRACE_FUNCTION_TRACE))
  2692. dprintf(TEXT("ServerServiceListUnpack: [%lu]\n"), ServerServiceTableSize);
  2693. #endif
  2694. //
  2695. // Walk server table, adding any new servers to our local table.
  2696. // Fix up the index pointers to match our local table and re-fix
  2697. // Service table pointers.
  2698. //
  2699. RtlAcquireResourceExclusive(&ServerListLock, TRUE);
  2700. RtlAcquireResourceShared(&MasterServiceListLock, TRUE);
  2701. for (i = 0; i < ServerServiceTableSize; i++) {
  2702. pSrv = &ServerServices[i];
  2703. pServer = ServerListFind(Servers[pSrv->Server - 1].Name);
  2704. ASSERT(pServer != NULL);
  2705. if (pServer != NULL) {
  2706. BOOL bReplaceValues;
  2707. pService = ServerServiceListFind(Services[pSrv->Service].Name, pServer->ServiceTableSize, pServer->Services);
  2708. bReplaceValues = ( NULL != pService );
  2709. pService = ServerServiceListAdd(Services[pSrv->Service].Name,
  2710. Services[pSrv->Service].Index,
  2711. &pServer->ServiceTableSize,
  2712. &pServer->Services);
  2713. ASSERT(pService != NULL);
  2714. if (pService != NULL)
  2715. {
  2716. //
  2717. // Remove any old info
  2718. //
  2719. pMasterService = MasterServiceTable[Services[pSrv->Service].Index];
  2720. if ( bReplaceValues )
  2721. {
  2722. pMasterService->MaxSessionCount -= pService->MaxSessionCount;
  2723. pMasterService->HighMark -= pService->HighMark;
  2724. }
  2725. //
  2726. // Now update new info
  2727. //
  2728. pService->MaxSessionCount = pSrv->MaxSessionCount;
  2729. pService->HighMark = pSrv->HighMark;
  2730. pMasterService->MaxSessionCount += pService->MaxSessionCount;
  2731. pMasterService->HighMark += pService->HighMark;
  2732. }
  2733. }
  2734. if (i % 100 == 0) ReportStatusToSCMgr( SERVICE_START_PENDING, NO_ERROR, NSERVICEWAITHINT);
  2735. }
  2736. RtlReleaseResource(&MasterServiceListLock);
  2737. RtlReleaseResource(&ServerListLock);
  2738. } // ServerServiceListUnpack
  2739. /////////////////////////////////////////////////////////////////////////
  2740. NTSTATUS
  2741. ServerListStringsPack (
  2742. ULONG ServerTableSize,
  2743. PREPL_SERVER_RECORD Servers,
  2744. ULONG *pServerStringSize,
  2745. LPTSTR *pServerStrings
  2746. )
  2747. /*++
  2748. Routine Description:
  2749. Arguments:
  2750. Return Value:
  2751. --*/
  2752. {
  2753. NTSTATUS Status = STATUS_SUCCESS;
  2754. ULONG i;
  2755. ULONG StringSize;
  2756. PREPL_SERVER_RECORD pServer;
  2757. LPTSTR ServerStrings = NULL;
  2758. TCHAR *pStr;
  2759. #if DBG
  2760. if (TraceFlags & TRACE_FUNCTION_TRACE)
  2761. dprintf(TEXT("ServerListStringsPack\n"));
  2762. #endif
  2763. ASSERT(pServerStrings != NULL);
  2764. ASSERT(pServerStringSize != NULL);
  2765. *pServerStrings = NULL;
  2766. *pServerStringSize = 0;
  2767. //
  2768. // First walk the list adding up string sizes - to calculate our buff size
  2769. //
  2770. StringSize = 0;
  2771. for (i = 0; i < ServerTableSize; i++) {
  2772. pServer = &Servers[i];
  2773. StringSize = StringSize + lstrlen(pServer->Name) + 1;
  2774. }
  2775. //
  2776. // Make sure there is anything to replicate
  2777. //
  2778. if (StringSize > 0) {
  2779. //
  2780. // Create our buffer to hold all of the garbage
  2781. //
  2782. ServerStrings = MIDL_user_allocate(StringSize * sizeof(TCHAR));
  2783. if (ServerStrings == NULL) {
  2784. ASSERT(FALSE);
  2785. return STATUS_NO_MEMORY;
  2786. }
  2787. //
  2788. // Fill in the buffer
  2789. //
  2790. pStr = ServerStrings;
  2791. for (i = 0; i < ServerTableSize; i++) {
  2792. pServer = &Servers[i];
  2793. lstrcpy(pStr, pServer->Name);
  2794. pStr = &pStr[lstrlen(pServer->Name) + 1];
  2795. }
  2796. }
  2797. *pServerStrings = ServerStrings;
  2798. *pServerStringSize = StringSize;
  2799. return Status;
  2800. } // ServerListStringsPack
  2801. /////////////////////////////////////////////////////////////////////////
  2802. VOID
  2803. ServerListStringsUnpack (
  2804. ULONG ServerTableSize,
  2805. PREPL_SERVER_RECORD Servers,
  2806. ULONG ServerStringSize,
  2807. LPTSTR ServerStrings
  2808. )
  2809. /*++
  2810. Routine Description:
  2811. Arguments:
  2812. Return Value:
  2813. --*/
  2814. {
  2815. ULONG i;
  2816. PREPL_SERVER_RECORD pServer;
  2817. TCHAR *pStr;
  2818. #if DBG
  2819. if (TraceFlags & TRACE_FUNCTION_TRACE)
  2820. dprintf(TEXT("ServerListStringsUnpack\n"));
  2821. #endif
  2822. //
  2823. // First do license service strings
  2824. //
  2825. pStr = ServerStrings;
  2826. for (i = 0; i < ServerTableSize; i++) {
  2827. pServer = &Servers[i];
  2828. pServer->Name = pStr;
  2829. //
  2830. // Move to end of current string
  2831. //
  2832. while (*pStr != TEXT('\0'))
  2833. pStr++;
  2834. // now go past ending NULL
  2835. pStr++;
  2836. }
  2837. } // ServerListStringsUnpack
  2838. /////////////////////////////////////////////////////////////////////////
  2839. /////////////////////////////////////////////////////////////////////////
  2840. /////////////////////////////////////////////////////////////////////////
  2841. NTSTATUS
  2842. PackAll (
  2843. DWORD LastReplicated,
  2844. ULONG *pServiceTableSize,
  2845. PREPL_SERVICE_RECORD *pServices,
  2846. ULONG *pServerTableSize,
  2847. PREPL_SERVER_RECORD *pServers,
  2848. ULONG *pServerServiceTableSize,
  2849. PREPL_SERVER_SERVICE_RECORD *pServerServices,
  2850. ULONG UserLevel,
  2851. ULONG *pUserTableSize,
  2852. LPVOID *pUsers
  2853. )
  2854. /*++
  2855. Routine Description:
  2856. Arguments:
  2857. Return Value:
  2858. --*/
  2859. {
  2860. NTSTATUS Status = STATUS_SUCCESS;
  2861. #if DBG
  2862. if (TraceFlags & TRACE_FUNCTION_TRACE)
  2863. dprintf(TEXT("LLS TRACE: PackAll\n"));
  2864. #endif
  2865. //
  2866. // We need to grab all the locks here so that a service isn't snuck in
  2867. // behind our backs - since these tables interact with each other.
  2868. //
  2869. RtlAcquireResourceExclusive(&UserListLock, TRUE);
  2870. RtlAcquireResourceShared(&MasterServiceListLock, TRUE);
  2871. RtlAcquireResourceShared(&ServerListLock, TRUE);
  2872. Status = ServiceListPack(pServiceTableSize, pServices);
  2873. if (Status != STATUS_SUCCESS)
  2874. goto PackAllExit;
  2875. Status = ServerListPack(pServerTableSize, pServers);
  2876. if (Status != STATUS_SUCCESS)
  2877. goto PackAllExit;
  2878. Status = ServerServiceListPack(pServerServiceTableSize, pServerServices);
  2879. if (Status != STATUS_SUCCESS)
  2880. goto PackAllExit;
  2881. Status = UserListPack(LastReplicated, UserLevel, pUserTableSize, pUsers);
  2882. if (Status != STATUS_SUCCESS)
  2883. goto PackAllExit;
  2884. //
  2885. // Now update our last used time
  2886. //
  2887. LastUsedTime = DateSystemGet() + 1;
  2888. PackAllExit:
  2889. RtlReleaseResource(&ServerListLock);
  2890. RtlReleaseResource(&MasterServiceListLock);
  2891. RtlReleaseResource(&UserListLock);
  2892. return Status;
  2893. } // PackAll
  2894. /////////////////////////////////////////////////////////////////////////
  2895. VOID
  2896. UnpackAll (
  2897. ULONG ServiceTableSize,
  2898. PREPL_SERVICE_RECORD Services,
  2899. ULONG ServerTableSize,
  2900. PREPL_SERVER_RECORD Servers,
  2901. ULONG ServerServiceTableSize,
  2902. PREPL_SERVER_SERVICE_RECORD ServerServices,
  2903. ULONG UserLevel,
  2904. ULONG UserTableSize,
  2905. LPVOID Users
  2906. )
  2907. /*++
  2908. Routine Description:
  2909. Arguments:
  2910. Return Value:
  2911. --*/
  2912. {
  2913. #if DBG
  2914. if (TraceFlags & TRACE_FUNCTION_TRACE)
  2915. dprintf(TEXT("LLS TRACE: UnpackAll\n"));
  2916. #endif
  2917. ServiceListUnpack(ServiceTableSize, Services, ServerTableSize, Servers, ServerServiceTableSize, ServerServices);
  2918. ServerListUnpack(ServiceTableSize, Services, ServerTableSize, Servers, ServerServiceTableSize, ServerServices);
  2919. ServerServiceListUnpack(ServiceTableSize, Services, ServerTableSize, Servers, ServerServiceTableSize, ServerServices);
  2920. UserListUnpack(ServiceTableSize, Services, ServerTableSize, Servers, ServerServiceTableSize, ServerServices, UserLevel, UserTableSize, Users);
  2921. } // UnpackAll
  2922. /////////////////////////////////////////////////////////////////////////
  2923. VOID
  2924. LLSDataLoad()
  2925. /*++
  2926. Routine Description:
  2927. Arguments:
  2928. None.
  2929. Return Value:
  2930. None.
  2931. --*/
  2932. {
  2933. BOOL ret;
  2934. DWORD Version, DataSize;
  2935. NTSTATUS Status = STATUS_SUCCESS;
  2936. HANDLE hFile = NULL;
  2937. ULONG ServiceTableSize = 0;
  2938. PREPL_SERVICE_RECORD Services = NULL;
  2939. ULONG ServiceStringSize;
  2940. LPTSTR ServiceStrings = NULL;
  2941. ULONG ServerServiceTableSize = 0;
  2942. PREPL_SERVER_SERVICE_RECORD ServerServices = NULL;
  2943. ULONG ServerTableSize = 0;
  2944. PREPL_SERVER_RECORD Servers = NULL;
  2945. ULONG ServerStringSize;
  2946. LPTSTR ServerStrings = NULL;
  2947. ULONG UserTableSize = 0;
  2948. LPVOID Users = NULL;
  2949. ULONG UserStringSize;
  2950. LPTSTR UserStrings = NULL;
  2951. LLS_DATA_FILE_HEADER FileHeader;
  2952. DWORD BytesRead;
  2953. #if DBG
  2954. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_DATABASE))
  2955. dprintf(TEXT("LLS TRACE: LLSDataLoad\n"));
  2956. #endif
  2957. //
  2958. // If nothing to load then get-out
  2959. //
  2960. if (!FileExists(UserFileName))
  2961. goto LLSDataLoadExit;
  2962. //
  2963. // Check the init header
  2964. //
  2965. Version = DataSize = 0;
  2966. hFile = LlsFileCheck(UserFileName, &Version, &DataSize );
  2967. if (hFile == NULL) {
  2968. Status = GetLastError();
  2969. goto LLSDataLoadExit;
  2970. }
  2971. if ( ( ( Version != USER_FILE_VERSION_0 )
  2972. || ( DataSize != sizeof(LLS_DATA_FILE_HEADER_0) ) )
  2973. && ( ( Version != USER_FILE_VERSION )
  2974. || ( DataSize != sizeof(LLS_DATA_FILE_HEADER) ) ) )
  2975. {
  2976. Status = STATUS_FILE_INVALID;
  2977. goto LLSDataLoadExit;
  2978. }
  2979. //
  2980. // The init header checks out, so load the license header and data blocks
  2981. //
  2982. if ( USER_FILE_VERSION_0 == Version )
  2983. {
  2984. // 3.51 data file
  2985. LLS_DATA_FILE_HEADER_0 FileHeader0;
  2986. ret = ReadFile(hFile, &FileHeader0, sizeof(LLS_DATA_FILE_HEADER_0), &BytesRead, NULL);
  2987. if ( ret )
  2988. {
  2989. FileHeader.ServiceLevel = 0;
  2990. FileHeader.ServiceTableSize = FileHeader0.ServiceTableSize;
  2991. FileHeader.ServiceStringSize = FileHeader0.ServiceStringSize;
  2992. FileHeader.ServerLevel = 0;
  2993. FileHeader.ServerTableSize = FileHeader0.ServerTableSize;
  2994. FileHeader.ServerStringSize = FileHeader0.ServerStringSize;
  2995. FileHeader.ServerServiceLevel = 0;
  2996. FileHeader.ServerServiceTableSize = FileHeader0.ServerServiceTableSize;
  2997. FileHeader.UserLevel = 0;
  2998. FileHeader.UserTableSize = FileHeader0.UserTableSize;
  2999. FileHeader.UserStringSize = FileHeader0.UserStringSize;
  3000. }
  3001. }
  3002. else
  3003. {
  3004. ret = ReadFile(hFile, &FileHeader, sizeof(LLS_DATA_FILE_HEADER), &BytesRead, NULL);
  3005. }
  3006. if ( ret )
  3007. {
  3008. // header read okay; ensure data type levels are okay
  3009. if ( ( 0 != FileHeader.ServiceLevel )
  3010. || ( 0 != FileHeader.ServerLevel )
  3011. || ( 0 != FileHeader.ServerServiceLevel )
  3012. || ( ( 0 != FileHeader.UserLevel )
  3013. && ( 1 != FileHeader.UserLevel ) ) )
  3014. {
  3015. Status = STATUS_FILE_INVALID;
  3016. goto LLSDataLoadExit;
  3017. }
  3018. }
  3019. ServiceTableSize = 0;
  3020. ServiceStringSize = 0;
  3021. ServerServiceTableSize = 0;
  3022. ServerTableSize = 0;
  3023. ServerStringSize = 0;
  3024. UserTableSize = 0;
  3025. UserStringSize = 0;
  3026. if (ret) {
  3027. //
  3028. // Run through and allocate space to read data blocks into
  3029. //
  3030. if (FileHeader.ServiceTableSize != 0) {
  3031. ServiceTableSize = FileHeader.ServiceTableSize / sizeof(REPL_SERVICE_RECORD);
  3032. Services = MIDL_user_allocate(FileHeader.ServiceTableSize);
  3033. if ( Services == NULL ) {
  3034. Status = STATUS_NO_MEMORY;
  3035. goto LLSDataLoadExit;
  3036. }
  3037. }
  3038. if (FileHeader.ServiceStringSize != 0) {
  3039. ServiceStringSize = FileHeader.ServiceStringSize / sizeof(TCHAR);
  3040. ServiceStrings = MIDL_user_allocate(FileHeader.ServiceStringSize);
  3041. if ( ServiceStrings == NULL ) {
  3042. Status = STATUS_NO_MEMORY;
  3043. goto LLSDataLoadExit;
  3044. }
  3045. }
  3046. if (FileHeader.ServerTableSize != 0) {
  3047. ServerTableSize = FileHeader.ServerTableSize / sizeof(REPL_SERVER_RECORD);
  3048. Servers = MIDL_user_allocate(FileHeader.ServerTableSize);
  3049. if ( Servers == NULL ) {
  3050. Status = STATUS_NO_MEMORY;
  3051. goto LLSDataLoadExit;
  3052. }
  3053. }
  3054. if (FileHeader.ServerStringSize != 0) {
  3055. ServerStringSize = FileHeader.ServerStringSize / sizeof(TCHAR);
  3056. ServerStrings = MIDL_user_allocate(FileHeader.ServerStringSize);
  3057. if ( ServerStrings == NULL ) {
  3058. Status = STATUS_NO_MEMORY;
  3059. goto LLSDataLoadExit;
  3060. }
  3061. }
  3062. if (FileHeader.ServerServiceTableSize != 0) {
  3063. ServerServiceTableSize = FileHeader.ServerServiceTableSize / sizeof(REPL_SERVER_SERVICE_RECORD);
  3064. ServerServices = MIDL_user_allocate(FileHeader.ServerServiceTableSize);
  3065. if ( ServerServices == NULL ) {
  3066. Status = STATUS_NO_MEMORY;
  3067. goto LLSDataLoadExit;
  3068. }
  3069. }
  3070. if (FileHeader.UserTableSize != 0) {
  3071. UserTableSize = FileHeader.UserTableSize / ( FileHeader.UserLevel ? sizeof(REPL_USER_RECORD_1)
  3072. : sizeof(REPL_USER_RECORD_0) );
  3073. Users = MIDL_user_allocate(FileHeader.UserTableSize);
  3074. if ( Users == NULL ) {
  3075. Status = STATUS_NO_MEMORY;
  3076. goto LLSDataLoadExit;
  3077. }
  3078. }
  3079. if (FileHeader.UserStringSize != 0) {
  3080. UserStringSize = FileHeader.UserStringSize / sizeof(TCHAR);
  3081. UserStrings = MIDL_user_allocate(FileHeader.UserStringSize);
  3082. if ( UserStrings == NULL ) {
  3083. Status = STATUS_NO_MEMORY;
  3084. goto LLSDataLoadExit;
  3085. }
  3086. }
  3087. }
  3088. if (ret && (FileHeader.ServiceTableSize != 0) )
  3089. ret = ReadFile(hFile, Services, FileHeader.ServiceTableSize, &BytesRead, NULL);
  3090. if (ret && (FileHeader.ServiceStringSize != 0) )
  3091. ret = ReadFile(hFile, ServiceStrings, FileHeader.ServiceStringSize, &BytesRead, NULL);
  3092. if (ret && (FileHeader.ServerTableSize != 0) )
  3093. ret = ReadFile(hFile, Servers, FileHeader.ServerTableSize, &BytesRead, NULL);
  3094. if (ret && (FileHeader.ServerStringSize != 0) )
  3095. ret = ReadFile(hFile, ServerStrings, FileHeader.ServerStringSize, &BytesRead, NULL);
  3096. if (ret && (FileHeader.ServerServiceTableSize != 0) )
  3097. ret = ReadFile(hFile, ServerServices, FileHeader.ServerServiceTableSize, &BytesRead, NULL);
  3098. if (ret && (FileHeader.UserTableSize != 0) )
  3099. ret = ReadFile(hFile, Users, FileHeader.UserTableSize, &BytesRead, NULL);
  3100. if (ret && (FileHeader.UserStringSize != 0) )
  3101. ret = ReadFile(hFile, UserStrings, FileHeader.UserStringSize, &BytesRead, NULL);
  3102. if (!ret) {
  3103. Status = GetLastError();
  3104. goto LLSDataLoadExit;
  3105. }
  3106. //
  3107. // Decrypt the data
  3108. //
  3109. Status = DeBlock(Services, FileHeader.ServiceTableSize);
  3110. if (Status == STATUS_SUCCESS)
  3111. Status = DeBlock(ServiceStrings, FileHeader.ServiceStringSize);
  3112. if (Status == STATUS_SUCCESS)
  3113. Status = DeBlock(Servers, FileHeader.ServerTableSize);
  3114. if (Status == STATUS_SUCCESS)
  3115. Status = DeBlock(ServerStrings, FileHeader.ServerStringSize);
  3116. if (Status == STATUS_SUCCESS)
  3117. Status = DeBlock(ServerServices, FileHeader.ServerServiceTableSize);
  3118. if (Status == STATUS_SUCCESS)
  3119. Status = DeBlock(Users, FileHeader.UserTableSize);
  3120. if (Status == STATUS_SUCCESS)
  3121. Status = DeBlock(UserStrings, FileHeader.UserStringSize);
  3122. if (Status != STATUS_SUCCESS)
  3123. goto LLSDataLoadExit;
  3124. //
  3125. // Unpack the string data
  3126. //
  3127. ServiceListStringsUnpack( ServiceTableSize, Services, ServiceStringSize, ServiceStrings );
  3128. ServerListStringsUnpack( ServerTableSize, Servers, ServerStringSize, ServerStrings );
  3129. UserListStringsUnpack( FileHeader.UserLevel, UserTableSize, Users, UserStringSize, UserStrings );
  3130. //
  3131. // Unpack the data
  3132. //
  3133. UnpackAll ( ServiceTableSize, Services, ServerTableSize, Servers,
  3134. ServerServiceTableSize, ServerServices,
  3135. FileHeader.UserLevel, UserTableSize, Users );
  3136. LLSDataLoadExit:
  3137. if (hFile != NULL)
  3138. CloseHandle(hFile);
  3139. //
  3140. // Run through our tables and clean them up
  3141. //
  3142. if (Services != NULL)
  3143. MIDL_user_free(Services);
  3144. if (ServiceStrings != NULL)
  3145. MIDL_user_free(ServiceStrings);
  3146. if (Servers != NULL)
  3147. MIDL_user_free(Servers);
  3148. if (ServerStrings != NULL)
  3149. MIDL_user_free(ServerStrings);
  3150. if (ServerServices != NULL)
  3151. MIDL_user_free(ServerServices);
  3152. if (Users != NULL)
  3153. MIDL_user_free(Users);
  3154. if (UserStrings != NULL)
  3155. MIDL_user_free(UserStrings);
  3156. //
  3157. // If there was an error log it.
  3158. //
  3159. if (Status != STATUS_SUCCESS)
  3160. LogEvent(LLS_EVENT_LOAD_USER, 0, NULL, Status);
  3161. } // LLSDataLoad
  3162. /////////////////////////////////////////////////////////////////////////
  3163. NTSTATUS
  3164. LLSDataSave()
  3165. /*++
  3166. Routine Description:
  3167. Arguments:
  3168. None.
  3169. Return Value:
  3170. None.
  3171. --*/
  3172. {
  3173. BOOL ret = TRUE;
  3174. NTSTATUS Status = STATUS_SUCCESS;
  3175. HANDLE hFile = NULL;
  3176. ULONG ServiceTableSize = 0;
  3177. PREPL_SERVICE_RECORD Services = NULL;
  3178. ULONG ServiceStringSize;
  3179. LPTSTR ServiceStrings = NULL;
  3180. ULONG ServerServiceTableSize = 0;
  3181. PREPL_SERVER_SERVICE_RECORD ServerServices = NULL;
  3182. ULONG ServerTableSize = 0;
  3183. PREPL_SERVER_RECORD Servers = NULL;
  3184. ULONG ServerStringSize;
  3185. LPTSTR ServerStrings = NULL;
  3186. ULONG UserTableSize = 0;
  3187. PREPL_USER_RECORD_1 Users = NULL;
  3188. ULONG UserStringSize;
  3189. LPTSTR UserStrings = NULL;
  3190. LLS_DATA_FILE_HEADER FileHeader;
  3191. DWORD BytesWritten;
  3192. #if DBG
  3193. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_DATABASE))
  3194. dprintf(TEXT("LLS TRACE: LLSDataSave\n"));
  3195. #endif
  3196. //
  3197. // Pack the data
  3198. //
  3199. Status = PackAll ( 0,
  3200. &ServiceTableSize, &Services,
  3201. &ServerTableSize, &Servers,
  3202. &ServerServiceTableSize, &ServerServices,
  3203. 1, &UserTableSize, &Users );
  3204. if (Status != STATUS_SUCCESS)
  3205. goto LLSDataSaveExit;
  3206. //
  3207. // Now pack the String data
  3208. //
  3209. Status = ServiceListStringsPack( ServiceTableSize, Services, &ServiceStringSize, &ServiceStrings );
  3210. if (Status != STATUS_SUCCESS)
  3211. goto LLSDataSaveExit;
  3212. Status = ServerListStringsPack( ServerTableSize, Servers, &ServerStringSize, &ServerStrings );
  3213. if (Status != STATUS_SUCCESS)
  3214. goto LLSDataSaveExit;
  3215. Status = UserListStringsPack( 1, UserTableSize, Users, &UserStringSize, &UserStrings );
  3216. if (Status != STATUS_SUCCESS)
  3217. goto LLSDataSaveExit;
  3218. //
  3219. // Fill out the file header - sizes are byte sizes
  3220. //
  3221. FileHeader.ServiceTableSize = ServiceTableSize * sizeof(REPL_SERVICE_RECORD);
  3222. FileHeader.ServiceStringSize = ServiceStringSize * sizeof(TCHAR);
  3223. FileHeader.ServerTableSize = ServerTableSize * sizeof(REPL_SERVER_RECORD);
  3224. FileHeader.ServerStringSize = ServerStringSize * sizeof(TCHAR);
  3225. FileHeader.ServerServiceTableSize = ServerServiceTableSize * sizeof(REPL_SERVER_SERVICE_RECORD);
  3226. FileHeader.UserTableSize = UserTableSize * sizeof(REPL_USER_RECORD_1);
  3227. FileHeader.UserStringSize = UserStringSize * sizeof(TCHAR);
  3228. FileHeader.ServiceLevel = 0;
  3229. FileHeader.ServerLevel = 0;
  3230. FileHeader.ServerServiceLevel = 0;
  3231. FileHeader.UserLevel = 1;
  3232. //
  3233. // Encrypt the data before saving it out.
  3234. //
  3235. Status = EBlock(Services, FileHeader.ServiceTableSize);
  3236. if (Status == STATUS_SUCCESS)
  3237. Status = EBlock(ServiceStrings, FileHeader.ServiceStringSize);
  3238. if (Status == STATUS_SUCCESS)
  3239. Status = EBlock(Servers, FileHeader.ServerTableSize);
  3240. if (Status == STATUS_SUCCESS)
  3241. Status = EBlock(ServerStrings, FileHeader.ServerStringSize);
  3242. if (Status == STATUS_SUCCESS)
  3243. Status = EBlock(ServerServices, FileHeader.ServerServiceTableSize);
  3244. if (Status == STATUS_SUCCESS)
  3245. Status = EBlock(Users, FileHeader.UserTableSize);
  3246. if (Status == STATUS_SUCCESS)
  3247. Status = EBlock(UserStrings, FileHeader.UserStringSize);
  3248. if (Status != STATUS_SUCCESS)
  3249. goto LLSDataSaveExit;
  3250. //
  3251. // Save out the header record
  3252. //
  3253. hFile = LlsFileInit(UserFileName, USER_FILE_VERSION, sizeof(LLS_DATA_FILE_HEADER) );
  3254. if (hFile == NULL) {
  3255. Status = GetLastError();
  3256. goto LLSDataSaveExit;
  3257. }
  3258. //
  3259. // Now write out all the data blocks
  3260. //
  3261. ret = WriteFile(hFile, &FileHeader, sizeof(LLS_DATA_FILE_HEADER), &BytesWritten, NULL);
  3262. if (ret && (Services != NULL) && (FileHeader.ServiceTableSize != 0) )
  3263. ret = WriteFile(hFile, Services, FileHeader.ServiceTableSize, &BytesWritten, NULL);
  3264. if (ret && (ServiceStrings != NULL) && (FileHeader.ServiceStringSize != 0) )
  3265. ret = WriteFile(hFile, ServiceStrings, FileHeader.ServiceStringSize, &BytesWritten, NULL);
  3266. if (ret && (Servers != NULL) && (FileHeader.ServerTableSize != 0) )
  3267. ret = WriteFile(hFile, Servers, FileHeader.ServerTableSize, &BytesWritten, NULL);
  3268. if (ret && (ServerStrings != NULL) && (FileHeader.ServerStringSize != 0) )
  3269. ret = WriteFile(hFile, ServerStrings, FileHeader.ServerStringSize, &BytesWritten, NULL);
  3270. if (ret && (ServerServices != NULL) && (FileHeader.ServerServiceTableSize != 0) )
  3271. ret = WriteFile(hFile, ServerServices, FileHeader.ServerServiceTableSize, &BytesWritten, NULL);
  3272. if (ret && (Users != NULL) && (FileHeader.UserTableSize != 0) )
  3273. ret = WriteFile(hFile, Users, FileHeader.UserTableSize, &BytesWritten, NULL);
  3274. if (ret && (UserStrings != NULL) && (FileHeader.UserStringSize != 0) )
  3275. ret = WriteFile(hFile, UserStrings, FileHeader.UserStringSize, &BytesWritten, NULL);
  3276. if (!ret)
  3277. Status = GetLastError();
  3278. LLSDataSaveExit:
  3279. if (hFile != NULL)
  3280. CloseHandle(hFile);
  3281. //
  3282. // Run through our tables and clean them up
  3283. //
  3284. if (Services != NULL)
  3285. MIDL_user_free(Services);
  3286. if (ServiceStrings != NULL)
  3287. MIDL_user_free(ServiceStrings);
  3288. if (Servers != NULL)
  3289. MIDL_user_free(Servers);
  3290. if (ServerStrings != NULL)
  3291. MIDL_user_free(ServerStrings);
  3292. if (ServerServices != NULL)
  3293. MIDL_user_free(ServerServices);
  3294. if (Users != NULL)
  3295. MIDL_user_free(Users);
  3296. if (UserStrings != NULL)
  3297. MIDL_user_free(UserStrings);
  3298. //
  3299. // If there was an error log it.
  3300. //
  3301. if (Status != STATUS_SUCCESS)
  3302. LogEvent(LLS_EVENT_SAVE_USER, 0, NULL, Status);
  3303. return Status;
  3304. } // LLSDataSave
  3305. /////////////////////////////////////////////////////////////////////////
  3306. VOID
  3307. LoadAll ( )
  3308. /*++
  3309. Routine Description:
  3310. Arguments:
  3311. Return Value:
  3312. --*/
  3313. {
  3314. #if DBG
  3315. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_DATABASE))
  3316. dprintf(TEXT("LLS TRACE: LoadAll\n"));
  3317. #endif
  3318. PurchaseFile = NULL;
  3319. try {
  3320. LicenseListLoad();
  3321. } except (TRUE) {
  3322. LogEvent(LLS_EVENT_LOAD_LICENSE, 0, NULL, GetExceptionCode());
  3323. }
  3324. try {
  3325. MappingListLoad();
  3326. } except (TRUE) {
  3327. LogEvent(LLS_EVENT_LOAD_MAPPING, 0, NULL, GetExceptionCode());
  3328. }
  3329. try {
  3330. LLSDataLoad();
  3331. } except (TRUE) {
  3332. LogEvent(LLS_EVENT_LOAD_USER, 0, NULL, GetExceptionCode());
  3333. }
  3334. try {
  3335. CertDbLoad();
  3336. } except (TRUE) {
  3337. LogEvent(LLS_EVENT_LOAD_CERT_DB, 0, NULL, GetExceptionCode());
  3338. }
  3339. } // LoadAll
  3340. /////////////////////////////////////////////////////////////////////////
  3341. VOID
  3342. SaveAll ( )
  3343. /*++
  3344. Routine Description:
  3345. Arguments:
  3346. Return Value:
  3347. --*/
  3348. {
  3349. #if DBG
  3350. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_DATABASE))
  3351. dprintf(TEXT("LLS TRACE: SaveAll\n"));
  3352. #endif
  3353. LicenseListSave();
  3354. MappingListSave();
  3355. LLSDataSave();
  3356. CertDbSave();
  3357. } // SaveAll