|
|
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
pack.c
Abstract:
Author:
Arthur Hanson (arth) 06-Jan-1995
Revision History:
Jeff Parham (jeffparh) 05-Dec-1995 o Added new fields to purchase record to support secure certificates. o Unified per server purchase model with per seat purchase model for secure certificates; per server model still done in the traditional manner for non-secure certificates (for backwards compatibility). o Removed assertion on LicenseAdd() failure. LicenseAdd() may legitimately fail under certain circumstances. o Fixed bug wherein a memory allocation failure in the LLS routines would result in a corrupt data file (which would AV the server when it was thereafter read). (Bug #14072.) o Added SaveAll() function analogous to LoadAll(). o Added support for extended user data packing/unpacking. This was done to save the SUITE_USE flag across restarts of the service. o Removed user table parameters from unpack routines that didn't use them. o Fixed ServerServiceListUnpack() to subtract out old values only when they were previously added to the MasterServiceTable. This fixes problems with the MaxSessionCount and HighMark tallies getting skewed.
--*/
#include <stdlib.h>
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <tstr.h>
#include <dsgetdc.h>
#include "llsapi.h"
#include "debug.h"
#include "llsutil.h"
#include "llssrv.h"
#include "mapping.h"
#include "msvctbl.h"
#include "svctbl.h"
#include "perseat.h"
#include "purchase.h"
#include "server.h"
#include "service.h"
#include "llsrpc_s.h"
#include "lsapi_s.h"
#include "llsdbg_s.h"
#include "repl.h"
#include "pack.h"
#include "llsevent.h"
#include "certdb.h"
#include "llsrtl.h"
#include <strsafe.h> //include last
int __cdecl MServiceRecordCompare(const void *arg1, const void *arg2); BOOL ValidateDN(LPTSTR pszDN);
static HANDLE PurchaseFile = NULL;
RTL_CRITICAL_SECTION MappingFileLock; RTL_CRITICAL_SECTION UserFileLock;
/////////////////////////////////////////////////////////////////////////
// License List
//
/////////////////////////////////////////////////////////////////////////
VOID LicenseListUnpackOld ( ULONG LicenseServiceTableSize, PPACK_LICENSE_SERVICE_RECORD LicenseServices,
ULONG LicenseTableSize, PPACK_LICENSE_PURCHASE_RECORD_0 Licenses )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ NTSTATUS Status = STATUS_SUCCESS; ULONG i; PPACK_LICENSE_PURCHASE_RECORD_0 pLicense;
#if DBG
if (TraceFlags & TRACE_FUNCTION_TRACE) dprintf(TEXT("LicenseListUnpackOld: Service[%lu] License[%lu]\n"), LicenseServiceTableSize, LicenseTableSize); #endif
//
// Walk services table, adding any new services to our local table.
// Fix up the index pointers to match our local services.
//
RtlAcquireResourceExclusive(&LicenseListLock, TRUE);
for (i = 0; i < LicenseTableSize; i++) { pLicense = &Licenses[i];
if (pLicense->Service < LicenseServiceTableSize) 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 ); else { ASSERT(FALSE); }
if (Status != STATUS_SUCCESS) { #ifdef DBG
dprintf(TEXT("LicenseAdd failed: 0x%lX\n"), Status); #endif
// ASSERT(FALSE);
}
}
RtlReleaseResource(&LicenseListLock);
} // LicenseListUnpackOld
/////////////////////////////////////////////////////////////////////////
VOID LicenseListStringsUnpackOld ( ULONG LicenseServiceTableSize, PPACK_LICENSE_SERVICE_RECORD LicenseServices,
ULONG LicenseServiceStringSize, LPTSTR LicenseServiceStrings,
ULONG LicenseTableSize, PPACK_LICENSE_PURCHASE_RECORD_0 Licenses,
ULONG LicenseStringSize, LPTSTR LicenseStrings )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ ULONG i; PPACK_LICENSE_SERVICE_RECORD pSvc; PPACK_LICENSE_PURCHASE_RECORD_0 pLicense; TCHAR *pStr;
UNREFERENCED_PARAMETER(LicenseServiceStringSize); UNREFERENCED_PARAMETER(LicenseStringSize);
#if DBG
if (TraceFlags & TRACE_FUNCTION_TRACE) dprintf(TEXT("LicenseListStringsUnpack\n")); #endif
//
// First do license service strings
//
pStr = LicenseServiceStrings; for (i = 0; i < LicenseServiceTableSize; i++) { pSvc = &LicenseServices[i];
pSvc->ServiceName = pStr;
//
// Move to end of current string
//
while (*pStr != TEXT('\0')) pStr++;
// now go past ending NULL
pStr++; }
//
// Now do license purchase strings
//
pStr = LicenseStrings; for (i = 0; i < LicenseTableSize; i++) { pLicense = &Licenses[i];
pLicense->Admin = pStr;
//
// Move to end of current string
//
while (*pStr != TEXT('\0')) pStr++;
// now go past ending NULL
pStr++;
pLicense->Comment = pStr;
//
// Move to end of current string
//
while (*pStr != TEXT('\0')) pStr++;
// now go past ending NULL
pStr++; }
} // LicenseListStringsUnpackOld
/////////////////////////////////////////////////////////////////////////
VOID LicenseListLoadOld()
/*++
Routine Description:
Arguments:
None.
Return Value:
None.
--*/
{ BOOL ret; DWORD Version, DataSize; NTSTATUS Status = STATUS_SUCCESS; HANDLE hFile = NULL;
ULONG LicenseServiceTableSize; PPACK_LICENSE_SERVICE_RECORD LicenseServices = NULL;
ULONG LicenseServiceStringSize; LPTSTR LicenseServiceStrings = NULL;
ULONG LicenseTableSize; PPACK_LICENSE_PURCHASE_RECORD_0 Licenses = NULL;
ULONG LicenseStringSize; LPTSTR LicenseStrings = NULL;
LICENSE_FILE_HEADER_0 FileHeader; DWORD BytesRead;
#if DBG
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_DATABASE)) dprintf(TEXT("LLS TRACE: LicenseListLoad\n")); #endif
//
// Check if we already have file open
//
if (PurchaseFile != NULL) { CloseHandle(PurchaseFile); PurchaseFile = NULL; }
//
// If nothing to load then get-out
//
if (!FileExists(LicenseFileName)) goto LicenseListLoadExit;
//
// Check the init header
//
Version = DataSize = 0; PurchaseFile = LlsFileCheck(LicenseFileName, &Version, &DataSize ); if (PurchaseFile == NULL) { Status = GetLastError(); goto LicenseListLoadExit; }
if ((Version != LICENSE_FILE_VERSION_0) || (DataSize != sizeof(LICENSE_FILE_HEADER_0))) { Status = STATUS_FILE_INVALID; goto LicenseListLoadExit; }
//
// The init header checks out, so load the license header and data blocks
//
hFile = PurchaseFile; ret = ReadFile(hFile, &FileHeader, sizeof(LICENSE_FILE_HEADER_0), &BytesRead, NULL);
LicenseServiceTableSize = 0; LicenseServiceStringSize = 0; LicenseTableSize = 0; LicenseStringSize = 0;
if (ret) { //
// Run through and allocate space to read data blocks into
//
if (FileHeader.LicenseServiceTableSize != 0) { LicenseServiceTableSize = FileHeader.LicenseServiceTableSize / sizeof(PACK_LICENSE_SERVICE_RECORD); LicenseServices = MIDL_user_allocate(FileHeader.LicenseServiceTableSize);
if ( LicenseServices == NULL ) { Status = STATUS_NO_MEMORY; goto LicenseListLoadExit; } }
if (FileHeader.LicenseServiceStringSize != 0) { LicenseServiceStringSize = FileHeader.LicenseServiceStringSize / sizeof(TCHAR); LicenseServiceStrings = MIDL_user_allocate(FileHeader.LicenseServiceStringSize);
if ( LicenseServiceStrings == NULL ) { Status = STATUS_NO_MEMORY; goto LicenseListLoadExit; } }
if (FileHeader.LicenseTableSize != 0) { LicenseTableSize = FileHeader.LicenseTableSize / sizeof(PACK_LICENSE_PURCHASE_RECORD); Licenses = MIDL_user_allocate(FileHeader.LicenseTableSize);
if ( Licenses == NULL ) { Status = STATUS_NO_MEMORY; goto LicenseListLoadExit; } }
if (FileHeader.LicenseStringSize != 0) { LicenseStringSize = FileHeader.LicenseStringSize / sizeof(TCHAR); LicenseStrings = MIDL_user_allocate(FileHeader.LicenseStringSize);
if ( LicenseStrings == NULL ) { Status = STATUS_NO_MEMORY; goto LicenseListLoadExit; } }
}
if (ret && (FileHeader.LicenseServiceTableSize != 0) ) ret = ReadFile(hFile, LicenseServices, FileHeader.LicenseServiceTableSize, &BytesRead, NULL);
if (ret && (FileHeader.LicenseServiceStringSize != 0) ) ret = ReadFile(hFile, LicenseServiceStrings, FileHeader.LicenseServiceStringSize, &BytesRead, NULL);
if (ret && (FileHeader.LicenseTableSize != 0) ) ret = ReadFile(hFile, Licenses, FileHeader.LicenseTableSize, &BytesRead, NULL);
if (ret && (FileHeader.LicenseStringSize != 0) ) ret = ReadFile(hFile, LicenseStrings, FileHeader.LicenseStringSize, &BytesRead, NULL);
if (!ret) { Status = GetLastError(); goto LicenseListLoadExit; }
//
// Decrypt the data
//
Status = DeBlock(LicenseServices, FileHeader.LicenseServiceTableSize);
if (Status == STATUS_SUCCESS) Status = DeBlock(LicenseServiceStrings, FileHeader.LicenseServiceStringSize);
if (Status == STATUS_SUCCESS) Status = DeBlock(Licenses, FileHeader.LicenseTableSize);
if (Status == STATUS_SUCCESS) Status = DeBlock(LicenseStrings, FileHeader.LicenseStringSize);
if (Status != STATUS_SUCCESS) goto LicenseListLoadExit;
//
// Unpack the string data
//
LicenseListStringsUnpackOld( LicenseServiceTableSize, LicenseServices, LicenseServiceStringSize, LicenseServiceStrings, LicenseTableSize, Licenses, LicenseStringSize, LicenseStrings );
//
// Unpack the license data
//
LicenseListUnpackOld( LicenseServiceTableSize, LicenseServices, LicenseTableSize, Licenses );
LicenseListLoadExit:
// Note: Don't close the License Purchase File (keep it locked).
//
// Run through our tables and clean them up
//
if (LicenseServices != NULL) MIDL_user_free(LicenseServices);
if (LicenseServiceStrings != NULL) MIDL_user_free(LicenseServiceStrings);
if (Licenses != NULL) MIDL_user_free(Licenses);
if (LicenseStrings != NULL) MIDL_user_free(LicenseStrings);
//
// If there was an error log it.
//
if (Status != STATUS_SUCCESS) LogEvent(LLS_EVENT_LOAD_LICENSE, 0, NULL, Status);
} // LicenseListLoadOld
/////////////////////////////////////////////////////////////////////////
NTSTATUS LicenseListPack ( ULONG *pLicenseServiceTableSize, PPACK_LICENSE_SERVICE_RECORD *pLicenseServices,
ULONG *pLicenseTableSize, PPACK_LICENSE_PURCHASE_RECORD *pLicenses,
ULONG *pPerServerLicenseServiceTableSize, PPACK_LICENSE_SERVICE_RECORD *pPerServerLicenseServices )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ NTSTATUS Status = STATUS_SUCCESS; PPACK_LICENSE_SERVICE_RECORD LicenseServices = NULL; PPACK_LICENSE_PURCHASE_RECORD Licenses = NULL; ULONG i; ULONG TotalRecords = 0; PLICENSE_SERVICE_RECORD pLicenseService; PLICENSE_PURCHASE_RECORD pLicense; PPACK_LICENSE_SERVICE_RECORD PerServerLicenseServices = NULL; PLICENSE_SERVICE_RECORD pPerServerLicenseService;
#if DBG
if (TraceFlags & TRACE_FUNCTION_TRACE) dprintf(TEXT("LLS TRACE: LicenseListPack\n")); #endif
ASSERT(pLicenseServices != NULL); ASSERT(pLicenseServiceTableSize != NULL);
*pLicenseServices = NULL; *pLicenseServiceTableSize = 0;
ASSERT(pLicenses != NULL); ASSERT(pLicenseTableSize != NULL);
*pLicenses = NULL; *pLicenseTableSize = 0;
ASSERT(pPerServerLicenseServices != NULL); ASSERT(pPerServerLicenseServiceTableSize != NULL);
*pPerServerLicenseServices = NULL; *pPerServerLicenseServiceTableSize = 0;
//////////////////////////////////////////////////////////////////
//
// Do License Service Table First
//
TotalRecords = LicenseServiceListSize;
//
// Make sure there is anything to replicate
//
if (TotalRecords > 0) { //
// Create our buffer to hold all of the garbage
//
LicenseServices = MIDL_user_allocate(TotalRecords * sizeof(PACK_LICENSE_SERVICE_RECORD)); if (LicenseServices == NULL) { ASSERT(FALSE); return STATUS_NO_MEMORY; }
//
// Fill in the buffer - walk the License Services tree
//
for (i = 0; i < LicenseServiceListSize; i++) { pLicenseService = LicenseServiceList[i];
//
// Make index match table in it's current state
//
pLicenseService->Index = i;
LicenseServices[i].ServiceName = pLicenseService->ServiceName; LicenseServices[i].NumberLicenses = pLicenseService->NumberLicenses; } }
*pLicenseServices = LicenseServices; *pLicenseServiceTableSize = TotalRecords;
//////////////////////////////////////////////////////////////////
//
// Now Do Per Server License Service Table
//
TotalRecords = PerServerLicenseServiceListSize;
//
// Make sure there is anything to replicate
//
if (TotalRecords > 0) { //
// Create our buffer to hold all of the garbage
//
PerServerLicenseServices = MIDL_user_allocate(TotalRecords * sizeof(PACK_LICENSE_SERVICE_RECORD)); if (PerServerLicenseServices == NULL) { ASSERT(FALSE);
//
// Clean up already alloc'd information
//
if (LicenseServices != NULL) MIDL_user_free(LicenseServices);
*pLicenseServices = NULL; *pLicenseServiceTableSize = 0;
return STATUS_NO_MEMORY; }
//
// Fill in the buffer - walk the Per Server License Services tree
//
for (i = 0; i < PerServerLicenseServiceListSize; i++) { pPerServerLicenseService = PerServerLicenseServiceList[i];
//
// Make index match table in it's current state
//
pPerServerLicenseService->Index = i;
PerServerLicenseServices[i].ServiceName = pPerServerLicenseService->ServiceName; PerServerLicenseServices[i].NumberLicenses = pPerServerLicenseService->NumberLicenses; } }
*pPerServerLicenseServices = PerServerLicenseServices; *pPerServerLicenseServiceTableSize = TotalRecords;
//////////////////////////////////////////////////////////////////
//
// Now Do License Purchase Records
//
TotalRecords = PurchaseListSize;
//
// Make sure there is anything to replicate
//
if (TotalRecords > 0) { //
// Create our buffer to hold all of the garbage
//
Licenses = MIDL_user_allocate(TotalRecords * sizeof(PACK_LICENSE_PURCHASE_RECORD)); if (Licenses == NULL) { ASSERT(FALSE);
//
// Clean up already alloc'd information
//
if (LicenseServices != NULL) MIDL_user_free(LicenseServices); if (PerServerLicenseServices != NULL) MIDL_user_free(PerServerLicenseServices);
*pLicenseServices = NULL; *pLicenseServiceTableSize = 0; *pPerServerLicenseServices = NULL; *pPerServerLicenseServiceTableSize = 0;
return STATUS_NO_MEMORY; }
//
// Fill in the buffer - walk the License Purchase tree
//
for (i = 0; i < PurchaseListSize; i++) { pLicense = &PurchaseList[i];
//
// License Service table index is fixed-up to what we need
//
Licenses[i].Service = ( pLicense->AllowedModes & 1 ) ? pLicense->Service->Index : 0xFFFFFFFF; Licenses[i].NumberLicenses = pLicense->NumberLicenses; Licenses[i].Date = pLicense->Date; Licenses[i].Admin = pLicense->Admin; Licenses[i].Comment = pLicense->Comment;
Licenses[i].PerServerService = ( pLicense->AllowedModes & 2 ) ? pLicense->PerServerService->Index : 0xFFFFFFFF; Licenses[i].AllowedModes = pLicense->AllowedModes; Licenses[i].CertificateID = pLicense->CertificateID; Licenses[i].Source = pLicense->Source; Licenses[i].ExpirationDate = pLicense->ExpirationDate; Licenses[i].MaxQuantity = pLicense->MaxQuantity; Licenses[i].Vendor = pLicense->Vendor; memcpy( Licenses[i].Secrets, pLicense->Secrets, LLS_NUM_SECRETS * sizeof( *pLicense->Secrets ) ); } }
*pLicenses = Licenses; *pLicenseTableSize = TotalRecords; return Status; } // LicenseListPack
/////////////////////////////////////////////////////////////////////////
VOID LicenseListUnpack ( ULONG LicenseServiceTableSize, PPACK_LICENSE_SERVICE_RECORD LicenseServices,
ULONG LicenseTableSize, PPACK_LICENSE_PURCHASE_RECORD Licenses,
ULONG PerServerLicenseServiceTableSize, PPACK_LICENSE_SERVICE_RECORD PerServerLicenseServices )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ NTSTATUS Status = STATUS_SUCCESS; ULONG i; PPACK_LICENSE_PURCHASE_RECORD pLicense; LPTSTR ServiceName;
#if DBG
if (TraceFlags & TRACE_FUNCTION_TRACE) dprintf(TEXT("LicenseListUnpack: Service[%lu] PerServerService[%lu] License[%lu]\n"), LicenseServiceTableSize, PerServerLicenseServiceTableSize, LicenseTableSize); #endif
//
// Walk services table, adding any new services to our local table.
// Fix up the index pointers to match our local services.
//
RtlAcquireResourceExclusive(&LicenseListLock, TRUE);
for (i = 0; i < LicenseTableSize; i++) { pLicense = &Licenses[i];
ServiceName = NULL;
if ( pLicense->AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SERVER ) { if ( pLicense->PerServerService < PerServerLicenseServiceTableSize ) { ServiceName = PerServerLicenseServices[ pLicense->PerServerService ].ServiceName; } else { ASSERT( FALSE ); } }
if ( ( NULL == ServiceName ) && ( pLicense->AllowedModes & LLS_LICENSE_MODE_ALLOW_PER_SEAT ) ) { if ( pLicense->Service < LicenseServiceTableSize ) { ServiceName = LicenseServices[ pLicense->Service ].ServiceName; } else { ASSERT( FALSE ); } }
if ( NULL == ServiceName ) { ASSERT( FALSE ); } else { 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 );
if (Status != STATUS_SUCCESS) { #ifdef DBG
dprintf(TEXT("LicenseAdd failed: 0x%lX\n"), Status); #endif
// ASSERT(FALSE);
} } if (i % 100 == 0) ReportStatusToSCMgr( SERVICE_START_PENDING, NO_ERROR, NSERVICEWAITHINT); }
RtlReleaseResource(&LicenseListLock);
} // LicenseListUnpack
/////////////////////////////////////////////////////////////////////////
NTSTATUS LicenseListStringsPack ( ULONG LicenseServiceTableSize, PPACK_LICENSE_SERVICE_RECORD LicenseServices,
ULONG *pLicenseServiceStringSize, LPTSTR *pLicenseServiceStrings,
ULONG LicenseTableSize, PPACK_LICENSE_PURCHASE_RECORD Licenses,
ULONG *pLicenseStringSize, LPTSTR *pLicenseStrings,
ULONG PerServerLicenseServiceTableSize, PPACK_LICENSE_SERVICE_RECORD PerServerLicenseServices,
ULONG *pPerServerLicenseServiceStringSize, LPTSTR *pPerServerLicenseServiceStrings )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ NTSTATUS Status = STATUS_SUCCESS; ULONG i; ULONG StringSize; PPACK_LICENSE_SERVICE_RECORD pSvc; PPACK_LICENSE_PURCHASE_RECORD pLicense; LPTSTR LicenseServiceStrings = NULL; LPTSTR LicenseStrings = NULL; TCHAR *pStr; LPTSTR PerServerLicenseServiceStrings = NULL; HRESULT hr;
#if DBG
if (TraceFlags & TRACE_FUNCTION_TRACE) dprintf(TEXT("LicenseListStringsPack\n")); #endif
ASSERT(pLicenseServiceStrings != NULL); ASSERT(pLicenseServiceStringSize != NULL);
*pLicenseServiceStrings = NULL; *pLicenseServiceStringSize = 0;
ASSERT(pLicenseStrings != NULL); ASSERT(pLicenseStringSize != NULL);
*pLicenseStrings = NULL; *pLicenseStringSize = 0;
ASSERT(pPerServerLicenseServiceStrings != NULL); ASSERT(pPerServerLicenseServiceStringSize != NULL);
*pPerServerLicenseServiceStrings = NULL; *pPerServerLicenseServiceStringSize = 0;
//////////////////////////////////////////////////////////////////
//
// Do License Service Strings
//
//
// First walk the list adding up string sizes - to calculate our buff size
//
StringSize = 0; for (i = 0; i < LicenseServiceTableSize; i++) { pSvc = &LicenseServices[i];
StringSize = StringSize + lstrlen(pSvc->ServiceName) + 1; }
//
// Make sure there is anything to replicate
//
if (StringSize > 0) { //
// Create our buffer to hold all of the garbage
//
LicenseServiceStrings = MIDL_user_allocate(StringSize * sizeof(TCHAR)); if (LicenseServiceStrings == NULL) { ASSERT(FALSE); return STATUS_NO_MEMORY; }
//
// Fill in the buffer
//
pStr = LicenseServiceStrings; for (i = 0; i < LicenseServiceTableSize; i++) { pSvc = &LicenseServices[i]; hr = StringCchCopy(pStr, StringSize, pSvc->ServiceName); ASSERT(SUCCEEDED(hr)); pStr = &pStr[lstrlen(pSvc->ServiceName) + 1]; } }
*pLicenseServiceStrings = LicenseServiceStrings; *pLicenseServiceStringSize = StringSize;
//////////////////////////////////////////////////////////////////
//
// Do Per Server License Service Strings
//
//
// First walk the list adding up string sizes - to calculate our buff size
//
StringSize = 0; for (i = 0; i < PerServerLicenseServiceTableSize; i++) { pSvc = &PerServerLicenseServices[i];
StringSize = StringSize + lstrlen(pSvc->ServiceName) + 1; }
//
// Make sure there is anything to replicate
//
if (StringSize > 0) { //
// Create our buffer to hold all of the garbage
//
PerServerLicenseServiceStrings = MIDL_user_allocate(StringSize * sizeof(TCHAR)); if (PerServerLicenseServiceStrings == NULL) { ASSERT(FALSE);
//
// Clean up already alloc'd information
//
if (LicenseServiceStrings != NULL) MIDL_user_free(LicenseServiceStrings);
*pLicenseServiceStrings = NULL; *pLicenseServiceStringSize = 0;
return STATUS_NO_MEMORY; }
//
// Fill in the buffer
//
pStr = PerServerLicenseServiceStrings; for (i = 0; i < PerServerLicenseServiceTableSize; i++) { pSvc = &PerServerLicenseServices[i]; hr = StringCchCopy(pStr, StringSize, pSvc->ServiceName); ASSERT(SUCCEEDED(hr)); pStr = &pStr[lstrlen(pSvc->ServiceName) + 1]; } }
*pPerServerLicenseServiceStrings = PerServerLicenseServiceStrings; *pPerServerLicenseServiceStringSize = StringSize;
//////////////////////////////////////////////////////////////////
//
// Now Do License Purchase Strings
//
//
// First walk the list adding up string sizes - to calculate our buff size
//
StringSize = 0; for (i = 0; i < LicenseTableSize; i++) { pLicense = &Licenses[i];
StringSize = StringSize + lstrlen(pLicense->Vendor) + 1; StringSize = StringSize + lstrlen(pLicense->Admin) + 1; StringSize = StringSize + lstrlen(pLicense->Comment) + 1; StringSize = StringSize + lstrlen(pLicense->Source) + 1; }
//
// Make sure there is anything to replicate
//
if (StringSize > 0) { //
// Create our buffer to hold all of the garbage
//
LicenseStrings = MIDL_user_allocate(StringSize * sizeof(TCHAR)); if (LicenseStrings == NULL) { ASSERT(FALSE);
//
// Clean up already alloc'd information
//
if (LicenseServiceStrings != NULL) MIDL_user_free(LicenseServiceStrings); if (PerServerLicenseServiceStrings != NULL) MIDL_user_free(PerServerLicenseServiceStrings);
*pLicenseServiceStrings = NULL; *pLicenseServiceStringSize = 0; *pPerServerLicenseServiceStrings = NULL; *pPerServerLicenseServiceStringSize = 0;
return STATUS_NO_MEMORY; }
//
// Fill in the buffer
//
pStr = LicenseStrings; for (i = 0; i < LicenseTableSize; i++) { pLicense = &Licenses[i]; hr = StringCchCopy(pStr, StringSize, pLicense->Vendor); ASSERT(SUCCEEDED(hr)); pStr = &pStr[lstrlen(pLicense->Vendor) + 1]; hr = StringCchCopy(pStr, StringSize, pLicense->Admin); ASSERT(SUCCEEDED(hr)); pStr = &pStr[lstrlen(pLicense->Admin) + 1]; hr = StringCchCopy(pStr, StringSize, pLicense->Comment); ASSERT(SUCCEEDED(hr)); pStr = &pStr[lstrlen(pLicense->Comment) + 1]; hr = StringCchCopy(pStr, StringSize, pLicense->Source); ASSERT(SUCCEEDED(hr)); pStr = &pStr[lstrlen(pLicense->Source) + 1]; } }
*pLicenseStrings = LicenseStrings; *pLicenseStringSize = StringSize;
return Status; } // LicenseListStringsPack
/////////////////////////////////////////////////////////////////////////
VOID LicenseListStringsUnpack ( ULONG LicenseServiceTableSize, PPACK_LICENSE_SERVICE_RECORD LicenseServices,
ULONG LicenseServiceStringSize, LPTSTR LicenseServiceStrings,
ULONG LicenseTableSize, PPACK_LICENSE_PURCHASE_RECORD Licenses,
ULONG LicenseStringSize, LPTSTR LicenseStrings,
ULONG PerServerLicenseServiceTableSize, PPACK_LICENSE_SERVICE_RECORD PerServerLicenseServices,
ULONG PerServerLicenseServiceStringSize, LPTSTR PerServerLicenseServiceStrings )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ ULONG i; PPACK_LICENSE_SERVICE_RECORD pSvc; PPACK_LICENSE_PURCHASE_RECORD pLicense; TCHAR *pStr;
UNREFERENCED_PARAMETER(LicenseServiceStringSize); UNREFERENCED_PARAMETER(LicenseStringSize); UNREFERENCED_PARAMETER(PerServerLicenseServiceStringSize);
#if DBG
if (TraceFlags & TRACE_FUNCTION_TRACE) dprintf(TEXT("LicenseListStringsUnpack\n")); #endif
//
// First do per seat license service strings
//
pStr = LicenseServiceStrings; for (i = 0; i < LicenseServiceTableSize; i++) { pSvc = &LicenseServices[i];
pSvc->ServiceName = pStr;
//
// Move to end of current string
//
while (*pStr != TEXT('\0')) pStr++;
// now go past ending NULL
pStr++; }
//
// Then do per server license service strings
//
pStr = PerServerLicenseServiceStrings; for (i = 0; i < PerServerLicenseServiceTableSize; i++) { pSvc = &PerServerLicenseServices[i];
pSvc->ServiceName = pStr;
//
// Move to end of current string
//
while (*pStr != TEXT('\0')) pStr++;
// now go past ending NULL
pStr++; }
//
// Now do license purchase strings
//
pStr = LicenseStrings; for (i = 0; i < LicenseTableSize; i++) { pLicense = &Licenses[i];
pLicense->Vendor = pStr;
//
// Move to end of current string
//
while (*pStr != TEXT('\0')) pStr++;
// now go past ending NULL
pStr++;
pLicense->Admin = pStr;
//
// Move to end of current string
//
while (*pStr != TEXT('\0')) pStr++;
// now go past ending NULL
pStr++;
pLicense->Comment = pStr;
//
// Move to end of current string
//
while (*pStr != TEXT('\0')) pStr++;
// now go past ending NULL
pStr++;
pLicense->Source = pStr;
//
// Move to end of current string
//
while (*pStr != TEXT('\0')) pStr++;
// now go past ending NULL
pStr++; }
} // LicenseListStringsUnpack
/////////////////////////////////////////////////////////////////////////
VOID LicenseListLoad()
/*++
Routine Description:
Arguments:
None.
Return Value:
None.
--*/
{ BOOL ret; DWORD Version, DataSize; NTSTATUS Status = STATUS_SUCCESS; HANDLE hFile = NULL;
ULONG LicenseServiceTableSize; PPACK_LICENSE_SERVICE_RECORD LicenseServices = NULL;
ULONG LicenseServiceStringSize; LPTSTR LicenseServiceStrings = NULL;
ULONG PerServerLicenseServiceTableSize = 0; PPACK_LICENSE_SERVICE_RECORD PerServerLicenseServices = NULL;
ULONG PerServerLicenseServiceStringSize = 0; LPTSTR PerServerLicenseServiceStrings = NULL;
ULONG LicenseTableSize; PPACK_LICENSE_PURCHASE_RECORD Licenses = NULL;
ULONG LicenseStringSize; LPTSTR LicenseStrings = NULL;
LICENSE_FILE_HEADER FileHeader; DWORD BytesRead;
#if DBG
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_DATABASE)) dprintf(TEXT("LLS TRACE: LicenseListLoad\n")); #endif
//
// Check if we already have file open
//
if (PurchaseFile != NULL) { CloseHandle(PurchaseFile); PurchaseFile = NULL; }
//
// If nothing to load then get-out
//
if (!FileExists(LicenseFileName)) goto LicenseListLoadExit;
//
// Check the init header
//
Version = DataSize = 0; PurchaseFile = LlsFileCheck(LicenseFileName, &Version, &DataSize ); if (PurchaseFile == NULL) { Status = GetLastError(); goto LicenseListLoadExit; }
if ( ( Version == LICENSE_FILE_VERSION_0 ) && ( DataSize == sizeof(LICENSE_FILE_HEADER_0) ) ) { CloseHandle(PurchaseFile); PurchaseFile = NULL;
LicenseListLoadOld(); return; }
if ( ( Version != LICENSE_FILE_VERSION ) || ( DataSize != sizeof(LICENSE_FILE_HEADER) ) ) { Status = STATUS_FILE_INVALID; goto LicenseListLoadExit; }
//
// The init header checks out, so load the license header and data blocks
//
hFile = PurchaseFile; ret = ReadFile(hFile, &FileHeader, sizeof(LICENSE_FILE_HEADER), &BytesRead, NULL);
LicenseServiceTableSize = 0; LicenseServiceStringSize = 0; LicenseTableSize = 0; LicenseStringSize = 0;
if (ret) { //
// Run through and allocate space to read data blocks into
//
if (FileHeader.LicenseServiceTableSize != 0) { LicenseServiceTableSize = FileHeader.LicenseServiceTableSize / sizeof(PACK_LICENSE_SERVICE_RECORD); LicenseServices = MIDL_user_allocate(FileHeader.LicenseServiceTableSize);
if ( LicenseServices == NULL ) { Status = STATUS_NO_MEMORY; goto LicenseListLoadExit; } }
if (FileHeader.LicenseServiceStringSize != 0) { LicenseServiceStringSize = FileHeader.LicenseServiceStringSize / sizeof(TCHAR); LicenseServiceStrings = MIDL_user_allocate(FileHeader.LicenseServiceStringSize);
if ( LicenseServiceStrings == NULL ) { Status = STATUS_NO_MEMORY; goto LicenseListLoadExit; } }
if (FileHeader.LicenseServiceTableSize != 0) { PerServerLicenseServiceTableSize = FileHeader.PerServerLicenseServiceTableSize / sizeof(PACK_LICENSE_SERVICE_RECORD); PerServerLicenseServices = MIDL_user_allocate(FileHeader.PerServerLicenseServiceTableSize);
if ( PerServerLicenseServices == NULL ) { Status = STATUS_NO_MEMORY; goto LicenseListLoadExit; } }
if (FileHeader.PerServerLicenseServiceStringSize != 0) { PerServerLicenseServiceStringSize = FileHeader.PerServerLicenseServiceStringSize / sizeof(TCHAR); PerServerLicenseServiceStrings = MIDL_user_allocate(FileHeader.PerServerLicenseServiceStringSize);
if ( PerServerLicenseServiceStrings == NULL ) { Status = STATUS_NO_MEMORY; goto LicenseListLoadExit; } }
if (FileHeader.LicenseTableSize != 0) { LicenseTableSize = FileHeader.LicenseTableSize / sizeof(PACK_LICENSE_PURCHASE_RECORD); Licenses = MIDL_user_allocate(FileHeader.LicenseTableSize);
if ( Licenses == NULL ) { Status = STATUS_NO_MEMORY; goto LicenseListLoadExit; } }
if (FileHeader.LicenseStringSize != 0) { LicenseStringSize = FileHeader.LicenseStringSize / sizeof(TCHAR); LicenseStrings = MIDL_user_allocate(FileHeader.LicenseStringSize);
if ( LicenseStrings == NULL ) { Status = STATUS_NO_MEMORY; goto LicenseListLoadExit; } }
}
if (ret && (FileHeader.LicenseServiceTableSize != 0) ) ret = ReadFile(hFile, LicenseServices, FileHeader.LicenseServiceTableSize, &BytesRead, NULL);
if (ret && (FileHeader.LicenseServiceStringSize != 0) ) ret = ReadFile(hFile, LicenseServiceStrings, FileHeader.LicenseServiceStringSize, &BytesRead, NULL);
if (ret && (FileHeader.PerServerLicenseServiceTableSize != 0) ) ret = ReadFile(hFile, PerServerLicenseServices, FileHeader.PerServerLicenseServiceTableSize, &BytesRead, NULL);
if (ret && (FileHeader.PerServerLicenseServiceStringSize != 0) ) ret = ReadFile(hFile, PerServerLicenseServiceStrings, FileHeader.PerServerLicenseServiceStringSize, &BytesRead, NULL);
if (ret && (FileHeader.LicenseTableSize != 0) ) ret = ReadFile(hFile, Licenses, FileHeader.LicenseTableSize, &BytesRead, NULL);
if (ret && (FileHeader.LicenseStringSize != 0) ) ret = ReadFile(hFile, LicenseStrings, FileHeader.LicenseStringSize, &BytesRead, NULL);
if (!ret) { Status = GetLastError(); goto LicenseListLoadExit; }
//
// Decrypt the data
//
Status = DeBlock(LicenseServices, FileHeader.LicenseServiceTableSize);
if (Status == STATUS_SUCCESS) Status = DeBlock(LicenseServiceStrings, FileHeader.LicenseServiceStringSize);
if (Status == STATUS_SUCCESS) Status = DeBlock(PerServerLicenseServices, FileHeader.PerServerLicenseServiceTableSize);
if (Status == STATUS_SUCCESS) Status = DeBlock(PerServerLicenseServiceStrings, FileHeader.PerServerLicenseServiceStringSize);
if (Status == STATUS_SUCCESS) Status = DeBlock(Licenses, FileHeader.LicenseTableSize);
if (Status == STATUS_SUCCESS) Status = DeBlock(LicenseStrings, FileHeader.LicenseStringSize);
if (Status != STATUS_SUCCESS) goto LicenseListLoadExit;
//
// Unpack the string data
//
LicenseListStringsUnpack( LicenseServiceTableSize, LicenseServices, LicenseServiceStringSize, LicenseServiceStrings, LicenseTableSize, Licenses, LicenseStringSize, LicenseStrings, PerServerLicenseServiceTableSize, PerServerLicenseServices, PerServerLicenseServiceStringSize, PerServerLicenseServiceStrings );
//
// Unpack the license data
//
LicenseListUnpack( LicenseServiceTableSize, LicenseServices, LicenseTableSize, Licenses, PerServerLicenseServiceTableSize, PerServerLicenseServices );
LicenseListLoadExit:
// Note: Don't close the License Purchase File (keep it locked).
//
// Run through our tables and clean them up
//
if (LicenseServices != NULL) MIDL_user_free(LicenseServices);
if (LicenseServiceStrings != NULL) MIDL_user_free(LicenseServiceStrings);
if (PerServerLicenseServices != NULL) MIDL_user_free(PerServerLicenseServices);
if (PerServerLicenseServiceStrings != NULL) MIDL_user_free(PerServerLicenseServiceStrings);
if (Licenses != NULL) MIDL_user_free(Licenses);
if (LicenseStrings != NULL) MIDL_user_free(LicenseStrings);
//
// If there was an error log it.
//
if (Status != STATUS_SUCCESS) LogEvent(LLS_EVENT_LOAD_LICENSE, 0, NULL, Status);
} // LicenseListLoad
/////////////////////////////////////////////////////////////////////////
NTSTATUS LicenseListSave()
/*++
Routine Description:
Arguments:
None.
Return Value:
None.
--*/
{ BOOL ret = TRUE; NTSTATUS Status = STATUS_SUCCESS; HANDLE hFile = NULL;
ULONG LicenseServiceTableSize; PPACK_LICENSE_SERVICE_RECORD LicenseServices = NULL;
ULONG LicenseServiceStringSize; LPTSTR LicenseServiceStrings = NULL;
ULONG PerServerLicenseServiceTableSize; PPACK_LICENSE_SERVICE_RECORD PerServerLicenseServices = NULL;
ULONG PerServerLicenseServiceStringSize; LPTSTR PerServerLicenseServiceStrings = NULL;
ULONG LicenseTableSize; PPACK_LICENSE_PURCHASE_RECORD Licenses = NULL;
ULONG LicenseStringSize; LPTSTR LicenseStrings = NULL;
LICENSE_FILE_HEADER FileHeader; DWORD BytesWritten;
#if DBG
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_DATABASE)) dprintf(TEXT("LLS TRACE: LicenseListSave\n")); #endif
RtlAcquireResourceExclusive(&LicenseListLock, TRUE);
//
// Check if we already have file open
//
if (PurchaseFile != NULL) { CloseHandle(PurchaseFile); PurchaseFile = NULL; }
//
// If nothing to save then get-out
//
if ( (LicenseServiceListSize == 0) && (PerServerLicenseServiceListSize == 0) ) goto LicenseListSaveExit;
//
// Pack the license data
//
Status = LicenseListPack( &LicenseServiceTableSize, &LicenseServices, &LicenseTableSize, &Licenses, &PerServerLicenseServiceTableSize, &PerServerLicenseServices ); if (Status != STATUS_SUCCESS) goto LicenseListSaveExit;
//
// Now pack the String data
//
Status = LicenseListStringsPack( LicenseServiceTableSize, LicenseServices, &LicenseServiceStringSize, &LicenseServiceStrings, LicenseTableSize, Licenses, &LicenseStringSize, &LicenseStrings, PerServerLicenseServiceTableSize, PerServerLicenseServices, &PerServerLicenseServiceStringSize, &PerServerLicenseServiceStrings );
if (Status != STATUS_SUCCESS) goto LicenseListSaveExit;
//
// Fill out the file header - sizes are byte sizes
//
FileHeader.LicenseServiceTableSize = LicenseServiceTableSize * sizeof(PACK_LICENSE_SERVICE_RECORD); FileHeader.LicenseServiceStringSize = LicenseServiceStringSize * sizeof(TCHAR); FileHeader.PerServerLicenseServiceTableSize = PerServerLicenseServiceTableSize * sizeof(PACK_LICENSE_SERVICE_RECORD); FileHeader.PerServerLicenseServiceStringSize = PerServerLicenseServiceStringSize * sizeof(TCHAR); FileHeader.LicenseTableSize = LicenseTableSize * sizeof(PACK_LICENSE_PURCHASE_RECORD); FileHeader.LicenseStringSize = LicenseStringSize * sizeof(TCHAR);
//
// Encrypt the data before saving it out.
//
Status = EBlock(LicenseServices, FileHeader.LicenseServiceTableSize);
if (Status == STATUS_SUCCESS) Status = EBlock(LicenseServiceStrings, FileHeader.LicenseServiceStringSize);
if (Status == STATUS_SUCCESS) Status = EBlock(PerServerLicenseServices, FileHeader.PerServerLicenseServiceTableSize);
if (Status == STATUS_SUCCESS) Status = EBlock(PerServerLicenseServiceStrings, FileHeader.PerServerLicenseServiceStringSize);
if (Status == STATUS_SUCCESS) Status = EBlock(Licenses, FileHeader.LicenseTableSize);
if (Status == STATUS_SUCCESS) Status = EBlock(LicenseStrings, FileHeader.LicenseStringSize);
if (Status != STATUS_SUCCESS) goto LicenseListSaveExit;
//
// Save out the header record
//
PurchaseFile = LlsFileInit(LicenseFileName, LICENSE_FILE_VERSION, sizeof(LICENSE_FILE_HEADER) ); if (PurchaseFile == NULL) { Status = GetLastError(); goto LicenseListSaveExit; }
//
// Now write out all the data blocks
//
hFile = PurchaseFile;
ret = WriteFile(hFile, &FileHeader, sizeof(LICENSE_FILE_HEADER), &BytesWritten, NULL);
if (ret && (LicenseServices != NULL) && (FileHeader.LicenseServiceTableSize != 0)) ret = WriteFile(hFile, LicenseServices, FileHeader.LicenseServiceTableSize, &BytesWritten, NULL);
if (ret && (LicenseServiceStrings != NULL) && (FileHeader.LicenseServiceStringSize != 0)) ret = WriteFile(hFile, LicenseServiceStrings, FileHeader.LicenseServiceStringSize, &BytesWritten, NULL);
if (ret && (PerServerLicenseServices != NULL) && (FileHeader.PerServerLicenseServiceTableSize != 0)) ret = WriteFile(hFile, PerServerLicenseServices, FileHeader.PerServerLicenseServiceTableSize, &BytesWritten, NULL);
if (ret && (PerServerLicenseServiceStrings != NULL) && (FileHeader.PerServerLicenseServiceStringSize != 0)) ret = WriteFile(hFile, PerServerLicenseServiceStrings, FileHeader.PerServerLicenseServiceStringSize, &BytesWritten, NULL);
if (ret && (Licenses != NULL) && (FileHeader.LicenseTableSize != 0)) ret = WriteFile(hFile, Licenses, FileHeader.LicenseTableSize, &BytesWritten, NULL);
if (ret && (LicenseStrings != NULL) && (FileHeader.LicenseStringSize != 0)) ret = WriteFile(hFile, LicenseStrings, FileHeader.LicenseStringSize, &BytesWritten, NULL);
if (!ret) Status = GetLastError();
LicenseListSaveExit: RtlReleaseResource(&LicenseListLock);
// Note: Don't close the License Purchase File (keep it locked).
if (hFile != NULL) FlushFileBuffers(hFile);
//
// Run through our tables and clean them up
//
if (LicenseServices != NULL) MIDL_user_free(LicenseServices);
if (LicenseServiceStrings != NULL) MIDL_user_free(LicenseServiceStrings);
if (PerServerLicenseServices != NULL) MIDL_user_free(PerServerLicenseServices);
if (PerServerLicenseServiceStrings != NULL) MIDL_user_free(PerServerLicenseServiceStrings);
if (Licenses != NULL) MIDL_user_free(Licenses);
if (LicenseStrings != NULL) MIDL_user_free(LicenseStrings);
//
// If there was an error log it.
//
if (Status != STATUS_SUCCESS) LogEvent(LLS_EVENT_SAVE_LICENSE, 0, NULL, Status);
return Status; } // LicenseListSave
/////////////////////////////////////////////////////////////////////////
// Mapping List
//
/////////////////////////////////////////////////////////////////////////
NTSTATUS MappingListPack ( ULONG *pMappingUserTableSize, PPACK_MAPPING_USER_RECORD *pMappingUsers,
ULONG *pMappingTableSize, PPACK_MAPPING_RECORD *pMappings )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ NTSTATUS Status = STATUS_SUCCESS; PPACK_MAPPING_USER_RECORD MappingUsers = NULL; PPACK_MAPPING_RECORD Mappings = NULL; ULONG i, j, k; ULONG TotalRecords = 0; PMAPPING_RECORD pMapping;
#if DBG
if (TraceFlags & TRACE_FUNCTION_TRACE) dprintf(TEXT("LLS TRACE: MappingListPack\n")); #endif
ASSERT(pMappingUsers != NULL); ASSERT(pMappingUserTableSize != NULL);
*pMappingUsers = NULL; *pMappingUserTableSize = 0;
ASSERT(pMappings != NULL); ASSERT(pMappingTableSize != NULL);
*pMappings = NULL; *pMappingTableSize = 0;
//////////////////////////////////////////////////////////////////
//
// Do Mapping User Table First
//
TotalRecords = 0;
//
// Make sure there is anything to replicate
//
for (i = 0; i < MappingListSize; i++) TotalRecords += MappingList[i]->NumMembers;
if (TotalRecords > 0) { //
// Create our buffer to hold all of the garbage
//
MappingUsers = MIDL_user_allocate(TotalRecords * sizeof(PACK_MAPPING_USER_RECORD)); if (MappingUsers == NULL) { ASSERT(FALSE); return STATUS_NO_MEMORY; }
//
// Fill in the buffer - walk the Mapping tree
//
k = 0; for (i = 0; i < MappingListSize; i++) { pMapping = MappingList[i];
for (j = 0; j < pMapping->NumMembers; j++) { MappingUsers[k].Mapping = i; MappingUsers[k].Name = pMapping->Members[j]; k++; } } }
*pMappingUsers = MappingUsers; *pMappingUserTableSize = TotalRecords;
//////////////////////////////////////////////////////////////////
//
// Now Do Mapping Records
//
TotalRecords = MappingListSize;
//
// Make sure there is anything to replicate
//
if (TotalRecords > 0) { //
// Create our buffer to hold all of the garbage
//
Mappings = MIDL_user_allocate(TotalRecords * sizeof(PACK_MAPPING_RECORD)); if (Mappings == NULL) { ASSERT(FALSE);
//
// Clean up already alloc'd information
//
if (MappingUsers != NULL) MIDL_user_free(MappingUsers);
*pMappingUsers = NULL; *pMappingUserTableSize = 0;
return STATUS_NO_MEMORY; }
//
// Fill in the buffer - walk the License Purchase tree
//
for (i = 0; i < MappingListSize; i++) { pMapping = MappingList[i];
Mappings[i].Name = pMapping->Name; Mappings[i].Comment = pMapping->Comment; Mappings[i].Licenses = pMapping->Licenses; } }
*pMappings = Mappings; *pMappingTableSize = TotalRecords; return Status; } // MappingListPack
/////////////////////////////////////////////////////////////////////////
VOID MappingListUnpack ( ULONG MappingUserTableSize, PPACK_MAPPING_USER_RECORD MappingUsers,
ULONG MappingTableSize, PPACK_MAPPING_RECORD Mappings )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ ULONG i; PPACK_MAPPING_USER_RECORD pUsr; PPACK_MAPPING_RECORD pMapping; PMAPPING_RECORD pMap;
#if DBG
if (TraceFlags & TRACE_FUNCTION_TRACE) dprintf(TEXT("MappingListUnpack: Mappings[%lu] TotalUsers[%lu]\n"), MappingTableSize, MappingUserTableSize); #endif
RtlAcquireResourceExclusive(&MappingListLock, TRUE);
//
// Add the Mappings first
//
for (i = 0; i < MappingTableSize; i++) { pMapping = &Mappings[i];
pMap = MappingListAdd(pMapping->Name, pMapping->Comment, pMapping->Licenses,NULL);
if (i % 100 == 0) ReportStatusToSCMgr( SERVICE_START_PENDING, NO_ERROR, NSERVICEWAITHINT); }
//
// Now add the users to the mappings...
//
for (i = 0; i < MappingUserTableSize; i++) { pUsr = &MappingUsers[i];
pMap = NULL; if (pUsr->Mapping < MappingTableSize) pMap = MappingUserListAdd(Mappings[pUsr->Mapping].Name, pUsr->Name);
#if DBG
if (pMap == NULL) { dprintf(TEXT("pMap: 0x%lX pUsr->Mapping: %lu MappingTableSize: %lu\n"), pMap, pUsr->Mapping, MappingTableSize); ASSERT(FALSE); } #endif
if (i % 100 == 0) ReportStatusToSCMgr( SERVICE_START_PENDING, NO_ERROR, NSERVICEWAITHINT); }
RtlReleaseResource(&MappingListLock);
} // MappingListUnpack
/////////////////////////////////////////////////////////////////////////
NTSTATUS MappingListStringsPack ( ULONG MappingUserTableSize, PPACK_MAPPING_USER_RECORD MappingUsers,
ULONG *pMappingUserStringSize, LPTSTR *pMappingUserStrings,
ULONG MappingTableSize, PPACK_MAPPING_RECORD Mappings,
ULONG *pMappingStringSize, LPTSTR *pMappingStrings )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ NTSTATUS Status = STATUS_SUCCESS; ULONG i; ULONG StringSize; PPACK_MAPPING_USER_RECORD pUsr; PPACK_MAPPING_RECORD pMapping; LPTSTR MappingUserStrings = NULL; LPTSTR MappingStrings = NULL; TCHAR *pStr; HRESULT hr;
#if DBG
if (TraceFlags & TRACE_FUNCTION_TRACE) dprintf(TEXT("MappingListStringsPack\n")); #endif
ASSERT(pMappingUserStrings != NULL); ASSERT(pMappingUserStringSize != NULL);
*pMappingUserStrings = NULL; *pMappingUserStringSize = 0;
ASSERT(pMappingStrings != NULL); ASSERT(pMappingStringSize != NULL);
*pMappingStrings = NULL; *pMappingStringSize = 0;
//////////////////////////////////////////////////////////////////
//
// Do Mapping User Strings
//
//
// First walk the list adding up string sizes - to calculate our buff size
//
StringSize = 0; for (i = 0; i < MappingUserTableSize; i++) { pUsr = &MappingUsers[i];
StringSize = StringSize + lstrlen(pUsr->Name) + 1; }
//
// Make sure there is anything to replicate
//
if (StringSize > 0) { //
// Create our buffer to hold all of the garbage
//
MappingUserStrings = MIDL_user_allocate(StringSize * sizeof(TCHAR)); if (MappingUserStrings == NULL) { ASSERT(FALSE); return STATUS_NO_MEMORY; }
//
// Fill in the buffer
//
pStr = MappingUserStrings; for (i = 0; i < MappingUserTableSize; i++) { pUsr = &MappingUsers[i]; hr = StringCchCopy(pStr, StringSize, pUsr->Name); ASSERT(SUCCEEDED(hr)); pStr = &pStr[lstrlen(pUsr->Name) + 1]; } }
*pMappingUserStrings = MappingUserStrings; *pMappingUserStringSize = StringSize;
//////////////////////////////////////////////////////////////////
//
// Now Do Mapping Strings
//
//
// First walk the list adding up string sizes - to calculate our buff size
//
StringSize = 0; for (i = 0; i < MappingTableSize; i++) { pMapping = &Mappings[i];
StringSize = StringSize + lstrlen(pMapping->Name) + 1; StringSize = StringSize + lstrlen(pMapping->Comment) + 1; }
//
// Make sure there is anything to replicate
//
if (StringSize > 0) { //
// Create our buffer to hold all of the garbage
//
MappingStrings = MIDL_user_allocate(StringSize * sizeof(TCHAR)); if (MappingStrings == NULL) { ASSERT(FALSE);
//
// Clean up already alloc'd information
//
if (MappingUserStrings != NULL) MIDL_user_free(MappingUserStrings);
*pMappingUserStrings = NULL; *pMappingUserStringSize = 0;
return STATUS_NO_MEMORY; }
//
// Fill in the buffer
//
pStr = MappingStrings; for (i = 0; i < MappingTableSize; i++) { pMapping = &Mappings[i]; hr = StringCchCopy(pStr, StringSize, pMapping->Name); ASSERT(SUCCEEDED(hr)); pStr = &pStr[lstrlen(pMapping->Name) + 1]; hr = StringCchCopy(pStr, StringSize, pMapping->Comment); ASSERT(SUCCEEDED(hr)); pStr = &pStr[lstrlen(pMapping->Comment) + 1]; } }
*pMappingStrings = MappingStrings; *pMappingStringSize = StringSize;
return Status; } // MappingListStringsPack
/////////////////////////////////////////////////////////////////////////
VOID MappingListStringsUnpack ( ULONG MappingUserTableSize, PPACK_MAPPING_USER_RECORD MappingUsers, ULONG MappingUserStringSize, LPTSTR MappingUserStrings,
ULONG MappingTableSize, PPACK_MAPPING_RECORD Mappings,
ULONG MappingStringSize, LPTSTR MappingStrings )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ ULONG i; PPACK_MAPPING_USER_RECORD pUsr; PPACK_MAPPING_RECORD pMapping; TCHAR *pStr;
UNREFERENCED_PARAMETER(MappingUserStringSize); UNREFERENCED_PARAMETER(MappingStringSize);
#if DBG
if (TraceFlags & TRACE_FUNCTION_TRACE) dprintf(TEXT("MappingListStringsUnpack\n")); #endif
//
// First do license service strings
//
pStr = MappingUserStrings; for (i = 0; i < MappingUserTableSize; i++) { pUsr = &MappingUsers[i];
pUsr->Name = pStr;
//
// Move to end of current string
//
while (*pStr != TEXT('\0')) pStr++;
// now go past ending NULL
pStr++; }
//
// Now do license purchase strings
//
pStr = MappingStrings; for (i = 0; i < MappingTableSize; i++) { pMapping = &Mappings[i];
pMapping->Name = pStr;
//
// Move to end of current string
//
while (*pStr != TEXT('\0')) pStr++;
// now go past ending NULL
pStr++;
pMapping->Comment = pStr;
//
// Move to end of current string
//
while (*pStr != TEXT('\0')) pStr++;
// now go past ending NULL
pStr++; }
} // MappingListStringsUnpack
/////////////////////////////////////////////////////////////////////////
VOID MappingListLoad()
/*++
Routine Description:
Arguments:
None.
Return Value:
None.
--*/
{ BOOL ret; DWORD Version, DataSize; NTSTATUS Status = STATUS_SUCCESS; HANDLE hFile = NULL;
ULONG MappingUserTableSize; PPACK_MAPPING_USER_RECORD MappingUsers = NULL;
ULONG MappingUserStringSize; LPTSTR MappingUserStrings = NULL;
ULONG MappingTableSize; PPACK_MAPPING_RECORD Mappings = NULL;
ULONG MappingStringSize; LPTSTR MappingStrings = NULL;
MAPPING_FILE_HEADER FileHeader; DWORD BytesRead;
#if DBG
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_DATABASE)) dprintf(TEXT("LLS TRACE: MappingListLoad\n")); #endif
RtlEnterCriticalSection(&MappingFileLock);
//
// If nothing to load then get-out
//
if (!FileExists(MappingFileName)) goto MappingListLoadExit;
//
// Check the init header
//
Version = DataSize = 0; hFile = LlsFileCheck(MappingFileName, &Version, &DataSize ); if (hFile == NULL) { Status = GetLastError(); goto MappingListLoadExit; }
if ((Version != MAPPING_FILE_VERSION) || (DataSize != sizeof(MAPPING_FILE_HEADER))) { Status = STATUS_FILE_INVALID; goto MappingListLoadExit; }
//
// The init header checks out, so load the license header and data blocks
//
ret = ReadFile(hFile, &FileHeader, sizeof(MAPPING_FILE_HEADER), &BytesRead, NULL);
MappingUserTableSize = 0; MappingUserStringSize = 0; MappingTableSize = 0; MappingStringSize = 0;
if (ret) { //
// Run through and allocate space to read data blocks into
//
if (FileHeader.MappingUserTableSize != 0) { MappingUserTableSize = FileHeader.MappingUserTableSize / sizeof(PACK_MAPPING_USER_RECORD); MappingUsers = MIDL_user_allocate(FileHeader.MappingUserTableSize);
if ( MappingUsers == NULL ) { Status = STATUS_NO_MEMORY; goto MappingListLoadExit; } }
if (FileHeader.MappingUserStringSize != 0) { MappingUserStringSize = FileHeader.MappingUserStringSize / sizeof(TCHAR); MappingUserStrings = MIDL_user_allocate(FileHeader.MappingUserStringSize);
if ( MappingUserStrings == NULL ) { Status = STATUS_NO_MEMORY; goto MappingListLoadExit; } }
if (FileHeader.MappingTableSize != 0) { MappingTableSize = FileHeader.MappingTableSize / sizeof(PACK_MAPPING_RECORD); Mappings = MIDL_user_allocate(FileHeader.MappingTableSize);
if ( Mappings == NULL ) { Status = STATUS_NO_MEMORY; goto MappingListLoadExit; } }
if (FileHeader.MappingStringSize != 0) { MappingStringSize = FileHeader.MappingStringSize / sizeof(TCHAR); MappingStrings = MIDL_user_allocate(FileHeader.MappingStringSize);
if ( MappingStrings == NULL ) { Status = STATUS_NO_MEMORY; goto MappingListLoadExit; } }
}
if (ret && (FileHeader.MappingUserTableSize != 0) ) ret = ReadFile(hFile, MappingUsers, FileHeader.MappingUserTableSize, &BytesRead, NULL);
if (ret && (FileHeader.MappingUserStringSize != 0) ) ret = ReadFile(hFile, MappingUserStrings, FileHeader.MappingUserStringSize, &BytesRead, NULL);
if (ret && (FileHeader.MappingTableSize != 0) ) ret = ReadFile(hFile, Mappings, FileHeader.MappingTableSize, &BytesRead, NULL);
if (ret && (FileHeader.MappingStringSize != 0) ) ret = ReadFile(hFile, MappingStrings, FileHeader.MappingStringSize, &BytesRead, NULL);
if (!ret) { Status = GetLastError(); goto MappingListLoadExit; }
//
// Decrypt the data
//
Status = DeBlock(MappingUsers, FileHeader.MappingUserTableSize);
if (Status == STATUS_SUCCESS) Status = DeBlock(MappingUserStrings, FileHeader.MappingUserStringSize);
if (Status == STATUS_SUCCESS) Status = DeBlock(Mappings, FileHeader.MappingTableSize);
if (Status == STATUS_SUCCESS) Status = DeBlock(MappingStrings, FileHeader.MappingStringSize);
if (Status != STATUS_SUCCESS) goto MappingListLoadExit;
//
// Unpack the string data
//
MappingListStringsUnpack( MappingUserTableSize, MappingUsers, MappingUserStringSize, MappingUserStrings, MappingTableSize, Mappings, MappingStringSize, MappingStrings );
//
// Unpack the data
//
MappingListUnpack( MappingUserTableSize, MappingUsers, MappingTableSize, Mappings );
MappingListLoadExit:
if (hFile != NULL) CloseHandle(hFile);
RtlLeaveCriticalSection(&MappingFileLock);
//
// Run through our tables and clean them up
//
if (MappingUsers != NULL) MIDL_user_free(MappingUsers);
if (MappingUserStrings != NULL) MIDL_user_free(MappingUserStrings);
if (Mappings != NULL) MIDL_user_free(Mappings);
if (MappingStrings != NULL) MIDL_user_free(MappingStrings);
//
// If there was an error log it.
//
if (Status != STATUS_SUCCESS) LogEvent(LLS_EVENT_LOAD_MAPPING, 0, NULL, Status);
} // MappingListLoad
/////////////////////////////////////////////////////////////////////////
NTSTATUS MappingListSave()
/*++
Routine Description:
Arguments:
None.
Return Value:
None.
--*/
{ BOOL ret = TRUE; NTSTATUS Status = STATUS_SUCCESS; HANDLE hFile = NULL;
ULONG MappingUserTableSize; PPACK_MAPPING_USER_RECORD MappingUsers = NULL;
ULONG MappingUserStringSize; LPTSTR MappingUserStrings = NULL;
ULONG MappingTableSize; PPACK_MAPPING_RECORD Mappings = NULL;
ULONG MappingStringSize; LPTSTR MappingStrings = NULL;
MAPPING_FILE_HEADER FileHeader; DWORD BytesWritten;
#if DBG
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_DATABASE)) dprintf(TEXT("LLS TRACE: MappingListSave\n")); #endif
RtlEnterCriticalSection(&MappingFileLock);
RtlAcquireResourceExclusive(&MappingListLock, TRUE);
//
// If nothing to save then get-out
//
if (MappingListSize == 0) goto MappingListSaveExit;
//
// Pack the data
//
Status = MappingListPack( &MappingUserTableSize, &MappingUsers, &MappingTableSize, &Mappings ); if (Status != STATUS_SUCCESS) goto MappingListSaveExit;
//
// Now pack the String data
//
Status = MappingListStringsPack( MappingUserTableSize, MappingUsers, &MappingUserStringSize, &MappingUserStrings, MappingTableSize, Mappings, &MappingStringSize, &MappingStrings );
if (Status != STATUS_SUCCESS) goto MappingListSaveExit;
//
// Fill out the file header - sizes are byte sizes
//
FileHeader.MappingUserTableSize = MappingUserTableSize * sizeof(PACK_MAPPING_USER_RECORD); FileHeader.MappingUserStringSize = MappingUserStringSize * sizeof(TCHAR); FileHeader.MappingTableSize = MappingTableSize * sizeof(PACK_MAPPING_RECORD); FileHeader.MappingStringSize = MappingStringSize * sizeof(TCHAR);
//
// Encrypt the data before saving it out.
//
Status = EBlock(MappingUsers, FileHeader.MappingUserTableSize);
if (Status == STATUS_SUCCESS) Status = EBlock(MappingUserStrings, FileHeader.MappingUserStringSize);
if (Status == STATUS_SUCCESS) Status = EBlock(Mappings, FileHeader.MappingTableSize);
if (Status == STATUS_SUCCESS) Status = EBlock(MappingStrings, FileHeader.MappingStringSize);
if (Status != STATUS_SUCCESS) goto MappingListSaveExit;
//
// Save out the header record
//
hFile = LlsFileInit(MappingFileName, MAPPING_FILE_VERSION, sizeof(MAPPING_FILE_HEADER) ); if (hFile == NULL) { Status = GetLastError(); goto MappingListSaveExit; }
//
// Now write out all the data blocks
//
ret = WriteFile(hFile, &FileHeader, sizeof(MAPPING_FILE_HEADER), &BytesWritten, NULL);
if (ret && (MappingUsers != NULL) && (FileHeader.MappingUserTableSize != 0)) ret = WriteFile(hFile, MappingUsers, FileHeader.MappingUserTableSize, &BytesWritten, NULL);
if (ret && (MappingUserStrings != NULL) && (FileHeader.MappingUserStringSize != 0)) ret = WriteFile(hFile, MappingUserStrings, FileHeader.MappingUserStringSize, &BytesWritten, NULL);
if (ret && (Mappings != NULL) && (FileHeader.MappingTableSize != 0)) ret = WriteFile(hFile, Mappings, FileHeader.MappingTableSize, &BytesWritten, NULL);
if (ret && (MappingStrings != NULL) && (FileHeader.MappingStringSize != 0)) ret = WriteFile(hFile, MappingStrings, FileHeader.MappingStringSize, &BytesWritten, NULL);
if (!ret) Status = GetLastError();
MappingListSaveExit: RtlReleaseResource(&MappingListLock);
if (hFile != NULL) CloseHandle(hFile);
RtlLeaveCriticalSection(&MappingFileLock);
//
// Run through our tables and clean them up
//
if (MappingUsers != NULL) MIDL_user_free(MappingUsers);
if (MappingUserStrings != NULL) MIDL_user_free(MappingUserStrings);
if (Mappings != NULL) MIDL_user_free(Mappings);
if (MappingStrings != NULL) MIDL_user_free(MappingStrings);
//
// If there was an error log it.
//
if (Status != STATUS_SUCCESS) LogEvent(LLS_EVENT_SAVE_MAPPING, 0, NULL, Status);
return Status; } // MappingListSave
/////////////////////////////////////////////////////////////////////////
// User List
//
/////////////////////////////////////////////////////////////////////////
NTSTATUS UserListPack ( DWORD LastReplicated, ULONG UserLevel, ULONG *pUserTableSize, LPVOID *pUsers )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ NTSTATUS Status = STATUS_SUCCESS; LPVOID Users = NULL; ULONG i, j, k; ULONG TotalRecords = 0; PUSER_RECORD pUser;
#if DBG
if (TraceFlags & TRACE_FUNCTION_TRACE) dprintf(TEXT("LLS TRACE: UserListPack\n")); #endif
ASSERT(pUsers != NULL); ASSERT(pUserTableSize != NULL);
*pUsers = NULL; *pUserTableSize = 0;
//
// Now walk our tree and figure out how many records we must send.
//
i = 0; TotalRecords = 0; while (i < UserListNumEntries) { pUser = LLSGetElementGenericTable(&UserList, i);
if (pUser != NULL) { //
// Walk each service under each user
//
RtlEnterCriticalSection(&pUser->ServiceTableLock);
for (j = 0; j < pUser->ServiceTableSize; j++) if ( (pUser->Services[j].AccessCount > 0) || (pUser->Services[j].LastAccess > LastReplicated) ) TotalRecords++;
RtlLeaveCriticalSection(&pUser->ServiceTableLock); }
i++; }
#if DBG
if (TraceFlags & TRACE_REPLICATION) dprintf(TEXT(" LLS Packing %lu User Records\n"), TotalRecords); #endif
//
// Make sure there is anything to replicate
//
if (TotalRecords > 0) { //
// Create our buffer to hold all of the garbage
//
Users = MIDL_user_allocate(TotalRecords * ( UserLevel ? sizeof(REPL_USER_RECORD_1) : sizeof(REPL_USER_RECORD_0) ) ); if (Users == NULL) { ASSERT(FALSE); return STATUS_NO_MEMORY; }
//
// Fill in the buffer - walk the user tree
//
i = 0; j = 0; while ((i < UserListNumEntries) && (j < TotalRecords)) { pUser = LLSGetElementGenericTable(&UserList, i);
if (pUser != NULL) { //
// Walk each service under each user
//
k = 0; RtlEnterCriticalSection(&pUser->ServiceTableLock); while (k < pUser->ServiceTableSize) { if ( (pUser->Services[k].AccessCount > 0) || (pUser->Services[k].LastAccess > LastReplicated) ) { if ( 0 == UserLevel ) { ((PREPL_USER_RECORD_0)Users)[j].Name = pUser->UserID; ((PREPL_USER_RECORD_0)Users)[j].Service = pUser->Services[k].Service->Index; ((PREPL_USER_RECORD_0)Users)[j].AccessCount = pUser->Services[k].AccessCount; ((PREPL_USER_RECORD_0)Users)[j].LastAccess = pUser->Services[k].LastAccess; } else { ((PREPL_USER_RECORD_1)Users)[j].Name = pUser->UserID; ((PREPL_USER_RECORD_1)Users)[j].Service = pUser->Services[k].Service->Index; ((PREPL_USER_RECORD_1)Users)[j].AccessCount = pUser->Services[k].AccessCount; ((PREPL_USER_RECORD_1)Users)[j].LastAccess = pUser->Services[k].LastAccess; ((PREPL_USER_RECORD_1)Users)[j].Flags = pUser->Flags; }
//
// Reset access count so we don't increment forever
//
if (LastReplicated != 0) pUser->Services[k].AccessCount = 0;
j++; }
k++; } RtlLeaveCriticalSection(&pUser->ServiceTableLock); }
i++; } } // User Records
#if DBG
if (TraceFlags & TRACE_REPLICATION) dprintf(TEXT("UserListPack: [%lu]\n"), TotalRecords); #endif
*pUsers = Users; *pUserTableSize = TotalRecords; return Status; } // UserListPack
/////////////////////////////////////////////////////////////////////////
VOID UserListUnpack ( ULONG ServiceTableSize, PREPL_SERVICE_RECORD Services,
ULONG ServerTableSize, PREPL_SERVER_RECORD Servers,
ULONG ServerServiceTableSize, PREPL_SERVER_SERVICE_RECORD ServerServices,
ULONG UserLevel, ULONG UserTableSize, LPVOID Users )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ NTSTATUS Status = STATUS_SUCCESS; ULONG i; PREPL_USER_RECORD_0 pReplUser0 = NULL; PREPL_USER_RECORD_1 pReplUser1 = NULL; PADD_CACHE pAdd = NULL; PADD_CACHE tAdd = NULL; PADD_CACHE lAdd = NULL; ULONG CacheSize = 0; ULONG DataLength; LPTSTR NewName; HRESULT hr;
UNREFERENCED_PARAMETER(ServiceTableSize); UNREFERENCED_PARAMETER(ServerTableSize); UNREFERENCED_PARAMETER(Servers); UNREFERENCED_PARAMETER(ServerServiceTableSize); UNREFERENCED_PARAMETER(ServerServices);
#if DBG
if (TraceFlags & (TRACE_REPLICATION | TRACE_FUNCTION_TRACE)) dprintf(TEXT("UserListUnpack: [%lu]\n"), UserTableSize); #endif
//
// Walk User table. First fixup service pointers to our local service
// table. Next create a big add cache list to dump onto our add-cache
// queue.
//
for (i = 0; i < UserTableSize; i++) { //
// Update Index
//
if ( 0 == UserLevel ) { pReplUser0 = &( (PREPL_USER_RECORD_0) Users)[i]; pReplUser0->Service = Services[pReplUser0->Service].Index;
//
// Validate the user name.
//
// NB : Strange this code is necessary, but occasionally the names
// received via replication are invalid. Maintain this code
// for safety until the original problem is completely fixed.
//
if (!ValidateDN(pReplUser0->Name)) { //
// TBD : Log event noting rejected name.
//
#if DBG
dprintf(TEXT("LS: Rejecting invalid user name = \"%s\"\n"), pReplUser0->Name); #endif
continue; } } else { pReplUser1 = &( (PREPL_USER_RECORD_1) Users)[i]; pReplUser1->Service = Services[pReplUser1->Service].Index;
//
// Validate the user name.
//
// NB : Strange this code is necessary, but occasionally the names
// received via replication are invalid. Maintain this code
// for safety until the original problem is completely fixed.
//
if (!ValidateDN(pReplUser1->Name)) { //
// TBD : Log event noting rejected name.
//
#if DBG
dprintf(TEXT("LS: Rejecting invalid user name = \"%s\"\n"), pReplUser1->Name); #endif
continue; } }
//
// Now create Add Cache object
//
tAdd = LocalAlloc(LPTR, sizeof(ADD_CACHE)); if (tAdd != NULL) { if ( 0 == UserLevel ) { DataLength = (lstrlen(pReplUser0->Name) + 1) * sizeof(TCHAR); } else { DataLength = (lstrlen(pReplUser1->Name) + 1) * sizeof(TCHAR); }
NewName = LocalAlloc( LPTR, DataLength);
if (NewName == NULL) { LocalFree(tAdd); ASSERT(FALSE); } else { tAdd->Data = NewName; tAdd->DataType = DATA_TYPE_USERNAME; tAdd->DataLength = DataLength;
if ( 0 == UserLevel ) { hr = StringCbCopy( NewName, DataLength, pReplUser0->Name ); ASSERT(SUCCEEDED(hr)); tAdd->AccessCount = pReplUser0->AccessCount; tAdd->LastAccess = pReplUser0->LastAccess; tAdd->Flags = LLS_FLAG_SUITE_AUTO;
RtlAcquireResourceShared(&MasterServiceListLock, TRUE); tAdd->Service = MasterServiceTable[pReplUser0->Service]; RtlReleaseResource(&MasterServiceListLock); } else { hr = StringCbCopy( NewName, DataLength, pReplUser1->Name ); ASSERT(SUCCEEDED(hr)); tAdd->AccessCount = pReplUser1->AccessCount; tAdd->LastAccess = pReplUser1->LastAccess; tAdd->Flags = pReplUser1->Flags & ( LLS_FLAG_SUITE_USE | LLS_FLAG_SUITE_AUTO );
RtlAcquireResourceShared(&MasterServiceListLock, TRUE); tAdd->Service = MasterServiceTable[pReplUser1->Service]; RtlReleaseResource(&MasterServiceListLock); }
//
// Now add it to our cache
//
tAdd->prev = pAdd; pAdd = tAdd;
//
// Keep track of first on (bottom on stack) so we can append
// it onto the real add cache.
//
if (lAdd == NULL) lAdd = pAdd;
CacheSize++; } } else { ASSERT(FALSE); }
if (i % 100 == 0) ReportStatusToSCMgr( SERVICE_START_PENDING, NO_ERROR, NSERVICEWAITHINT); }
//
// Now that we've walked through all the users - update the actual
// Add Cache.
//
if (pAdd != NULL) { RtlEnterCriticalSection(&AddCacheLock); lAdd->prev = AddCache; AddCache = pAdd; AddCacheSize += CacheSize; RtlLeaveCriticalSection(&AddCacheLock);
//
// Now must signal the event so we can pull off the new record.
//
Status = NtSetEvent( LLSAddCacheEvent, NULL ); ASSERT(NT_SUCCESS(Status));
}
} // UserListUnpack
//
// Illegal user/domain characters.
//
#define CTRL_CHARS_0 TEXT( "\001\002\003\004\005\006\007")
#define CTRL_CHARS_1 TEXT("\010\011\012\013\014\015\016\017")
#define CTRL_CHARS_2 TEXT("\020\021\022\023\024\025\026\027")
#define CTRL_CHARS_3 TEXT("\030\031\032\033\034\035\036\037")
#define CTRL_CHARS_STR CTRL_CHARS_0 CTRL_CHARS_1 CTRL_CHARS_2 CTRL_CHARS_3
#define ILLEGAL_NAME_CHARS_STR TEXT("\"/\\[]:|<>+=;,?") CTRL_CHARS_STR
static const TCHAR szUserIllegalChars[] = ILLEGAL_NAME_CHARS_STR TEXT("*"); static const TCHAR szDomainIllegalChars[] = ILLEGAL_NAME_CHARS_STR TEXT("*") TEXT(" ");
/////////////////////////////////////////////////////////////////////////
BOOL ValidateDN ( LPTSTR pszDN )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ //
// NB : This code understands only NT4 usernames at present.
//
TCHAR szDN[MAX_USERNAME_LENGTH + MAX_DOMAINNAME_LENGTH + 2]; LPTSTR pszUserName; LPTSTR pszDomainName; LPTSTR pszBSlash; SIZE_T ccUserNameLength; SIZE_T ccDomainNameLength;
if (pszDN == NULL || !*pszDN) { return FALSE; }
//
// Use a local buffer for character replacement during check.
//
if (lstrlen(pszDN) < (MAX_USERNAME_LENGTH + MAX_DOMAINNAME_LENGTH + 2)) { lstrcpyn(szDN, pszDN, MAX_USERNAME_LENGTH + MAX_DOMAINNAME_LENGTH + 2); } else { return FALSE; }
pszBSlash = STRRCHR(szDN, TEXT('\\'));
if (pszBSlash == NULL) { return FALSE; }
//
// Isolate user/domain names.
//
*pszBSlash = TEXT('\0');
pszUserName = pszBSlash + 1; pszDomainName = szDN;
ccUserNameLength = lstrlen(pszUserName); ccDomainNameLength = pszBSlash - pszDomainName;
//
// Check user/domain name length and the existence of invalid chars.
//
if (ccUserNameLength && ccUserNameLength <= MAX_USERNAME_LENGTH) { if (STRCSPN(pszUserName, szUserIllegalChars) == ccUserNameLength) { if (ccDomainNameLength <= MAX_DOMAINNAME_LENGTH) { if (STRCSPN(pszDomainName, szDomainIllegalChars) == ccDomainNameLength) { return TRUE; } } } }
return FALSE; }
/////////////////////////////////////////////////////////////////////////
NTSTATUS UserListStringsPack ( ULONG UserLevel,
ULONG UserTableSize, LPVOID Users,
ULONG *pUserStringSize, LPTSTR *pUserStrings )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ NTSTATUS Status = STATUS_SUCCESS; ULONG i; ULONG StringSize; LPTSTR UserStrings = NULL; TCHAR *pStr; HRESULT hr;
#if DBG
if (TraceFlags & TRACE_FUNCTION_TRACE) dprintf(TEXT("UserListStringsPack\n")); #endif
ASSERT(pUserStrings != NULL); ASSERT(pUserStringSize != NULL);
*pUserStrings = NULL; *pUserStringSize = 0;
//
// First walk the list adding up string sizes - to calculate our buff size
//
StringSize = 0; for (i = 0; i < UserTableSize; i++) { if ( 0 == UserLevel ) { StringSize += 1 + lstrlen( ((PREPL_USER_RECORD_0) Users)[i].Name ); } else { StringSize += 1 + lstrlen( ((PREPL_USER_RECORD_1) Users)[i].Name ); } }
//
// Make sure there is anything to replicate
//
if (StringSize > 0) { //
// Create our buffer to hold all of the garbage
//
UserStrings = MIDL_user_allocate(StringSize * sizeof(TCHAR)); if (UserStrings == NULL) { ASSERT(FALSE); return STATUS_NO_MEMORY; }
//
// Fill in the buffer
//
pStr = UserStrings; for (i = 0; i < UserTableSize; i++) { if ( 0 == UserLevel ) { hr = StringCchCopy( pStr, StringSize, ((PREPL_USER_RECORD_0) Users)[i].Name ); ASSERT(SUCCEEDED(hr)); } else { hr = StringCchCopy( pStr, StringSize, ((PREPL_USER_RECORD_1) Users)[i].Name ); ASSERT(SUCCEEDED(hr)); }
pStr += 1 + lstrlen( pStr ); } }
*pUserStrings = UserStrings; *pUserStringSize = StringSize;
return Status; } // UserListStringsPack
/////////////////////////////////////////////////////////////////////////
VOID UserListStringsUnpack ( ULONG UserLevel,
ULONG UserTableSize, LPVOID Users,
ULONG UserStringSize, LPTSTR UserStrings )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ ULONG i; TCHAR *pStr;
UNREFERENCED_PARAMETER(UserStringSize);
#if DBG
if (TraceFlags & TRACE_FUNCTION_TRACE) dprintf(TEXT("UserListStringsUnpack\n")); #endif
pStr = UserStrings; for (i = 0; i < UserTableSize; i++) { if ( 0 == UserLevel ) { ((PREPL_USER_RECORD_0) Users)[i].Name = pStr; } else { ((PREPL_USER_RECORD_1) Users)[i].Name = pStr; }
//
// Move to end of current string
//
while (*pStr != TEXT('\0')) pStr++;
// now go past ending NULL
pStr++; }
} // UserListStringsUnpack
/////////////////////////////////////////////////////////////////////////
// Service List
//
/////////////////////////////////////////////////////////////////////////
NTSTATUS ServiceListPack ( ULONG *pServiceTableSize, PREPL_SERVICE_RECORD *pServices )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ NTSTATUS Status = STATUS_SUCCESS; PREPL_SERVICE_RECORD Services = NULL; ULONG i; ULONG TotalRecords = 0; PMASTER_SERVICE_RECORD pService;
#if DBG
if (TraceFlags & TRACE_FUNCTION_TRACE) dprintf(TEXT("LLS TRACE: ServiceListPack\n")); #endif
ASSERT(pServices != NULL); ASSERT(pServiceTableSize != NULL); *pServices = NULL; *pServiceTableSize = 0;
TotalRecords = MasterServiceListSize;
//
// Make sure there is anything to replicate
//
if (TotalRecords > 0) { //
// Create our buffer to hold all of the garbage
//
Services = MIDL_user_allocate(TotalRecords * sizeof(REPL_SERVICE_RECORD)); if (Services == NULL) { ASSERT(FALSE); return STATUS_NO_MEMORY; }
//
// Fill in the buffer - walk the user tree
//
for (i = 0; i < MasterServiceListSize; i++) { pService = MasterServiceTable[i];
Services[i].Name = pService->Name; Services[i].FamilyName = pService->Family->Name; Services[i].Version = pService->Version; Services[i].Index = pService->Index; } }
#if DBG
if (TraceFlags & TRACE_REPLICATION) dprintf(TEXT("ServiceListPack: [%lu]\n"), TotalRecords); #endif
*pServices = Services; *pServiceTableSize = TotalRecords; return Status; } // ServiceListPack
/////////////////////////////////////////////////////////////////////////
VOID ServiceListUnpack ( ULONG ServiceTableSize, PREPL_SERVICE_RECORD Services,
ULONG ServerTableSize, PREPL_SERVER_RECORD Servers,
ULONG ServerServiceTableSize, PREPL_SERVER_SERVICE_RECORD ServerServices )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ ULONG i, j; PMASTER_SERVICE_RECORD pService; PREPL_SERVICE_RECORD pSvc;
UNREFERENCED_PARAMETER(ServerTableSize); UNREFERENCED_PARAMETER(Servers); UNREFERENCED_PARAMETER(ServerServiceTableSize); UNREFERENCED_PARAMETER(ServerServices);
#if DBG
if (TraceFlags & (TRACE_REPLICATION | TRACE_FUNCTION_TRACE)) dprintf(TEXT("ServiceListUnpack: [%lu]\n"), ServiceTableSize); #endif
//
// Walk services table, adding any new services to our local table.
// Fix up the index pointers to match our local services.
//
RtlAcquireResourceExclusive(&MasterServiceListLock, TRUE);
for (i = 0; i < ServiceTableSize; i++) { pSvc = &Services[i]; pService = MasterServiceListAdd(pSvc->FamilyName, pSvc->Name, pSvc->Version );
if (pService != NULL) { pSvc->Index = pService->Index;
//
// In case this got added from the local service list table and we
// didn't have a version # yet.
//
if ( (pService->Version == 0) && (pSvc->Version != 0) ) { PMASTER_SERVICE_ROOT ServiceRoot = NULL;
//
// Fixup next pointer chain
//
ServiceRoot = pService->Family; j = 0; while ((j < ServiceRoot->ServiceTableSize) && (MasterServiceTable[ServiceRoot->Services[j]]->Version < pSvc->Version)) j++;
pService->next = 0; pService->Version = pSvc->Version; if (j > 0) { if (MasterServiceTable[ServiceRoot->Services[j - 1]]->next == pService->Index + 1) pService->next = 0; else pService->next = MasterServiceTable[ServiceRoot->Services[j - 1]]->next;
if (MasterServiceTable[ServiceRoot->Services[j - 1]] != pService) MasterServiceTable[ServiceRoot->Services[j - 1]]->next = pService->Index + 1;
}
// Resort it in order of the versions
qsort((void *) ServiceRoot->Services, (size_t) ServiceRoot->ServiceTableSize, sizeof(ULONG), MServiceRecordCompare); }
} else { ASSERT(FALSE); pSvc->Index = 0; }
if (i % 100 == 0) ReportStatusToSCMgr( SERVICE_START_PENDING, NO_ERROR, NSERVICEWAITHINT); }
RtlReleaseResource(&MasterServiceListLock);
} // ServiceListUnpack
/////////////////////////////////////////////////////////////////////////
NTSTATUS ServiceListStringsPack ( ULONG ServiceTableSize, PREPL_SERVICE_RECORD Services,
ULONG *pServiceStringSize, LPTSTR *pServiceStrings )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ NTSTATUS Status = STATUS_SUCCESS; ULONG i; ULONG StringSize; PREPL_SERVICE_RECORD pService; LPTSTR ServiceStrings = NULL; TCHAR *pStr; HRESULT hr;
#if DBG
if (TraceFlags & TRACE_FUNCTION_TRACE) dprintf(TEXT("ServiceListStringsPack\n")); #endif
ASSERT(pServiceStrings != NULL); ASSERT(pServiceStringSize != NULL);
*pServiceStrings = NULL; *pServiceStringSize = 0;
//
// First walk the list adding up string sizes - to calculate our buff size
//
StringSize = 0; for (i = 0; i < ServiceTableSize; i++) { pService = &Services[i];
StringSize = StringSize + lstrlen(pService->Name) + 1; StringSize = StringSize + lstrlen(pService->FamilyName) + 1; }
//
// Make sure there is anything to replicate
//
if (StringSize > 0) { //
// Create our buffer to hold all of the garbage
//
ServiceStrings = MIDL_user_allocate(StringSize * sizeof(TCHAR)); if (ServiceStrings == NULL) { ASSERT(FALSE); return STATUS_NO_MEMORY; }
//
// Fill in the buffer
//
pStr = ServiceStrings; for (i = 0; i < ServiceTableSize; i++) { pService = &Services[i];
hr = StringCchCopy(pStr, StringSize, pService->Name); ASSERT(SUCCEEDED(hr)); pStr = &pStr[lstrlen(pService->Name) + 1];
hr = StringCchCopy(pStr, StringSize, pService->FamilyName); ASSERT(SUCCEEDED(hr)); pStr = &pStr[lstrlen(pService->FamilyName) + 1]; } }
*pServiceStrings = ServiceStrings; *pServiceStringSize = StringSize;
return Status; } // ServiceListStringsPack
/////////////////////////////////////////////////////////////////////////
VOID ServiceListStringsUnpack ( ULONG ServiceTableSize, PREPL_SERVICE_RECORD Services,
ULONG ServiceStringSize, LPTSTR ServiceStrings )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ ULONG i; PREPL_SERVICE_RECORD pService; TCHAR *pStr;
UNREFERENCED_PARAMETER(ServiceStringSize);
#if DBG
if (TraceFlags & TRACE_FUNCTION_TRACE) dprintf(TEXT("ServiceListStringsUnpack\n")); #endif
pStr = ServiceStrings; for (i = 0; i < ServiceTableSize; i++) { pService = &Services[i];
pService->Name = pStr;
//
// Move to end of current string
//
while (*pStr != TEXT('\0')) pStr++;
// now go past ending NULL
pStr++;
pService->FamilyName = pStr;
//
// Move to end of current string
//
while (*pStr != TEXT('\0')) pStr++;
// now go past ending NULL
pStr++; }
} // ServiceListStringsUnpack
/////////////////////////////////////////////////////////////////////////
// Server List
//
/////////////////////////////////////////////////////////////////////////
NTSTATUS ServerListPack ( ULONG *pServerTableSize, PREPL_SERVER_RECORD *pServers )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ NTSTATUS Status = STATUS_SUCCESS; PREPL_SERVER_RECORD Servers = NULL; ULONG i; ULONG TotalRecords = 0; PSERVER_RECORD pServer;
#if DBG
if (TraceFlags & TRACE_FUNCTION_TRACE) dprintf(TEXT("LLS TRACE: ServerListPack\n")); #endif
ASSERT(pServers != NULL); ASSERT(pServerTableSize != NULL);
*pServers = NULL; *pServerTableSize = 0;
TotalRecords = ServerListSize;
//
// Make sure there is anything to replicate
//
if (TotalRecords > 0) { //
// Create our buffer to hold all of the garbage
//
Servers = MIDL_user_allocate(TotalRecords * sizeof(REPL_SERVER_RECORD)); if (Servers == NULL) { ASSERT(FALSE); return STATUS_NO_MEMORY; }
//
// Fill in the buffer - walk the user tree
//
for (i = 0; i < ServerListSize; i++) { pServer = ServerTable[i];
Servers[i].Name = pServer->Name; Servers[i].MasterServer = pServer->MasterServer; Servers[i].Index = pServer->Index; } }
#if DBG
if (TraceFlags & TRACE_REPLICATION) dprintf(TEXT("ServerListPack: [%lu]\n"), TotalRecords); #endif
*pServers = Servers;; *pServerTableSize = TotalRecords; return Status; } // ServerListPack
/////////////////////////////////////////////////////////////////////////
VOID ServerListUnpack ( ULONG ServiceTableSize, PREPL_SERVICE_RECORD Services,
ULONG ServerTableSize, PREPL_SERVER_RECORD Servers,
ULONG ServerServiceTableSize, PREPL_SERVER_SERVICE_RECORD ServerServices )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ ULONG i; PSERVER_RECORD pServer; PREPL_SERVER_RECORD pSrv; TCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1]; HRESULT hr;
UNREFERENCED_PARAMETER(ServiceTableSize); UNREFERENCED_PARAMETER(Services); UNREFERENCED_PARAMETER(ServerServiceTableSize); UNREFERENCED_PARAMETER(ServerServices);
#if DBG
if (TraceFlags & (TRACE_REPLICATION | TRACE_FUNCTION_TRACE)) dprintf(TEXT("ServerListUnpack: [%lu]\n"), ServerTableSize); #endif
ComputerName[0] = 0;
//
// Walk server table, adding any new servers to our local table.
// Fix up the index pointers to match our local table and re-fix
// Service table pointers.
//
RtlEnterCriticalSection(&ConfigInfoLock);
if (ConfigInfo.ComputerName != NULL) { hr = StringCbCopy(ComputerName, sizeof(ComputerName), ConfigInfo.ComputerName); ASSERT(SUCCEEDED(hr)); }
RtlLeaveCriticalSection(&ConfigInfoLock);
RtlAcquireResourceExclusive(&ServerListLock, TRUE);
for (i = 0; i < ServerTableSize; i++) { pSrv = &Servers[i];
if (pSrv->MasterServer != 0) pServer = ServerListAdd(pSrv->Name, Servers[pSrv->MasterServer - 1].Name); else pServer = ServerListAdd(pSrv->Name, ComputerName);
if (pServer != NULL) pSrv->Index = pServer->Index; else { ASSERT(FALSE); pSrv->Index = 0; }
if (i % 100 == 0) ReportStatusToSCMgr( SERVICE_START_PENDING, NO_ERROR, NSERVICEWAITHINT); }
RtlReleaseResource(&ServerListLock);
} // ServerListUnpack
/////////////////////////////////////////////////////////////////////////
NTSTATUS ServerServiceListPack ( ULONG *pServerServiceTableSize, PREPL_SERVER_SERVICE_RECORD *pServerServices )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ NTSTATUS Status = STATUS_SUCCESS; PREPL_SERVER_SERVICE_RECORD ServerServices = NULL; ULONG i, j, k; ULONG TotalRecords = 0; PSERVER_RECORD pServer;
#if DBG
if (TraceFlags & TRACE_FUNCTION_TRACE) dprintf(TEXT("LLS TRACE: ServerServiceListPack\n")); #endif
ASSERT(pServerServices != NULL); ASSERT(pServerServiceTableSize != NULL);
*pServerServices = NULL; *pServerServiceTableSize = 0;
//
// Walk the ServerList and find all ServiceRecords
for (i = 0; i < ServerListSize; i++) TotalRecords += ServerTable[i]->ServiceTableSize;
//
// Make sure there is anything to replicate
//
if (TotalRecords > 0) { //
// Create our buffer to hold all of the garbage
//
ServerServices = MIDL_user_allocate(TotalRecords * sizeof(REPL_SERVER_SERVICE_RECORD)); if (ServerServices == NULL) { ASSERT(FALSE); return STATUS_NO_MEMORY; }
//
// Fill in the buffer - walk the user tree
//
k = 0; for (i = 0; i < ServerListSize; i++) { pServer = ServerTable[i];
for (j = 0; j < pServer->ServiceTableSize; j++) { ServerServices[k].Server = pServer->Index; ServerServices[k].Service = pServer->Services[j]->Service; ServerServices[k].MaxSessionCount = pServer->Services[j]->MaxSessionCount; ServerServices[k].MaxSetSessionCount = pServer->Services[j]->MaxSetSessionCount; ServerServices[k].HighMark = pServer->Services[j]->HighMark; k++; } } }
#if DBG
if (TraceFlags & TRACE_REPLICATION) dprintf(TEXT("ServerServiceListPack: [%lu]\n"), TotalRecords); #endif
*pServerServices = ServerServices; *pServerServiceTableSize = TotalRecords; return Status; } // ServerServiceListPack
/////////////////////////////////////////////////////////////////////////
VOID ServerServiceListUnpack ( ULONG ServiceTableSize, PREPL_SERVICE_RECORD Services,
ULONG ServerTableSize, PREPL_SERVER_RECORD Servers,
ULONG ServerServiceTableSize, PREPL_SERVER_SERVICE_RECORD ServerServices )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ ULONG i; PSERVER_RECORD pServer; PREPL_SERVER_SERVICE_RECORD pSrv; PSERVER_SERVICE_RECORD pService; PMASTER_SERVICE_RECORD pMasterService;
UNREFERENCED_PARAMETER(ServiceTableSize); UNREFERENCED_PARAMETER(ServerTableSize);
#if DBG
if (TraceFlags & (TRACE_REPLICATION | TRACE_FUNCTION_TRACE)) dprintf(TEXT("ServerServiceListUnpack: [%lu]\n"), ServerServiceTableSize); #endif
//
// Walk server table, adding any new servers to our local table.
// Fix up the index pointers to match our local table and re-fix
// Service table pointers.
//
RtlAcquireResourceExclusive(&ServerListLock, TRUE); RtlAcquireResourceShared(&MasterServiceListLock, TRUE);
for (i = 0; i < ServerServiceTableSize; i++) { pSrv = &ServerServices[i]; pServer = ServerListFind(Servers[pSrv->Server - 1].Name); ASSERT(pServer != NULL);
if (pServer != NULL) { BOOL bReplaceValues;
pService = ServerServiceListFind(Services[pSrv->Service].Name, pServer->ServiceTableSize, pServer->Services); bReplaceValues = ( NULL != pService );
pService = ServerServiceListAdd(Services[pSrv->Service].Name, Services[pSrv->Service].Index, &pServer->ServiceTableSize, &pServer->Services);
ASSERT(pService != NULL);
if (pService != NULL) { //
// Remove any old info
//
pMasterService = MasterServiceTable[Services[pSrv->Service].Index]; if ( bReplaceValues ) { pMasterService->MaxSessionCount -= pService->MaxSessionCount; pMasterService->HighMark -= pService->HighMark; }
//
// Now update new info
//
pService->MaxSessionCount = pSrv->MaxSessionCount; pService->HighMark = pSrv->HighMark; pMasterService->MaxSessionCount += pService->MaxSessionCount; pMasterService->HighMark += pService->HighMark; } }
if (i % 100 == 0) ReportStatusToSCMgr( SERVICE_START_PENDING, NO_ERROR, NSERVICEWAITHINT); }
RtlReleaseResource(&MasterServiceListLock); RtlReleaseResource(&ServerListLock);
} // ServerServiceListUnpack
/////////////////////////////////////////////////////////////////////////
NTSTATUS ServerListStringsPack ( ULONG ServerTableSize, PREPL_SERVER_RECORD Servers,
ULONG *pServerStringSize, LPTSTR *pServerStrings )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ NTSTATUS Status = STATUS_SUCCESS; ULONG i; ULONG StringSize; PREPL_SERVER_RECORD pServer; LPTSTR ServerStrings = NULL; TCHAR *pStr; HRESULT hr;
#if DBG
if (TraceFlags & TRACE_FUNCTION_TRACE) dprintf(TEXT("ServerListStringsPack\n")); #endif
ASSERT(pServerStrings != NULL); ASSERT(pServerStringSize != NULL);
*pServerStrings = NULL; *pServerStringSize = 0;
//
// First walk the list adding up string sizes - to calculate our buff size
//
StringSize = 0; for (i = 0; i < ServerTableSize; i++) { pServer = &Servers[i];
StringSize = StringSize + lstrlen(pServer->Name) + 1; }
//
// Make sure there is anything to replicate
//
if (StringSize > 0) { //
// Create our buffer to hold all of the garbage
//
ServerStrings = MIDL_user_allocate(StringSize * sizeof(TCHAR)); if (ServerStrings == NULL) { ASSERT(FALSE); return STATUS_NO_MEMORY; }
//
// Fill in the buffer
//
pStr = ServerStrings; for (i = 0; i < ServerTableSize; i++) { pServer = &Servers[i];
hr = StringCchCopy(pStr, StringSize, pServer->Name); ASSERT(SUCCEEDED(hr)); pStr = &pStr[lstrlen(pServer->Name) + 1]; } }
*pServerStrings = ServerStrings; *pServerStringSize = StringSize;
return Status; } // ServerListStringsPack
/////////////////////////////////////////////////////////////////////////
VOID ServerListStringsUnpack ( ULONG ServerTableSize, PREPL_SERVER_RECORD Servers,
ULONG ServerStringSize, LPTSTR ServerStrings )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ ULONG i; PREPL_SERVER_RECORD pServer; TCHAR *pStr;
UNREFERENCED_PARAMETER(ServerStringSize);
#if DBG
if (TraceFlags & TRACE_FUNCTION_TRACE) dprintf(TEXT("ServerListStringsUnpack\n")); #endif
//
// First do license service strings
//
pStr = ServerStrings; for (i = 0; i < ServerTableSize; i++) { pServer = &Servers[i];
pServer->Name = pStr;
//
// Move to end of current string
//
while (*pStr != TEXT('\0')) pStr++;
// now go past ending NULL
pStr++; }
} // ServerListStringsUnpack
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
NTSTATUS PackAll ( DWORD LastReplicated,
ULONG *pServiceTableSize, PREPL_SERVICE_RECORD *pServices,
ULONG *pServerTableSize, PREPL_SERVER_RECORD *pServers,
ULONG *pServerServiceTableSize, PREPL_SERVER_SERVICE_RECORD *pServerServices,
ULONG UserLevel, ULONG *pUserTableSize, LPVOID *pUsers )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ NTSTATUS Status = STATUS_SUCCESS;
#if DBG
if (TraceFlags & TRACE_FUNCTION_TRACE) dprintf(TEXT("LLS TRACE: PackAll\n")); #endif
//
// We need to grab all the locks here so that a service isn't snuck in
// behind our backs - since these tables interact with each other.
//
RtlAcquireResourceExclusive(&UserListLock, TRUE); RtlAcquireResourceShared(&MasterServiceListLock, TRUE); RtlAcquireResourceShared(&ServerListLock, TRUE);
Status = ServiceListPack(pServiceTableSize, pServices); if (Status != STATUS_SUCCESS) goto PackAllExit;
Status = ServerListPack(pServerTableSize, pServers); if (Status != STATUS_SUCCESS) goto PackAllExit;
Status = ServerServiceListPack(pServerServiceTableSize, pServerServices); if (Status != STATUS_SUCCESS) goto PackAllExit;
Status = UserListPack(LastReplicated, UserLevel, pUserTableSize, pUsers); if (Status != STATUS_SUCCESS) goto PackAllExit;
//
// Now update our last used time
//
LastUsedTime = DateSystemGet() + 1;
PackAllExit: RtlReleaseResource(&ServerListLock); RtlReleaseResource(&MasterServiceListLock); RtlReleaseResource(&UserListLock);
return Status; } // PackAll
/////////////////////////////////////////////////////////////////////////
VOID UnpackAll ( ULONG ServiceTableSize, PREPL_SERVICE_RECORD Services,
ULONG ServerTableSize, PREPL_SERVER_RECORD Servers,
ULONG ServerServiceTableSize, PREPL_SERVER_SERVICE_RECORD ServerServices,
ULONG UserLevel, ULONG UserTableSize, LPVOID Users )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ #if DBG
if (TraceFlags & TRACE_FUNCTION_TRACE) dprintf(TEXT("LLS TRACE: UnpackAll\n")); #endif
ServiceListUnpack(ServiceTableSize, Services, ServerTableSize, Servers, ServerServiceTableSize, ServerServices); ServerListUnpack(ServiceTableSize, Services, ServerTableSize, Servers, ServerServiceTableSize, ServerServices); ServerServiceListUnpack(ServiceTableSize, Services, ServerTableSize, Servers, ServerServiceTableSize, ServerServices); UserListUnpack(ServiceTableSize, Services, ServerTableSize, Servers, ServerServiceTableSize, ServerServices, UserLevel, UserTableSize, Users); } // UnpackAll
/////////////////////////////////////////////////////////////////////////
VOID LLSDataLoad()
/*++
Routine Description:
Arguments:
None.
Return Value:
None.
--*/
{ BOOL ret; DWORD Version, DataSize; NTSTATUS Status = STATUS_SUCCESS; HANDLE hFile = NULL;
ULONG ServiceTableSize = 0; PREPL_SERVICE_RECORD Services = NULL;
ULONG ServiceStringSize; LPTSTR ServiceStrings = NULL;
ULONG ServerServiceTableSize = 0; PREPL_SERVER_SERVICE_RECORD ServerServices = NULL;
ULONG ServerTableSize = 0; PREPL_SERVER_RECORD Servers = NULL;
ULONG ServerStringSize; LPTSTR ServerStrings = NULL;
ULONG UserTableSize = 0; LPVOID Users = NULL;
ULONG UserStringSize; LPTSTR UserStrings = NULL;
LLS_DATA_FILE_HEADER FileHeader; DWORD BytesRead;
#if DBG
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_DATABASE)) dprintf(TEXT("LLS TRACE: LLSDataLoad\n")); #endif
RtlEnterCriticalSection(&UserFileLock);
//init
ZeroMemory(&FileHeader, sizeof(FileHeader));
//
// If nothing to load then get-out
//
if (!FileExists(UserFileName)) goto LLSDataLoadExit;
//
// Check the init header
//
Version = DataSize = 0; hFile = LlsFileCheck(UserFileName, &Version, &DataSize ); if (hFile == NULL) { Status = GetLastError(); goto LLSDataLoadExit; }
if ( ( ( Version != USER_FILE_VERSION_0 ) || ( DataSize != sizeof(LLS_DATA_FILE_HEADER_0) ) ) && ( ( Version != USER_FILE_VERSION ) || ( DataSize != sizeof(LLS_DATA_FILE_HEADER) ) ) ) { Status = STATUS_FILE_INVALID; goto LLSDataLoadExit; }
//
// The init header checks out, so load the license header and data blocks
//
if ( USER_FILE_VERSION_0 == Version ) { // 3.51 data file
LLS_DATA_FILE_HEADER_0 FileHeader0;
ret = ReadFile(hFile, &FileHeader0, sizeof(LLS_DATA_FILE_HEADER_0), &BytesRead, NULL);
if ( ret ) { FileHeader.ServiceLevel = 0; FileHeader.ServiceTableSize = FileHeader0.ServiceTableSize; FileHeader.ServiceStringSize = FileHeader0.ServiceStringSize; FileHeader.ServerLevel = 0; FileHeader.ServerTableSize = FileHeader0.ServerTableSize; FileHeader.ServerStringSize = FileHeader0.ServerStringSize; FileHeader.ServerServiceLevel = 0; FileHeader.ServerServiceTableSize = FileHeader0.ServerServiceTableSize; FileHeader.UserLevel = 0; FileHeader.UserTableSize = FileHeader0.UserTableSize; FileHeader.UserStringSize = FileHeader0.UserStringSize; } } else { ret = ReadFile(hFile, &FileHeader, sizeof(LLS_DATA_FILE_HEADER), &BytesRead, NULL); }
if ( ret ) { // header read okay; ensure data type levels are okay
if ( ( 0 != FileHeader.ServiceLevel ) || ( 0 != FileHeader.ServerLevel ) || ( 0 != FileHeader.ServerServiceLevel ) || ( ( 0 != FileHeader.UserLevel ) && ( 1 != FileHeader.UserLevel ) ) ) { Status = STATUS_FILE_INVALID; goto LLSDataLoadExit; } }
ServiceTableSize = 0; ServiceStringSize = 0; ServerServiceTableSize = 0; ServerTableSize = 0; ServerStringSize = 0; UserTableSize = 0; UserStringSize = 0;
if (ret) { //
// Run through and allocate space to read data blocks into
//
if (FileHeader.ServiceTableSize != 0) { ServiceTableSize = FileHeader.ServiceTableSize / sizeof(REPL_SERVICE_RECORD); Services = MIDL_user_allocate(FileHeader.ServiceTableSize);
if ( Services == NULL ) { Status = STATUS_NO_MEMORY; goto LLSDataLoadExit; } }
if (FileHeader.ServiceStringSize != 0) { ServiceStringSize = FileHeader.ServiceStringSize / sizeof(TCHAR); ServiceStrings = MIDL_user_allocate(FileHeader.ServiceStringSize);
if ( ServiceStrings == NULL ) { Status = STATUS_NO_MEMORY; goto LLSDataLoadExit; } }
if (FileHeader.ServerTableSize != 0) { ServerTableSize = FileHeader.ServerTableSize / sizeof(REPL_SERVER_RECORD); Servers = MIDL_user_allocate(FileHeader.ServerTableSize);
if ( Servers == NULL ) { Status = STATUS_NO_MEMORY; goto LLSDataLoadExit; } }
if (FileHeader.ServerStringSize != 0) { ServerStringSize = FileHeader.ServerStringSize / sizeof(TCHAR); ServerStrings = MIDL_user_allocate(FileHeader.ServerStringSize);
if ( ServerStrings == NULL ) { Status = STATUS_NO_MEMORY; goto LLSDataLoadExit; } }
if (FileHeader.ServerServiceTableSize != 0) { ServerServiceTableSize = FileHeader.ServerServiceTableSize / sizeof(REPL_SERVER_SERVICE_RECORD); ServerServices = MIDL_user_allocate(FileHeader.ServerServiceTableSize);
if ( ServerServices == NULL ) { Status = STATUS_NO_MEMORY; goto LLSDataLoadExit; } }
if (FileHeader.UserTableSize != 0) { UserTableSize = FileHeader.UserTableSize / ( FileHeader.UserLevel ? sizeof(REPL_USER_RECORD_1) : sizeof(REPL_USER_RECORD_0) ); Users = MIDL_user_allocate(FileHeader.UserTableSize);
if ( Users == NULL ) { Status = STATUS_NO_MEMORY; goto LLSDataLoadExit; } }
if (FileHeader.UserStringSize != 0) { UserStringSize = FileHeader.UserStringSize / sizeof(TCHAR); UserStrings = MIDL_user_allocate(FileHeader.UserStringSize);
if ( UserStrings == NULL ) { Status = STATUS_NO_MEMORY; goto LLSDataLoadExit; } }
}
if (ret && (FileHeader.ServiceTableSize != 0) ) ret = ReadFile(hFile, Services, FileHeader.ServiceTableSize, &BytesRead, NULL);
if (ret && (FileHeader.ServiceStringSize != 0) ) ret = ReadFile(hFile, ServiceStrings, FileHeader.ServiceStringSize, &BytesRead, NULL);
if (ret && (FileHeader.ServerTableSize != 0) ) ret = ReadFile(hFile, Servers, FileHeader.ServerTableSize, &BytesRead, NULL);
if (ret && (FileHeader.ServerStringSize != 0) ) ret = ReadFile(hFile, ServerStrings, FileHeader.ServerStringSize, &BytesRead, NULL);
if (ret && (FileHeader.ServerServiceTableSize != 0) ) ret = ReadFile(hFile, ServerServices, FileHeader.ServerServiceTableSize, &BytesRead, NULL);
if (ret && (FileHeader.UserTableSize != 0) ) ret = ReadFile(hFile, Users, FileHeader.UserTableSize, &BytesRead, NULL);
if (ret && (FileHeader.UserStringSize != 0) ) ret = ReadFile(hFile, UserStrings, FileHeader.UserStringSize, &BytesRead, NULL);
if (!ret) { Status = GetLastError(); goto LLSDataLoadExit; }
//
// Decrypt the data
//
Status = DeBlock(Services, FileHeader.ServiceTableSize);
if (Status == STATUS_SUCCESS) Status = DeBlock(ServiceStrings, FileHeader.ServiceStringSize);
if (Status == STATUS_SUCCESS) Status = DeBlock(Servers, FileHeader.ServerTableSize);
if (Status == STATUS_SUCCESS) Status = DeBlock(ServerStrings, FileHeader.ServerStringSize);
if (Status == STATUS_SUCCESS) Status = DeBlock(ServerServices, FileHeader.ServerServiceTableSize);
if (Status == STATUS_SUCCESS) Status = DeBlock(Users, FileHeader.UserTableSize);
if (Status == STATUS_SUCCESS) Status = DeBlock(UserStrings, FileHeader.UserStringSize);
if (Status != STATUS_SUCCESS) goto LLSDataLoadExit;
//
// Unpack the string data
//
ServiceListStringsUnpack( ServiceTableSize, Services, ServiceStringSize, ServiceStrings ); ServerListStringsUnpack( ServerTableSize, Servers, ServerStringSize, ServerStrings ); UserListStringsUnpack( FileHeader.UserLevel, UserTableSize, Users, UserStringSize, UserStrings );
//
// Unpack the data
//
UnpackAll ( ServiceTableSize, Services, ServerTableSize, Servers, ServerServiceTableSize, ServerServices, FileHeader.UserLevel, UserTableSize, Users );
LLSDataLoadExit:
if (hFile != NULL) CloseHandle(hFile);
RtlLeaveCriticalSection(&UserFileLock);
//
// Run through our tables and clean them up
//
if (Services != NULL) MIDL_user_free(Services);
if (ServiceStrings != NULL) MIDL_user_free(ServiceStrings);
if (Servers != NULL) MIDL_user_free(Servers);
if (ServerStrings != NULL) MIDL_user_free(ServerStrings);
if (ServerServices != NULL) MIDL_user_free(ServerServices);
if (Users != NULL) MIDL_user_free(Users);
if (UserStrings != NULL) MIDL_user_free(UserStrings);
//
// If there was an error log it.
//
if (Status != STATUS_SUCCESS) LogEvent(LLS_EVENT_LOAD_USER, 0, NULL, Status);
} // LLSDataLoad
/////////////////////////////////////////////////////////////////////////
NTSTATUS LLSDataSave()
/*++
Routine Description:
Arguments:
None.
Return Value:
None.
--*/
{ BOOL ret = TRUE; NTSTATUS Status = STATUS_SUCCESS; HANDLE hFile = NULL;
ULONG ServiceTableSize = 0; PREPL_SERVICE_RECORD Services = NULL;
ULONG ServiceStringSize; LPTSTR ServiceStrings = NULL;
ULONG ServerServiceTableSize = 0; PREPL_SERVER_SERVICE_RECORD ServerServices = NULL;
ULONG ServerTableSize = 0; PREPL_SERVER_RECORD Servers = NULL;
ULONG ServerStringSize; LPTSTR ServerStrings = NULL;
ULONG UserTableSize = 0; PREPL_USER_RECORD_1 Users = NULL;
ULONG UserStringSize; LPTSTR UserStrings = NULL;
LLS_DATA_FILE_HEADER FileHeader; DWORD BytesWritten;
#if DBG
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_DATABASE)) dprintf(TEXT("LLS TRACE: LLSDataSave\n")); #endif
RtlEnterCriticalSection(&UserFileLock);
//
// Pack the data
//
Status = PackAll ( 0, &ServiceTableSize, &Services, &ServerTableSize, &Servers, &ServerServiceTableSize, &ServerServices, 1, &UserTableSize, &Users ); if (Status != STATUS_SUCCESS) goto LLSDataSaveExit;
//
// Now pack the String data
//
Status = ServiceListStringsPack( ServiceTableSize, Services, &ServiceStringSize, &ServiceStrings ); if (Status != STATUS_SUCCESS) goto LLSDataSaveExit;
Status = ServerListStringsPack( ServerTableSize, Servers, &ServerStringSize, &ServerStrings ); if (Status != STATUS_SUCCESS) goto LLSDataSaveExit;
Status = UserListStringsPack( 1, UserTableSize, Users, &UserStringSize, &UserStrings ); if (Status != STATUS_SUCCESS) goto LLSDataSaveExit;
//
// Fill out the file header - sizes are byte sizes
//
FileHeader.ServiceTableSize = ServiceTableSize * sizeof(REPL_SERVICE_RECORD); FileHeader.ServiceStringSize = ServiceStringSize * sizeof(TCHAR); FileHeader.ServerTableSize = ServerTableSize * sizeof(REPL_SERVER_RECORD); FileHeader.ServerStringSize = ServerStringSize * sizeof(TCHAR); FileHeader.ServerServiceTableSize = ServerServiceTableSize * sizeof(REPL_SERVER_SERVICE_RECORD); FileHeader.UserTableSize = UserTableSize * sizeof(REPL_USER_RECORD_1); FileHeader.UserStringSize = UserStringSize * sizeof(TCHAR);
FileHeader.ServiceLevel = 0; FileHeader.ServerLevel = 0; FileHeader.ServerServiceLevel = 0; FileHeader.UserLevel = 1;
//
// Encrypt the data before saving it out.
//
Status = EBlock(Services, FileHeader.ServiceTableSize);
if (Status == STATUS_SUCCESS) Status = EBlock(ServiceStrings, FileHeader.ServiceStringSize);
if (Status == STATUS_SUCCESS) Status = EBlock(Servers, FileHeader.ServerTableSize);
if (Status == STATUS_SUCCESS) Status = EBlock(ServerStrings, FileHeader.ServerStringSize);
if (Status == STATUS_SUCCESS) Status = EBlock(ServerServices, FileHeader.ServerServiceTableSize);
if (Status == STATUS_SUCCESS) Status = EBlock(Users, FileHeader.UserTableSize);
if (Status == STATUS_SUCCESS) Status = EBlock(UserStrings, FileHeader.UserStringSize);
if (Status != STATUS_SUCCESS) goto LLSDataSaveExit;
//
// Save out the header record
//
hFile = LlsFileInit(UserFileName, USER_FILE_VERSION, sizeof(LLS_DATA_FILE_HEADER) ); if (hFile == NULL) { Status = GetLastError(); goto LLSDataSaveExit; }
//
// Now write out all the data blocks
//
ret = WriteFile(hFile, &FileHeader, sizeof(LLS_DATA_FILE_HEADER), &BytesWritten, NULL);
if (ret && (Services != NULL) && (FileHeader.ServiceTableSize != 0) ) ret = WriteFile(hFile, Services, FileHeader.ServiceTableSize, &BytesWritten, NULL);
if (ret && (ServiceStrings != NULL) && (FileHeader.ServiceStringSize != 0) ) ret = WriteFile(hFile, ServiceStrings, FileHeader.ServiceStringSize, &BytesWritten, NULL);
if (ret && (Servers != NULL) && (FileHeader.ServerTableSize != 0) ) ret = WriteFile(hFile, Servers, FileHeader.ServerTableSize, &BytesWritten, NULL);
if (ret && (ServerStrings != NULL) && (FileHeader.ServerStringSize != 0) ) ret = WriteFile(hFile, ServerStrings, FileHeader.ServerStringSize, &BytesWritten, NULL);
if (ret && (ServerServices != NULL) && (FileHeader.ServerServiceTableSize != 0) ) ret = WriteFile(hFile, ServerServices, FileHeader.ServerServiceTableSize, &BytesWritten, NULL);
if (ret && (Users != NULL) && (FileHeader.UserTableSize != 0) ) ret = WriteFile(hFile, Users, FileHeader.UserTableSize, &BytesWritten, NULL);
if (ret && (UserStrings != NULL) && (FileHeader.UserStringSize != 0) ) ret = WriteFile(hFile, UserStrings, FileHeader.UserStringSize, &BytesWritten, NULL);
if (!ret) Status = GetLastError();
LLSDataSaveExit:
if (hFile != NULL) CloseHandle(hFile);
RtlLeaveCriticalSection(&UserFileLock);
//
// Run through our tables and clean them up
//
if (Services != NULL) MIDL_user_free(Services);
if (ServiceStrings != NULL) MIDL_user_free(ServiceStrings);
if (Servers != NULL) MIDL_user_free(Servers);
if (ServerStrings != NULL) MIDL_user_free(ServerStrings);
if (ServerServices != NULL) MIDL_user_free(ServerServices);
if (Users != NULL) MIDL_user_free(Users);
if (UserStrings != NULL) MIDL_user_free(UserStrings);
//
// If there was an error log it.
//
if (Status != STATUS_SUCCESS) LogEvent(LLS_EVENT_SAVE_USER, 0, NULL, Status);
return Status; } // LLSDataSave
/////////////////////////////////////////////////////////////////////////
VOID LoadAll ( )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ #if DBG
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_DATABASE)) dprintf(TEXT("LLS TRACE: LoadAll\n")); #endif
PurchaseFile = NULL;
try { LicenseListLoad(); } except (TRUE) { LogEvent(LLS_EVENT_LOAD_LICENSE, 0, NULL, GetExceptionCode()); }
try { MappingListLoad(); } except (TRUE) { LogEvent(LLS_EVENT_LOAD_MAPPING, 0, NULL, GetExceptionCode()); }
try { LLSDataLoad(); } except (TRUE) { LogEvent(LLS_EVENT_LOAD_USER, 0, NULL, GetExceptionCode()); }
try { CertDbLoad(); } except (TRUE) { LogEvent(LLS_EVENT_LOAD_CERT_DB, 0, NULL, GetExceptionCode()); }
} // LoadAll
/////////////////////////////////////////////////////////////////////////
VOID SaveAll ( )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ #if DBG
if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_DATABASE)) dprintf(TEXT("LLS TRACE: SaveAll\n")); #endif
LicenseListSave(); MappingListSave(); LLSDataSave(); CertDbSave();
} // SaveAll
|