404 lines
12 KiB
C
404 lines
12 KiB
C
/*++
|
|
|
|
Copyright (c) 1994-7 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
binldef.h
|
|
|
|
Abstract:
|
|
|
|
This file contains manifest constants and internal data structures
|
|
for the BINL service.
|
|
|
|
Author:
|
|
|
|
Colin Watson (colinw) 14-Apr-1997
|
|
|
|
Environment:
|
|
|
|
User Mode - Win32
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#ifndef _BINL_
|
|
#define _BINL_
|
|
|
|
#if DBG
|
|
#define STATIC
|
|
#else
|
|
#define STATIC static
|
|
#endif // DBG
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
extern DWORD BinlRepeatSleep;
|
|
|
|
|
|
// Connection information to a DC in our domain
|
|
extern PLDAP DCLdapHandle;
|
|
extern PWCHAR * DCBase;
|
|
|
|
// Connection information to the Global Catalog for our enterprise
|
|
extern PLDAP GCLdapHandle;
|
|
extern PWCHAR * GCBase;
|
|
|
|
|
|
|
|
//
|
|
// useful macros
|
|
//
|
|
|
|
#define WSTRSIZE( wsz ) (( wcslen( wsz ) + 1 ) * sizeof( WCHAR ))
|
|
#define STRSIZE( sz ) (( strlen( sz ) + 1 ) * sizeof( char ))
|
|
#define SWAP( p1, p2 ) \
|
|
{ \
|
|
VOID *pvTemp = p1; \
|
|
p1 = p2; \
|
|
p2 = pvTemp; \
|
|
}
|
|
|
|
//
|
|
// calculates the size of a field
|
|
//
|
|
|
|
#define GET_SIZEOF_FIELD( struct, field ) ( sizeof(((struct*)0)->field))
|
|
|
|
|
|
//
|
|
// Constants
|
|
//
|
|
|
|
#define BINL_SERVER L"BINLSVC"
|
|
|
|
//
|
|
// Timeouts, this is the length of time we wait for our threads to terminate.
|
|
//
|
|
|
|
#define THREAD_TERMINATION_TIMEOUT INFINITE // wait a long time,
|
|
// but don't AV
|
|
|
|
#define BINL_HYPERMODE_TIMEOUT 60*1000 // in msecs. 1 min
|
|
#define BINL_HYPERMODE_RETRY_COUNT 30 // do it for 30 mins
|
|
|
|
//
|
|
// message queue length.
|
|
//
|
|
|
|
#define BINL_RECV_QUEUE_LENGTH 50
|
|
#define BINL_MAX_PROCESSING_THREADS 20
|
|
//
|
|
// macros
|
|
//
|
|
|
|
#define LOCK_INPROGRESS_LIST() EnterCriticalSection(&BinlGlobalInProgressCritSect)
|
|
#define UNLOCK_INPROGRESS_LIST() LeaveCriticalSection(&BinlGlobalInProgressCritSect)
|
|
|
|
#define LOCK_RECV_LIST() EnterCriticalSection(&BinlGlobalRecvListCritSect)
|
|
#define UNLOCK_RECV_LIST() LeaveCriticalSection(&BinlGlobalRecvListCritSect)
|
|
|
|
//
|
|
// An endpoint represents a socket and the addresses associated with
|
|
// the socket.
|
|
//
|
|
|
|
typedef struct _ENDPOINT {
|
|
SOCKET Socket;
|
|
DWORD Port;
|
|
DHCP_IP_ADDRESS IpAddress;
|
|
DHCP_IP_ADDRESS SubnetMask;
|
|
DHCP_IP_ADDRESS SubnetAddress;
|
|
} ENDPOINT, *LPENDPOINT, *PENDPOINT;
|
|
|
|
|
|
//
|
|
// A request context, one per processing thread.
|
|
//
|
|
|
|
typedef struct _BINL_REQUEST_CONTEXT {
|
|
|
|
//
|
|
// list pointer.
|
|
//
|
|
|
|
LIST_ENTRY ListEntry;
|
|
|
|
|
|
//
|
|
// pointer to a received buffer.
|
|
//
|
|
|
|
LPBYTE ReceiveBuffer;
|
|
|
|
//
|
|
// A buffer to send response.
|
|
//
|
|
|
|
LPBYTE SendBuffer;
|
|
|
|
//
|
|
// The actual amount of data received in the buffer.
|
|
//
|
|
|
|
DWORD ReceiveMessageSize;
|
|
|
|
//
|
|
// The actual amount of data send in the buffer.
|
|
//
|
|
|
|
DWORD SendMessageSize;
|
|
|
|
//
|
|
// The source of the current message
|
|
//
|
|
|
|
PENDPOINT ActiveEndpoint;
|
|
struct sockaddr SourceName;
|
|
DWORD SourceNameLength;
|
|
DWORD TimeArrived;
|
|
|
|
BYTE MessageType;
|
|
|
|
} BINL_REQUEST_CONTEXT, *LPBINL_REQUEST_CONTEXT, *PBINL_REQUEST_CONTEXT;
|
|
|
|
|
|
#define BOOT_FILE_SIZE 128
|
|
#define BOOT_SERVER_SIZE 64
|
|
#define BOOT_FILE_SIZE_W ( BOOT_FILE_SIZE * sizeof( WCHAR ))
|
|
#define BOOT_SERVER_SIZE_W ( BOOT_SERVER_SIZE * sizeof( WCHAR ))
|
|
|
|
//
|
|
// Registry data
|
|
//
|
|
|
|
#define BINL_PARAMETERS_KEY L"System\\CurrentControlSet\\Services\\Binlsvc\\Parameters"
|
|
#define BINL_PORT_NAME L"Port"
|
|
#define BINL_DEFAULT_PORT 4011
|
|
#define BINL_DEBUG_KEY L"Debug"
|
|
#if DBG
|
|
#define BINL_REPEAT_RESPONSE L"RepeatResponse"
|
|
#endif // DBG
|
|
#define BINL_LDAP_OPT_REFERRALS L"LdapOptReferrals"
|
|
#define BINL_MIN_RESPONSE_TIME L"ResponseDelay"
|
|
#define BINL_LDAP_SEARCH_TIMEOUT L"LdapTimeout"
|
|
#define BINL_CACHE_EXPIRE L"CacheExpire"
|
|
#define BINL_CACHE_MAX_COUNT L"CacheMaxCount"
|
|
#define BINL_ALLOW_NEW_CLIENTS L"AllowNewClients"
|
|
#define BINL_DEFAULT_CONTAINER L"DefaultContainer"
|
|
#define BINL_DEFAULT_DOMAIN L"DefaultDomain"
|
|
#define BINL_DEFAULT_DS L"DefaultServer"
|
|
#define BINL_DEFAULT_GC L"DefaultGCServer"
|
|
#define BINL_CLIENT_TIMEOUT L"ClientTimeout"
|
|
#define BINL_SCAVENGER_SLEEP L"ScavengerSleep"
|
|
#define BINL_SCAVENGER_SIFFILE L"SifFileSleep"
|
|
#define BINL_DEFAULT_LANGUAGE L"DefaultLanguage"
|
|
#define BINL_UPDATE_PARAMETER_POLL L"UpdateParameterPoll"
|
|
#define BINL_DS_ERROR_COUNT_PARAMETER L"MaxDSErrorsToLog"
|
|
#define BINL_DS_ERROR_SLEEP L"DSErrorInterval"
|
|
#define BINL_ASSIGN_NEW_CLIENTS_TO_SERVER L"AssignNewClientsToServer"
|
|
|
|
#define BINL_SCP_CREATED L"ScpCreated"
|
|
#define BINL_SCP_NEWCLIENTS L"netbootAllowNewClients"
|
|
#define BINL_SCP_LIMITCLIENTS L"netbootLimitClients"
|
|
#define BINL_SCP_CURRENTCLIENTCOUNT L"netbootCurrentClientCount"
|
|
#define BINL_SCP_MAXCLIENTS L"netbootMaxClients"
|
|
#define BINL_SCP_ANSWER_REQUESTS L"netbootAnswerRequests"
|
|
#define BINL_SCP_ANSWER_VALID L"netbootAnswerOnlyValidClients"
|
|
#define BINL_SCP_NEWMACHINENAMEPOLICY L"netbootNewMachineNamingPolicy"
|
|
#define BINL_SCP_NEWMACHINEOU L"netbootNewMachineOU"
|
|
#define BINL_SCP_NETBOOTSERVER L"netbootServer"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct _DHCP_BINARY_DATA {
|
|
DWORD DataLength;
|
|
|
|
#if defined(MIDL_PASS)
|
|
[size_is(DataLength)]
|
|
#endif // MIDL_PASS
|
|
BYTE *Data;
|
|
|
|
} DHCP_BINARY_DATA, *LPDHCP_BINARY_DATA;
|
|
|
|
//
|
|
// Structure that defines the state of a client.
|
|
//
|
|
// The reason we use a separate Positive and Negative RefCount is so that
|
|
// we don't have to re-acquire the global ClientsCriticalSection when
|
|
// we are done with a CLIENT_STATE, just to decrement the ref count.
|
|
// Instead we guard the NegativeRefCount with just the CLIENT_STATE's
|
|
// CriticalSection. Then we compare Positive and Negative and if they
|
|
// are equal we delete the CLIENT_STATE. Even if PositiveRefCount is
|
|
// being added to just as we do this comparison, it won't ever be equal
|
|
// to Negative RefCount unless we really are the last thread to use the
|
|
// CLIENT_STATE.
|
|
//
|
|
// Padding is in the structure so that the first two elements, which are
|
|
// guarded by ClientsCriticalSection, aren't in the same quadword as
|
|
// anything else.
|
|
//
|
|
|
|
// search and replace structure
|
|
typedef struct {
|
|
LPSTR pszToken;
|
|
struct {
|
|
LPSTR pszStringA;
|
|
LPWSTR pszStringW;
|
|
};
|
|
} SAR, * LPSAR;
|
|
|
|
#define MAX_VARIABLES 64
|
|
|
|
typedef struct _CLIENT_STATE {
|
|
LIST_ENTRY Linkage; // in ClientsQueue
|
|
ULONG PositiveRefCount; // guarded by global ClientsCriticalSection
|
|
ULONG Padding;
|
|
CRITICAL_SECTION CriticalSection; // prevents two messages processed at once
|
|
ULONG NegativeRefCount; // guarded by our CriticalSection; delete when equal to PositiveRC
|
|
ULONG RemoteIp; // IP address of the client
|
|
CtxtHandle ServerContextHandle;
|
|
PLDAP AuthenticatedDCLdapHandle; // returned by ldap_bind (with credentials)
|
|
HANDLE UserToken; // returned by LogonUser with same credentials
|
|
ULONG ContextAttributes;
|
|
UCHAR Seed; // seed used for run encoding-decoding
|
|
BOOL NegotiateProcessed;
|
|
BOOL CustomInstall; // true if custom, false if auto
|
|
BOOL AuthenticateProcessed; // if TRUE, then AuthenticateStatus is valid
|
|
BOOL CriticalSectionHeld; // just a quick check, not 100% accurate.
|
|
BOOL InitializeOnFirstRequest; // call OscInitializeClientVariables on initial request?
|
|
SECURITY_STATUS AuthenticateStatus;
|
|
ULONG LastSequenceNumber;
|
|
PUCHAR LastResponse; // buffer holding the last packet sent
|
|
ULONG LastResponseAllocated; // size LastResponse is allocated at
|
|
ULONG LastResponseLength; // size of current data in LastResponse
|
|
DWORD LastUpdate; // Last time this client state was entered
|
|
|
|
ULONG nVariables; // current number of defined varaibles
|
|
SAR Variables[ MAX_VARIABLES ]; // "variables" that are replaced in OSCs and SIFs
|
|
INT nCreateAccountCounter; // Counts up each time a different computer name was tired
|
|
BOOL fCreateNewAccount; // FALSE if a pre-staged account exists
|
|
BOOL fAutomaticMachineName; // TRUE is BINL generated the machine name
|
|
BOOL fHaveSetupMachineDN; // TRUE if we've already called OscCheckMachineDN
|
|
WCHAR MachineAccountPassword[LM20_PWLEN+1];
|
|
DWORD MachineAccountPasswordLength;
|
|
} CLIENT_STATE, *PCLIENT_STATE;
|
|
|
|
//
|
|
// The structure that tracks info based on GUID.
|
|
//
|
|
// Because checking the DS is a expensive, we track the results we received
|
|
// from the DS per GUID in this structure. This also allows us to ignore
|
|
// duplicate requests from clients when we're already working on them.
|
|
//
|
|
// These cache entries are very short lived, on the order of a minute or so.
|
|
// We'd hold them longer except we have no idea when they get stale in the DS.
|
|
//
|
|
// The list of cache entries is protected by BinlCacheListLock. An entry
|
|
// is in use when the InProgress flag is set. If this flag is set, it means
|
|
// that a thread is actively using it and the entry shouldn't be touched.
|
|
//
|
|
// If the hostname is not filled in and the NotMyClient flag is set to FALSE,
|
|
// then the entry, though allocated, hasn't been fully filled in.
|
|
//
|
|
// The XXX_ALLOC bits indicate that the corresponding field was allocated
|
|
// and needs to be freed when the cache entry is freed.
|
|
//
|
|
|
|
#define BINL_GUID_LENGTH 16
|
|
|
|
#define MI_NAME 0x00000001
|
|
#define MI_SETUPPATH 0x00000002
|
|
#define MI_HOSTNAME 0x00000004
|
|
#define MI_BOOTFILENAME 0x00000008
|
|
|
|
#define MI_SAMNAME 0x00000010
|
|
#define MI_PASSWORD 0x00000020
|
|
#define MI_DOMAIN 0x00000040
|
|
#define MI_HOSTIP 0x00000080
|
|
|
|
#define MI_MACHINEDN 0x00000100
|
|
|
|
#define MI_NAME_ALLOC 0x00010000
|
|
#define MI_SETUPPATH_ALLOC 0x00020000
|
|
#define MI_HOSTNAME_ALLOC 0x00040000
|
|
#define MI_BOOTFILENAME_ALLOC 0x00080000
|
|
|
|
#define MI_SAMNAME_ALLOC 0x00100000
|
|
#define MI_DOMAIN_ALLOC 0x00400000
|
|
#define MI_SIFFILENAME_ALLOC 0x00800000
|
|
|
|
#define MI_MACHINEDN_ALLOC 0x01000000
|
|
|
|
#define MI_ALL_ALLOC 0x03ff0000
|
|
|
|
#define MI_GUID 0x80000000 // UpdateCreate forces a new guid to be written
|
|
|
|
typedef struct _MACHINE_INFO {
|
|
|
|
LIST_ENTRY CacheListEntry; // global is BinlCacheList
|
|
DWORD TimeCreated; // from GetTickCount
|
|
|
|
BOOLEAN InProgress; // is a thread currently working on this?
|
|
BOOLEAN MyClient; // do we not respond to this client?
|
|
BOOLEAN EntryExists; // does the entry exist in the DS?
|
|
|
|
DWORD dwFlags; // "MI_" bits saying what information is currently valid
|
|
UCHAR Guid[BINL_GUID_LENGTH]; // client's GUID
|
|
PWCHAR Name; // client's name
|
|
PWCHAR MachineDN; // client's FQ Distinguished Name
|
|
PWCHAR SetupPath; // client's orginal installation path
|
|
PWCHAR HostName; // client's host server name
|
|
DHCP_IP_ADDRESS HostAddress; // address of host - this is filled when HostName is filled
|
|
PWCHAR BootFileName; // client's boot filename
|
|
PWCHAR SamName; // client's SAM name
|
|
PWCHAR Password; // client's password (for setting only)
|
|
ULONG PasswordLength; // client's password length (for setting only)
|
|
PWCHAR Domain; // client's domain
|
|
LIST_ENTRY DNsWithSameGuid; // list of DNs with same GUID, except for MachineDN above.
|
|
PWCHAR ForcedSifFileName; // client's sif file it must use.
|
|
|
|
} MACHINE_INFO, *PMACHINE_INFO;
|
|
|
|
//
|
|
// Structure that tracks duplicate DNs for this machine account. The structure
|
|
// is allocated with room for the two strings at the end.
|
|
//
|
|
|
|
typedef struct _DUP_GUID_DN {
|
|
|
|
LIST_ENTRY ListEntry;
|
|
ULONG DuplicateDNOffset; // offset from the start of DuplicateName to DuplicateDN
|
|
WCHAR DuplicateName[1]; // name of the duplicate account (without final '$')
|
|
// WCHAR DuplicateDN[]; // this follows at DuplicateDNOffset
|
|
|
|
} DUP_GUID_DN, *PDUP_GUID_DN;
|
|
|
|
|
|
//
|
|
// The largest size of any client architecture name
|
|
// (current choices: i386 alpha mips ia64 ppc arci386) --
|
|
// assume it won't exceed 8 chars for now.
|
|
//
|
|
|
|
#define MAX_ARCHITECTURE_LENGTH 8
|
|
|
|
|
|
#define DHCP_OPTION_CLIENT_ARCHITECTURE_X86 0
|
|
#define DHCP_OPTION_CLIENT_ARCHITECTURE_NEC98 1
|
|
#define DHCP_OPTION_CLIENT_ARCHITECTURE_IA64 2
|
|
#define DHCP_OPTION_CLIENT_ARCHITECTURE_ALPHA 3
|
|
#define DHCP_OPTION_CLIENT_ARCHITECTURE_ARCX86 4
|
|
#define DHCP_OPTION_CLIENT_ARCHITECTURE_INTELLEAN 5
|
|
|
|
#endif _BINL_
|