163 lines
7.1 KiB
C
163 lines
7.1 KiB
C
//+----------------------------------------------------------------------------
|
|
//
|
|
// Copyright (C) 1992, Microsoft Corporation
|
|
//
|
|
// File: rpselect.h
|
|
//
|
|
// Contents: Function & Data Structure prototypes for replica selection.
|
|
//
|
|
// Classes:
|
|
//
|
|
// Functions: ReplFindFirstProvider - find first appropriate provider and
|
|
// initialize the select context.
|
|
// ReplFindNextProvider - get next provider from the list of
|
|
// providers based on an initialized select context.
|
|
// ReplSetActiveService - a courtesy routine to tell replica
|
|
// selection that a particular service "worked". Will
|
|
// cause this service to be the first one to be tried
|
|
// on subsequent calls to FindFirst.
|
|
// ReplIsRecoverableError - see if error code is something worth
|
|
// trying a replica for.
|
|
//
|
|
// Data Structures:
|
|
// REPL_SELECT_CONTEXT
|
|
//
|
|
// History: 02 Sep 92 MilanS created.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#ifndef _RPSELECT_
|
|
#define _RPSELECT_
|
|
|
|
//
|
|
// This structure is supposed to be opaque to the user of this module.
|
|
// It should only be used to create select contexts to be passed to
|
|
// FindFirstProvider and FindNextProvider.
|
|
//
|
|
|
|
typedef struct _REPL_SELECT_CONTEXT {
|
|
unsigned short Flags;
|
|
ULONG iFirstSvcIndex; // index of first svc
|
|
ULONG iSvcIndex; // index of the last svc
|
|
// returned to caller.
|
|
} REPL_SELECT_CONTEXT, *PREPL_SELECT_CONTEXT;
|
|
|
|
|
|
//
|
|
// Define flags for SelectContext structures.
|
|
//
|
|
|
|
#define REPL_UNINITIALIZED 0x0001
|
|
#define REPL_SVC_IS_LOCAL 0x0002
|
|
#define REPL_SVC_IS_REMOTE 0x0004
|
|
#define REPL_PRINCIPAL_SPECD 0x0008
|
|
#define REPL_NO_MORE_ENTRIES 0x0010
|
|
|
|
|
|
NTSTATUS
|
|
ReplFindFirstProvider(
|
|
IN PDFS_PKT_ENTRY pPktEntry, // for which a svc is needed
|
|
IN GUID *pidPrincipal, // look for this service
|
|
IN PUNICODE_STRING pustrPrincipal, // or look for this service
|
|
OUT PDFS_SERVICE *ppService, // return selected service
|
|
OUT PREPL_SELECT_CONTEXT pSelectContext, // Context to be initialized.
|
|
OUT BOOLEAN *pLastEntry // Last entry
|
|
);
|
|
|
|
|
|
NTSTATUS
|
|
ReplFindNextProvider(
|
|
IN PDFS_PKT_ENTRY pPktEntry, // for which another svc is
|
|
OUT PDFS_SERVICE *ppService, // needed.
|
|
IN OUT PREPL_SELECT_CONTEXT pSelectContext, // Context to use
|
|
OUT BOOLEAN *pLastEntry // Last entry
|
|
);
|
|
|
|
PPROVIDER_DEF
|
|
ReplLookupProvider(ULONG ProviderId);
|
|
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: ReplSetActiveService
|
|
//
|
|
// Synopsis: Sets the ActiveService pointer of a PKT Entry. This is an
|
|
// Optimization. People who later look for a service for this
|
|
// PKT Entry will be asked to look at the ActiveService first.
|
|
//
|
|
// Arguments: [pPktEntry] Pointer to PKT Entry.
|
|
// [SelectContext] Initialized Select Context returned by
|
|
// FindFirst or FindNext.
|
|
//
|
|
// Returns: Nothing
|
|
//
|
|
// Notes: For now, this is a #define. Later, when we support multi-
|
|
// threaded operation, we can change it to a function that tests
|
|
// whether the Pkt Entry has changed under it etc.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#define ReplSetActiveService(p,s) \
|
|
{ \
|
|
if ((s).Flags & REPL_SVC_IS_REMOTE ) { \
|
|
(p)->ActiveService = &(p)->Info.ServiceList[(s).iSvcIndex]; \
|
|
if ((p)->ActiveService->pMachEntry != NULL) { \
|
|
InterlockedIncrement( \
|
|
&(p)->ActiveService->pMachEntry->ConnectionCount); \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: ReplIsRecoverableError
|
|
//
|
|
// Synopsis: True if the argument is an NTSTATUS error code for which it
|
|
// makes sense to try a replica if one is available.
|
|
//
|
|
// Arguments: [x] - The NTSTATUS error code to be tested.
|
|
//
|
|
// Returns: True / False
|
|
//
|
|
// Notes: For now, this is simply #defined to be a relatively big OR
|
|
// statement that tests for a bunch of specific error codes. If we
|
|
// need to test for more error codes, it might be worth organizing
|
|
// them into a hash table, which can then quickly be tested.
|
|
//
|
|
// My initial estimates are that a hash table with either a modulo
|
|
// or multiplication hash function will become cheaper at around
|
|
// 7-8 error codes, assuming clock cycle estimates of x86. A tree
|
|
// type organization becomes effective after 10 error codes. The
|
|
// problem with the latter is generating at compile time a
|
|
// static, balanced tree.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#define ReplIsRecoverableError(x) ( (x) == STATUS_IO_TIMEOUT || \
|
|
(x) == STATUS_REMOTE_NOT_LISTENING || \
|
|
(x) == STATUS_VIRTUAL_CIRCUIT_CLOSED || \
|
|
(x) == STATUS_BAD_NETWORK_PATH || \
|
|
(x) == STATUS_NETWORK_BUSY || \
|
|
(x) == STATUS_INVALID_NETWORK_RESPONSE || \
|
|
(x) == STATUS_UNEXPECTED_NETWORK_ERROR || \
|
|
(x) == STATUS_NETWORK_NAME_DELETED || \
|
|
(x) == STATUS_BAD_NETWORK_NAME || \
|
|
(x) == STATUS_REQUEST_NOT_ACCEPTED || \
|
|
(x) == STATUS_DISK_OPERATION_FAILED || \
|
|
(x) == STATUS_DEVICE_OFF_LINE || \
|
|
(x) == STATUS_NETWORK_UNREACHABLE || \
|
|
(x) == STATUS_INSUFFICIENT_RESOURCES || \
|
|
(x) == STATUS_SHARING_PAUSED || \
|
|
(x) == STATUS_DFS_UNAVAILABLE || \
|
|
(x) == STATUS_NO_SUCH_DEVICE || \
|
|
(x) == STATUS_NETLOGON_NOT_STARTED || \
|
|
(x) == STATUS_UNMAPPABLE_CHARACTER || \
|
|
(x) == STATUS_CONNECTION_DISCONNECTED || \
|
|
(x) == STATUS_USER_SESSION_DELETED || \
|
|
(x) == STATUS_NO_SUCH_LOGON_SESSION \
|
|
)
|
|
#endif
|
|
|