You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2065 lines
76 KiB
2065 lines
76 KiB
/****************************************************************************/
|
|
// jetrpcfn.cpp
|
|
//
|
|
// TS Directory Integrity Service Jet RPC server-side implementations.
|
|
//
|
|
// Copyright (C) 2000, Microsoft Corporation
|
|
/****************************************************************************/
|
|
|
|
#include "dis.h"
|
|
#include "tssdshrd.h"
|
|
#include "jetrpc.h"
|
|
#include "jetsdis.h"
|
|
#include "sdevent.h"
|
|
#include <Lm.h>
|
|
|
|
#pragma warning (push, 4)
|
|
|
|
extern PSID g_pSid;
|
|
extern DWORD g_dwClusterState;
|
|
extern WCHAR *g_ClusterNetworkName;
|
|
|
|
/****************************************************************************/
|
|
// MIDL_user_allocate
|
|
// MIDL_user_free
|
|
//
|
|
// RPC-required allocation functions.
|
|
/****************************************************************************/
|
|
void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t Size)
|
|
{
|
|
return LocalAlloc(LMEM_FIXED, Size);
|
|
}
|
|
|
|
void __RPC_USER MIDL_user_free(void __RPC_FAR *p)
|
|
{
|
|
LocalFree(p);
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
// OutputAllTables (debug only)
|
|
//
|
|
// Output all tables to debug output.
|
|
/****************************************************************************/
|
|
#ifdef DBG
|
|
void OutputAllTables()
|
|
{
|
|
JET_ERR err;
|
|
JET_SESID sesid = JET_sesidNil;
|
|
JET_DBID dbid;
|
|
JET_TABLEID sessdirtableid;
|
|
JET_TABLEID servdirtableid;
|
|
JET_TABLEID clusdirtableid;
|
|
JET_RETRIEVECOLUMN rcSessDir[NUM_SESSDIRCOLUMNS];
|
|
WCHAR UserNameBuf[256];
|
|
WCHAR DomainBuf[127];
|
|
WCHAR ApplicationBuf[256];
|
|
WCHAR ServerNameBuf[128];
|
|
WCHAR ClusterNameBuf[128];
|
|
WCHAR ServerDNSNameBuf[SDNAMELENGTH];
|
|
unsigned count;
|
|
long num_vals[NUM_SESSDIRCOLUMNS];
|
|
char state;
|
|
char SingleSessMode;
|
|
|
|
CALL(JetBeginSession(g_instance, &sesid, "user", ""));
|
|
CALL(JetOpenDatabase(sesid, JETDBFILENAME, "", &dbid, 0));
|
|
|
|
CALL(JetOpenTable(sesid, dbid, "SessionDirectory", NULL, 0, 0,
|
|
&sessdirtableid));
|
|
CALL(JetOpenTable(sesid, dbid, "ServerDirectory", NULL, 0, 0,
|
|
&servdirtableid));
|
|
CALL(JetOpenTable(sesid, dbid, "ClusterDirectory", NULL, 0, 0,
|
|
&clusdirtableid));
|
|
CALL(JetBeginTransaction(sesid));
|
|
|
|
TSDISErrorOut(L"SESSION DIRECTORY\n");
|
|
|
|
err = JetMove(sesid, sessdirtableid, JET_MoveFirst, 0);
|
|
|
|
if (JET_errNoCurrentRecord == err) {
|
|
TSDISErrorOut(L" (empty database)\n");
|
|
}
|
|
|
|
while (JET_errNoCurrentRecord != err) {
|
|
// Retrieve all the columns
|
|
memset(&rcSessDir[0], 0, sizeof(JET_RETRIEVECOLUMN) *
|
|
NUM_SESSDIRCOLUMNS);
|
|
for (count = 0; count < NUM_SESSDIRCOLUMNS; count++) {
|
|
rcSessDir[count].columnid = sesdircolumnid[count];
|
|
rcSessDir[count].pvData = &num_vals[count];
|
|
rcSessDir[count].cbData = sizeof(long);
|
|
rcSessDir[count].itagSequence = 1;
|
|
}
|
|
// fix up pvData, cbData for non-int fields
|
|
rcSessDir[SESSDIR_USERNAME_INTERNAL_INDEX].pvData = UserNameBuf;
|
|
rcSessDir[SESSDIR_USERNAME_INTERNAL_INDEX].cbData = sizeof(UserNameBuf);
|
|
rcSessDir[SESSDIR_DOMAIN_INTERNAL_INDEX].pvData = DomainBuf;
|
|
rcSessDir[SESSDIR_DOMAIN_INTERNAL_INDEX].cbData = sizeof(DomainBuf);
|
|
rcSessDir[SESSDIR_APPTYPE_INTERNAL_INDEX].pvData = ApplicationBuf;
|
|
rcSessDir[SESSDIR_APPTYPE_INTERNAL_INDEX].cbData =
|
|
sizeof(ApplicationBuf);
|
|
rcSessDir[SESSDIR_STATE_INTERNAL_INDEX].pvData = &state;
|
|
rcSessDir[SESSDIR_STATE_INTERNAL_INDEX].cbData = sizeof(state);
|
|
|
|
CALL(JetRetrieveColumns(sesid, sessdirtableid, &rcSessDir[0],
|
|
NUM_SESSDIRCOLUMNS));
|
|
|
|
TSDISErrorOut(L"%8s, %s, %d, %d, %d\n",
|
|
UserNameBuf,
|
|
DomainBuf,
|
|
num_vals[SESSDIR_SERVERID_INTERNAL_INDEX],
|
|
num_vals[SESSDIR_SESSIONID_INTERNAL_INDEX],
|
|
num_vals[SESSDIR_TSPROTOCOL_INTERNAL_INDEX]);
|
|
|
|
TSDISErrorTimeOut(L" %s, ",
|
|
num_vals[SESSDIR_CTLOW_INTERNAL_INDEX],
|
|
num_vals[SESSDIR_CTHIGH_INTERNAL_INDEX]);
|
|
|
|
TSDISErrorTimeOut(L"%s\n",
|
|
num_vals[SESSDIR_DTLOW_INTERNAL_INDEX],
|
|
num_vals[SESSDIR_DTHIGH_INTERNAL_INDEX]);
|
|
|
|
TSDISErrorOut(L" %s, %d, %d, %d, %s\n",
|
|
ApplicationBuf ? L"(no application)" : ApplicationBuf,
|
|
num_vals[SESSDIR_RESWIDTH_INTERNAL_INDEX],
|
|
num_vals[SESSDIR_RESHEIGHT_INTERNAL_INDEX],
|
|
num_vals[SESSDIR_COLORDEPTH_INTERNAL_INDEX],
|
|
state ? L"disconnected" : L"connected");
|
|
|
|
err = JetMove(sesid, sessdirtableid, JET_MoveNext, 0);
|
|
}
|
|
|
|
// Output Server Directory (we are reusing the rcSessDir structure).
|
|
TSDISErrorOut(L"SERVER DIRECTORY\n");
|
|
|
|
err = JetMove(sesid, servdirtableid, JET_MoveFirst, 0);
|
|
if (JET_errNoCurrentRecord == err) {
|
|
TSDISErrorOut(L" (empty database)\n");
|
|
}
|
|
|
|
while (JET_errNoCurrentRecord != err) {
|
|
// Retrieve all the columns.
|
|
memset(&rcSessDir[0], 0, sizeof(JET_RETRIEVECOLUMN) *
|
|
NUM_SERVDIRCOLUMNS);
|
|
for (count = 0; count < NUM_SERVDIRCOLUMNS; count++) {
|
|
rcSessDir[count].columnid = servdircolumnid[count];
|
|
rcSessDir[count].pvData = &num_vals[count];
|
|
rcSessDir[count].cbData = sizeof(long);
|
|
rcSessDir[count].itagSequence = 1;
|
|
}
|
|
rcSessDir[SERVDIR_SERVADDR_INTERNAL_INDEX].pvData = ServerNameBuf;
|
|
rcSessDir[SERVDIR_SERVADDR_INTERNAL_INDEX].cbData =
|
|
sizeof(ServerNameBuf);
|
|
rcSessDir[SERVDIR_SERVDNSNAME_INTERNAL_INDEX].pvData = ServerDNSNameBuf;
|
|
rcSessDir[SERVDIR_SERVDNSNAME_INTERNAL_INDEX].cbData =
|
|
sizeof(ServerDNSNameBuf);
|
|
rcSessDir[SERVDIR_SINGLESESS_INTERNAL_INDEX].pvData = &SingleSessMode;
|
|
rcSessDir[SERVDIR_SINGLESESS_INTERNAL_INDEX].cbData = sizeof(SingleSessMode);
|
|
|
|
|
|
CALL(JetRetrieveColumns(sesid, servdirtableid, &rcSessDir[0],
|
|
NUM_SERVDIRCOLUMNS));
|
|
|
|
TSDISErrorOut(L"%d, %s, %d, %d, %d, %d, %s\n", num_vals[
|
|
SERVDIR_SERVID_INTERNAL_INDEX], ServerNameBuf, num_vals[
|
|
SERVDIR_CLUSID_INTERNAL_INDEX], num_vals[
|
|
SERVDIR_AITLOW_INTERNAL_INDEX], num_vals[
|
|
SERVDIR_AITHIGH_INTERNAL_INDEX], num_vals[
|
|
SERVDIR_NUMFAILPINGS_INTERNAL_INDEX], SingleSessMode ?
|
|
L"single session mode" : L"multi-session mode");
|
|
|
|
err = JetMove(sesid, servdirtableid, JET_MoveNext, 0);
|
|
|
|
}
|
|
|
|
|
|
// Output Cluster Directory
|
|
TSDISErrorOut(L"CLUSTER DIRECTORY\n");
|
|
|
|
err = JetMove(sesid, clusdirtableid, JET_MoveFirst, 0);
|
|
if (JET_errNoCurrentRecord == err) {
|
|
TSDISErrorOut(L" (empty database)\n");
|
|
}
|
|
|
|
while (JET_errNoCurrentRecord != err) {
|
|
memset(&rcSessDir[0], 0, sizeof(JET_RETRIEVECOLUMN) *
|
|
NUM_CLUSDIRCOLUMNS);
|
|
for (count = 0; count < NUM_CLUSDIRCOLUMNS; count++) {
|
|
rcSessDir[count].columnid = clusdircolumnid[count];
|
|
rcSessDir[count].pvData = &num_vals[count];
|
|
rcSessDir[count].cbData = sizeof(long);
|
|
rcSessDir[count].itagSequence = 1;
|
|
}
|
|
rcSessDir[CLUSDIR_CLUSNAME_INTERNAL_INDEX].pvData = ClusterNameBuf;
|
|
rcSessDir[CLUSDIR_CLUSNAME_INTERNAL_INDEX].cbData =
|
|
sizeof(ClusterNameBuf);
|
|
rcSessDir[CLUSDIR_SINGLESESS_INTERNAL_INDEX].pvData = &SingleSessMode;
|
|
rcSessDir[CLUSDIR_SINGLESESS_INTERNAL_INDEX].cbData =
|
|
sizeof(SingleSessMode);
|
|
|
|
CALL(JetRetrieveColumns(sesid, clusdirtableid, &rcSessDir[0],
|
|
NUM_CLUSDIRCOLUMNS));
|
|
|
|
TSDISErrorOut(L"%d, %s, %s\n", num_vals[CLUSDIR_CLUSID_INTERNAL_INDEX],
|
|
ClusterNameBuf, SingleSessMode ? L"single session mode" :
|
|
L"multi-session mode");
|
|
|
|
err = JetMove(sesid, clusdirtableid, JET_MoveNext, 0);
|
|
}
|
|
|
|
TSDISErrorOut(L"\n");
|
|
|
|
CALL(JetCommitTransaction(sesid, 0));
|
|
|
|
CALL(JetCloseTable(sesid, servdirtableid));
|
|
CALL(JetCloseTable(sesid, sessdirtableid));
|
|
CALL(JetCloseTable(sesid, clusdirtableid));
|
|
|
|
CALL(JetCloseDatabase(sesid, dbid, 0));
|
|
|
|
CALL(JetEndSession(sesid, 0));
|
|
|
|
return;
|
|
|
|
HandleError:
|
|
if (sesid != JET_sesidNil) {
|
|
// Can't really recover. Just bail out.
|
|
(VOID) JetRollback(sesid, JET_bitRollbackAll);
|
|
|
|
// Force the session closed
|
|
(VOID) JetEndSession(sesid, JET_bitForceSessionClosed);
|
|
}
|
|
|
|
}
|
|
#endif //DBG
|
|
|
|
|
|
typedef DWORD CLIENTINFO;
|
|
|
|
long
|
|
DeleteExistingServerSession(
|
|
JET_SESID sesid,
|
|
JET_TABLEID sessdirtableid,
|
|
CLIENTINFO *pCI,
|
|
DWORD SessionID
|
|
)
|
|
/*++
|
|
|
|
|
|
--*/
|
|
{
|
|
JET_ERR err = JET_errSuccess;
|
|
DWORD dwNumRecordDeleted = 0;
|
|
|
|
TSDISErrorOut(L"In DeleteExistingServerSession, ServID=%d, "
|
|
L"SessID=%d\n", *pCI, SessionID);
|
|
|
|
ASSERT( (sesid != JET_sesidNil), (TB, "Invalid JETBLUE Session...") );
|
|
|
|
// Delete all sessions in session directory that have this Server ID/Session ID
|
|
CALL(JetSetCurrentIndex(sesid, sessdirtableid, "primaryIndex"));
|
|
CALL(JetMakeKey(sesid, sessdirtableid, pCI, sizeof(*pCI), JET_bitNewKey));
|
|
CALL(JetMakeKey(sesid, sessdirtableid, &SessionID, sizeof(SessionID), 0));
|
|
|
|
err = JetSeek(sesid, sessdirtableid, JET_bitSeekEQ | JET_bitSetIndexRange);
|
|
|
|
while ( JET_errSuccess == err ) {
|
|
|
|
// TODO - check build, retrieve server id and session Id, assert if not equal to what
|
|
// we looking for
|
|
CALL(JetDelete(sesid, sessdirtableid));
|
|
dwNumRecordDeleted++;
|
|
|
|
// Move to the next matching record.
|
|
err = JetMove(sesid, sessdirtableid, JET_MoveNext, 0);
|
|
}
|
|
|
|
ASSERT( (dwNumRecordDeleted < 2), (TB, "Delete %d record...", dwNumRecordDeleted) );
|
|
|
|
TSDISErrorOut(L"Deleted %d for ServID=%d, "
|
|
L"SessID=%d\n", dwNumRecordDeleted, *pCI, SessionID);
|
|
|
|
return dwNumRecordDeleted;
|
|
|
|
HandleError:
|
|
|
|
// the only way to come here is error in one of Jet call wrap around CALL.
|
|
ASSERT( (err == JET_errSuccess), (TB, "Error in DeleteExistingServerSession %d", err) );
|
|
|
|
return -1;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
// SDRPCAccessCheck
|
|
//
|
|
// Check if this RPC caller havs access right or not
|
|
/****************************************************************************/
|
|
RPC_STATUS RPC_ENTRY SDRPCAccessCheck(RPC_IF_HANDLE idIF, void *Binding)
|
|
{
|
|
RPC_STATUS rpcStatus, rc;
|
|
HANDLE hClientToken = NULL;
|
|
DWORD Error;
|
|
BOOL AccessStatus = FALSE;
|
|
RPC_AUTHZ_HANDLE hPrivs;
|
|
DWORD dwAuthn;
|
|
RPC_BINDING_HANDLE ServerBinding = 0;
|
|
WCHAR *StringBinding = NULL;
|
|
WCHAR *ServerAddress = NULL;
|
|
|
|
idIF;
|
|
|
|
if (RpcBindingServerFromClient(Binding, &ServerBinding) != RPC_S_OK) {
|
|
TSDISErrorOut(L"In SDRPCAccessCheck: BindingServerFromClient failed!\n");
|
|
goto HandleError;
|
|
}
|
|
if (RpcBindingToStringBinding(ServerBinding, &StringBinding) != RPC_S_OK) {
|
|
TSDISErrorOut(L"In SDRPCAccessCheck: BindingToStringBinding failed!\n");
|
|
goto HandleError;
|
|
}
|
|
if (RpcStringBindingParse(StringBinding, NULL, NULL, &ServerAddress, NULL,
|
|
NULL) != RPC_S_OK) {
|
|
TSDISErrorOut(L"In SDRPCAccessCheck: StringBindingParse failed!\n");
|
|
goto HandleError;
|
|
}
|
|
|
|
// Check if the client uses the protocol sequence we expect
|
|
if (!CheckRPCClientProtoSeq(Binding, L"ncacn_ip_tcp")) {
|
|
TSDISErrorOut(L"In SDRPCAccessCheck: Client doesn't use the tcpip protocol sequence\n");
|
|
goto HandleError;
|
|
}
|
|
|
|
// Check what security level the client uses
|
|
rpcStatus = RpcBindingInqAuthClient(Binding,
|
|
&hPrivs,
|
|
NULL,
|
|
&dwAuthn,
|
|
NULL,
|
|
NULL);
|
|
if (rpcStatus != RPC_S_OK) {
|
|
TSDISErrorOut(L"In SDRPCAccessCheck: RpcBindingIngAuthClient fails with %u\n", rpcStatus);
|
|
goto HandleError;
|
|
}
|
|
// We request at least privacy-level authentication
|
|
if (dwAuthn < RPC_C_AUTHN_LEVEL_PKT_PRIVACY) {
|
|
TSDISErrorOut(L"In SDRPCAccessCheck: Attemp by client to use weak authentication\n");
|
|
goto HandleError;
|
|
}
|
|
|
|
// Check the access right of this rpc call
|
|
rpcStatus = RpcImpersonateClient(Binding);
|
|
if (RPC_S_OK != rpcStatus) {
|
|
TSDISErrorOut(L"In SDRPCAccessCheck: RpcImpersonateClient fail with %u\n", rpcStatus);
|
|
goto HandleError;
|
|
}
|
|
// get our impersonated token
|
|
if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hClientToken)) {
|
|
Error = GetLastError();
|
|
TSDISErrorOut(L"In SDRPCAccessCheck: OpenThreadToken Error %u\n", Error);
|
|
RpcRevertToSelf();
|
|
goto HandleError;
|
|
}
|
|
RpcRevertToSelf();
|
|
|
|
if (!CheckTokenMembership(hClientToken,
|
|
g_pSid,
|
|
&AccessStatus)) {
|
|
AccessStatus = FALSE;
|
|
Error = GetLastError();
|
|
TSDISErrorOut(L"In SDRPCAccessCheck: CheckTokenMembership fails with %u\n", Error);
|
|
}
|
|
|
|
HandleError:
|
|
if (AccessStatus) {
|
|
rc = RPC_S_OK;
|
|
}
|
|
else {
|
|
if (ServerAddress) {
|
|
TSDISErrorOut(L"In SDRPCAccessCheck: Unauthorized RPC call from server %s\n", ServerAddress);
|
|
PostSessDirErrorMsgEvent(EVENT_FAIL_RPC_DENY_ACCESS, ServerAddress, EVENTLOG_ERROR_TYPE);
|
|
}
|
|
rc = ERROR_ACCESS_DENIED;
|
|
}
|
|
|
|
if (hClientToken != NULL) {
|
|
CloseHandle(hClientToken);
|
|
}
|
|
if (ServerBinding != NULL)
|
|
RpcBindingFree(&ServerBinding);
|
|
if (StringBinding != NULL)
|
|
RpcStringFree(&StringBinding);
|
|
if (ServerAddress != NULL)
|
|
RpcStringFree(&ServerAddress);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
// TSSDRpcServerOnline
|
|
//
|
|
// Called for server-active indications on each cluster TS machine.
|
|
/****************************************************************************/
|
|
DWORD TSSDRpcServerOnline(
|
|
handle_t Binding,
|
|
WCHAR __RPC_FAR *ClusterName,
|
|
/* out */ HCLIENTINFO *hCI,
|
|
DWORD SrvOnlineFlags,
|
|
/* in, out */ WCHAR *ComputerName,
|
|
/* in */ WCHAR *ServerIPAddr)
|
|
{
|
|
JET_ERR err;
|
|
JET_SESID sesid = JET_sesidNil;
|
|
JET_DBID dbid;
|
|
JET_TABLEID clusdirtableid;
|
|
JET_TABLEID servdirtableid;
|
|
JET_SETCOLUMN scServDir[NUM_SERVDIRCOLUMNS];
|
|
WCHAR *StringBinding = NULL;
|
|
WCHAR *ServerAddress = NULL;
|
|
RPC_BINDING_HANDLE ServerBinding = 0;
|
|
unsigned long cbActual;
|
|
long ClusterID;
|
|
long ServerID = 0;
|
|
long zero = 0;
|
|
// The single session mode of this server.
|
|
char SingleSession = (char) SrvOnlineFlags & SINGLE_SESSION_FLAG;
|
|
char ClusSingleSessionMode;
|
|
unsigned count;
|
|
DWORD rc = (DWORD) E_FAIL;
|
|
DWORD cchBuff;
|
|
WCHAR ServerDNSName[SDNAMELENGTH];
|
|
|
|
// "unreferenced" parameter (referenced by RPC)
|
|
Binding;
|
|
ServerIPAddr;
|
|
|
|
TSDISErrorOut(L"In ServOnline, ClusterName=%s, SrvOnlineFlags=%u\n",
|
|
ClusterName, SrvOnlineFlags);
|
|
// Make a copy of TS server DNS server name
|
|
wcsncpy(ServerDNSName, ComputerName, SDNAMELENGTH);
|
|
TSDISErrorOut(L"In ServOnline, the Server Name is %s\n", ServerDNSName);
|
|
// Determine client address.
|
|
if (RpcBindingServerFromClient(Binding, &ServerBinding) != RPC_S_OK) {
|
|
TSDISErrorOut(L"ServOn: BindingServerFromClient failed!\n");
|
|
goto HandleError;
|
|
}
|
|
if (RpcBindingToStringBinding(ServerBinding, &StringBinding) != RPC_S_OK) {
|
|
TSDISErrorOut(L"ServOn: BindingToStringBinding failed!\n");
|
|
goto HandleError;
|
|
}
|
|
if (RpcStringBindingParse(StringBinding, NULL, NULL, &ServerAddress, NULL,
|
|
NULL) != RPC_S_OK) {
|
|
TSDISErrorOut(L"ServOn: StringBindingParse failed!\n");
|
|
goto HandleError;
|
|
}
|
|
|
|
//TSDISErrorOut(L"In ServOnline, ServerAddress is %s\n",
|
|
// ServerAddress);
|
|
|
|
CALL(JetBeginSession(g_instance, &sesid, "user", ""));
|
|
|
|
CALL(JetOpenDatabase(sesid, JETDBFILENAME, "", &dbid, 0));
|
|
|
|
CALL(JetOpenTable(sesid, dbid, "ClusterDirectory", NULL, 0, 0,
|
|
&clusdirtableid));
|
|
CALL(JetOpenTable(sesid, dbid, "ServerDirectory", NULL, 0, 0,
|
|
&servdirtableid));
|
|
|
|
// This server comes with NO_REPOPULATE_SESSION flag
|
|
// We will reuse its info in the database
|
|
if (SrvOnlineFlags & NO_REPOPULATE_SESSION) {
|
|
CALL(JetBeginTransaction(sesid));
|
|
|
|
CALL(JetSetCurrentIndex(sesid, servdirtableid, "ServDNSNameIndex"));
|
|
CALL(JetMakeKey(sesid, servdirtableid, ServerDNSName, (unsigned)
|
|
(wcslen(ServerDNSName) + 1) * sizeof(WCHAR), JET_bitNewKey));
|
|
err = JetSeek(sesid, servdirtableid, JET_bitSeekEQ);
|
|
if (JET_errSuccess == err) {
|
|
CALL(JetRetrieveColumn(sesid, servdirtableid, servdircolumnid[
|
|
SERVDIR_SERVID_INTERNAL_INDEX], &ServerID, sizeof(ServerID),
|
|
&cbActual, 0, NULL));
|
|
*hCI = ULongToPtr(ServerID);
|
|
TSDISErrorOut(L"In ServOnline, ServerID is %d\n", *hCI);
|
|
} else {
|
|
// If we can't find this server, fail ServOnline call and server will rejoin SD
|
|
TSDISErrorOut(L"ServOn: This server with no-populate flag can't be found\n");
|
|
goto HandleError;
|
|
}
|
|
CALL(JetCommitTransaction(sesid, 0));
|
|
|
|
goto NormalExit;
|
|
}
|
|
|
|
// First, delete all entries for this server from the session/server
|
|
//directories
|
|
CALL(JetBeginTransaction(sesid));
|
|
|
|
CALL(JetSetCurrentIndex(sesid, servdirtableid, "ServDNSNameIndex"));
|
|
CALL(JetMakeKey(sesid, servdirtableid, ServerDNSName, (unsigned)
|
|
(wcslen(ServerDNSName) + 1) * sizeof(WCHAR), JET_bitNewKey));
|
|
err = JetSeek(sesid, servdirtableid, JET_bitSeekEQ);
|
|
if (JET_errSuccess == err) {
|
|
CALL(JetRetrieveColumn(sesid, servdirtableid, servdircolumnid[
|
|
SERVDIR_SERVID_INTERNAL_INDEX], &ServerID, sizeof(ServerID),
|
|
&cbActual, 0, NULL));
|
|
if (TSSDPurgeServer(ServerID) != 0)
|
|
TSDISErrorOut(L"ServOn: PurgeServer %d failed.\n", ServerID);
|
|
} else if (JET_errRecordNotFound != err) {
|
|
CALL(err);
|
|
}
|
|
CALL(JetCommitTransaction(sesid, 0));
|
|
|
|
// We have to do the add in a loop, because we have to:
|
|
// 1) Check if the record is there.
|
|
// 2) If it's not, add it. (The next time through the loop, therefore,
|
|
// we'll go step 1->3, and we're done.)
|
|
// 3) If it is, retrieve the value of clusterID and break out.
|
|
//
|
|
// There is an additional complication in that someone else may be in the
|
|
// thread simultaneously, doing the same thing. Therefore, someone might
|
|
// be in step 2 and try to add a new cluster, but fail because someone
|
|
// else added it. So they have to keep trying, because though the other
|
|
// thread has added it, it may not have committed the change. To try to
|
|
// keep that to a minimum, we sleep a short time before trying again.
|
|
for ( ; ; ) {
|
|
// Now do the actual add.
|
|
CALL(JetBeginTransaction(sesid));
|
|
|
|
// Search for the cluster in the cluster directory.
|
|
CALL(JetSetCurrentIndex(sesid, clusdirtableid, "ClusNameIndex"));
|
|
CALL(JetMakeKey(sesid, clusdirtableid, ClusterName, (unsigned)
|
|
(wcslen(ClusterName) + 1) * sizeof(WCHAR), JET_bitNewKey));
|
|
err = JetSeek(sesid, clusdirtableid, JET_bitSeekEQ);
|
|
|
|
// If the cluster does not exist, create it.
|
|
if (JET_errRecordNotFound == err) {
|
|
CALL(JetPrepareUpdate(sesid, clusdirtableid, JET_prepInsert));
|
|
|
|
// ClusterName
|
|
CALL(JetSetColumn(sesid, clusdirtableid, clusdircolumnid[
|
|
CLUSDIR_CLUSNAME_INTERNAL_INDEX], ClusterName,
|
|
(unsigned) (wcslen(ClusterName) + 1) * sizeof(WCHAR), 0,
|
|
NULL));
|
|
|
|
// SingleSessionMode
|
|
|
|
// Since this is the only server in the cluster, the single session
|
|
// mode is simply the mode of this server.
|
|
CALL(JetSetColumn(sesid, clusdirtableid, clusdircolumnid[
|
|
CLUSDIR_SINGLESESS_INTERNAL_INDEX], &SingleSession,
|
|
sizeof(SingleSession), 0, NULL));
|
|
|
|
err = JetUpdate(sesid, clusdirtableid, NULL, 0, &cbActual);
|
|
|
|
// If it's a duplicate key, someone else made the key so we should
|
|
// be ok. Yield the processor and try the query again, next time
|
|
// through the loop.
|
|
if (JET_errKeyDuplicate == err) {
|
|
CALL(JetCommitTransaction(sesid, 0));
|
|
Sleep(100);
|
|
}
|
|
else {
|
|
CALL(err);
|
|
|
|
// Now we've succeeded. Just continue through the loop.
|
|
// The next time through, we will retrieve the autoincrement
|
|
// column we just added and break out.
|
|
CALL(JetCommitTransaction(sesid, 0));
|
|
}
|
|
|
|
}
|
|
else {
|
|
CALL(err);
|
|
|
|
// If the above check makes it here, we have found the row.
|
|
// Now retrieve the clusid, commit, and break out of the loop.
|
|
CALL(JetRetrieveColumn(sesid, clusdirtableid, clusdircolumnid[
|
|
CLUSDIR_CLUSID_INTERNAL_INDEX], &ClusterID,
|
|
sizeof(ClusterID), &cbActual, 0, NULL));
|
|
|
|
CALL(JetCommitTransaction(sesid, 0));
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
CALL(JetBeginTransaction(sesid));
|
|
|
|
// Insert the servername, clusterid, 0, 0 into the server directory table
|
|
err = JetMove(sesid, servdirtableid, JET_MoveLast, 0);
|
|
|
|
CALL(JetPrepareUpdate(sesid, servdirtableid, JET_prepInsert));
|
|
|
|
memset(&scServDir[0], 0, sizeof(JET_SETCOLUMN) * NUM_SERVDIRCOLUMNS);
|
|
|
|
for (count = 0; count < NUM_SERVDIRCOLUMNS; count++) {
|
|
scServDir[count].columnid = servdircolumnid[count];
|
|
scServDir[count].cbData = 4; // most of them, set the rest individually
|
|
scServDir[count].itagSequence = 1;
|
|
}
|
|
scServDir[SERVDIR_SERVADDR_INTERNAL_INDEX].pvData = ServerAddress;
|
|
scServDir[SERVDIR_SERVADDR_INTERNAL_INDEX].cbData =
|
|
(unsigned) (wcslen(ServerAddress) + 1) * sizeof(WCHAR);
|
|
scServDir[SERVDIR_CLUSID_INTERNAL_INDEX].pvData = &ClusterID;
|
|
scServDir[SERVDIR_AITLOW_INTERNAL_INDEX].pvData = &zero;
|
|
scServDir[SERVDIR_AITHIGH_INTERNAL_INDEX].pvData = &zero;
|
|
scServDir[SERVDIR_NUMFAILPINGS_INTERNAL_INDEX].pvData = &zero;
|
|
scServDir[SERVDIR_SINGLESESS_INTERNAL_INDEX].pvData = &SingleSession;
|
|
scServDir[SERVDIR_SINGLESESS_INTERNAL_INDEX].cbData = sizeof(SingleSession);
|
|
scServDir[SERVDIR_SERVDNSNAME_INTERNAL_INDEX].pvData = ServerDNSName;
|
|
scServDir[SERVDIR_SERVDNSNAME_INTERNAL_INDEX].cbData =
|
|
(unsigned) (wcslen(ServerDNSName) + 1) * sizeof(WCHAR);
|
|
|
|
// Don't set the first column (index 0)--it is autoincrement.
|
|
CALL(JetSetColumns(sesid, servdirtableid, &scServDir[
|
|
SERVDIR_SERVADDR_INTERNAL_INDEX], NUM_SERVDIRCOLUMNS - 1));
|
|
CALL(JetUpdate(sesid, servdirtableid, NULL, 0, &cbActual));
|
|
|
|
CALL(JetSetCurrentIndex(sesid, servdirtableid, "ServNameIndex"));
|
|
CALL(JetMakeKey(sesid, servdirtableid, ServerAddress, (unsigned)
|
|
(wcslen(ServerAddress) + 1) * sizeof(WCHAR), JET_bitNewKey));
|
|
CALL(JetSeek(sesid, servdirtableid, JET_bitSeekEQ));
|
|
CALL(JetRetrieveColumn(sesid, servdirtableid, servdircolumnid[
|
|
SERVDIR_SERVID_INTERNAL_INDEX], &ServerID, sizeof(ServerID),
|
|
&cbActual, 0, NULL));
|
|
*hCI = ULongToPtr(ServerID);
|
|
|
|
TSDISErrorOut(L"In ServOnline, ServerID is %d\n", *hCI);
|
|
|
|
// Now that the server is all set up, we have to set the cluster to the
|
|
// correct mode. If any server in the cluster is in multisession mode, then
|
|
// we stick with multisession. If they are all single session, though, we
|
|
// turn on single session in this cluster.
|
|
|
|
// Check the cluster to see if its single-session mode.
|
|
CALL(JetSetCurrentIndex(sesid, clusdirtableid, "ClusIDIndex"));
|
|
CALL(JetMakeKey(sesid, clusdirtableid, (const void *)&ClusterID,
|
|
sizeof(ClusterID), JET_bitNewKey));
|
|
CALL(JetSeek(sesid, clusdirtableid, JET_bitSeekEQ));
|
|
CALL(JetRetrieveColumn(sesid, clusdirtableid, clusdircolumnid[
|
|
CLUSDIR_SINGLESESS_INTERNAL_INDEX], &ClusSingleSessionMode, sizeof(
|
|
ClusSingleSessionMode), &cbActual, 0, NULL));
|
|
|
|
// If the new server is multi-session mode and cluster is single-session, change the mode.
|
|
if ((SingleSession == 0) && (ClusSingleSessionMode != SingleSession)) {
|
|
err = JetPrepareUpdate(sesid, clusdirtableid, JET_prepReplace);
|
|
|
|
if (JET_errWriteConflict == err) {
|
|
// Another thread is updating this setting, so no need to update
|
|
}
|
|
else {
|
|
CALL(err);
|
|
|
|
CALL(JetSetColumn(sesid, clusdirtableid, clusdircolumnid[
|
|
CLUSDIR_SINGLESESS_INTERNAL_INDEX], &SingleSession,
|
|
sizeof(SingleSession), 0, NULL));
|
|
CALL(JetUpdate(sesid, clusdirtableid, NULL, 0, &cbActual));
|
|
}
|
|
}
|
|
|
|
CALL(JetCommitTransaction(sesid, 0));
|
|
|
|
NormalExit:
|
|
CALL(JetCloseTable(sesid, servdirtableid));
|
|
CALL(JetCloseTable(sesid, clusdirtableid));
|
|
|
|
CALL(JetCloseDatabase(sesid, dbid, 0));
|
|
|
|
CALL(JetEndSession(sesid, 0));
|
|
|
|
// Get the local computer name
|
|
cchBuff = SDNAMELENGTH - 2;
|
|
if (g_dwClusterState == ClusterStateRunning) {
|
|
// return ClusterNetworkName as the computer name if it's
|
|
// running on fail-over cluster
|
|
wcsncpy(ComputerName, g_ClusterNetworkName, cchBuff);
|
|
}
|
|
else {
|
|
if (!GetComputerNameEx(ComputerNamePhysicalNetBIOS, ComputerName, &cchBuff)) {
|
|
TSDISErrorOut(L"GetComputerNameEx fails with 0x%x\n", GetLastError());
|
|
goto HandleError;
|
|
}
|
|
}
|
|
wcscat(ComputerName, L"$");
|
|
|
|
if (ServerBinding != NULL)
|
|
RpcBindingFree(&ServerBinding);
|
|
if (StringBinding != NULL)
|
|
RpcStringFree(&StringBinding);
|
|
if (ServerAddress != NULL)
|
|
RpcStringFree(&ServerAddress);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
HandleError:
|
|
if (sesid != JET_sesidNil) {
|
|
// Can't really recover. Just bail out.
|
|
(VOID) JetRollback(sesid, JET_bitRollbackAll);
|
|
|
|
// Force the session closed
|
|
(VOID) JetEndSession(sesid, JET_bitForceSessionClosed);
|
|
}
|
|
|
|
TSDISErrorOut(L"ERROR : ServOnline %s failed with possible error code %d, start TSSDPurgeServer\n", ComputerName, err);
|
|
|
|
if (ServerBinding != NULL)
|
|
RpcBindingFree(&ServerBinding);
|
|
if (StringBinding != NULL)
|
|
RpcStringFree(&StringBinding);
|
|
if (ServerAddress != NULL)
|
|
RpcStringFree(&ServerAddress);
|
|
|
|
// Just in case we got to commit.
|
|
if (ServerID != 0)
|
|
TSSDPurgeServer(ServerID);
|
|
|
|
// Close the context handle.
|
|
*hCI = NULL;
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
// TSSDRpcServerOffline
|
|
//
|
|
// Called for server-shutdown indications on each cluster TS machine.
|
|
/****************************************************************************/
|
|
DWORD TSSDRpcServerOffline(
|
|
handle_t Binding,
|
|
HCLIENTINFO *hCI)
|
|
{
|
|
DWORD retval = 0;
|
|
|
|
// "unreferenced" parameter (referenced by RPC)
|
|
Binding;
|
|
|
|
TSDISErrorOut(L"WARNING: In ServOff, hCI = 0x%x\n", *hCI);
|
|
|
|
CLIENTINFO *pCI = (CLIENTINFO *) hCI;
|
|
|
|
if (pCI != NULL)
|
|
retval = TSSDPurgeServer(*pCI);
|
|
|
|
*hCI = NULL;
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
// TSSDPurgeServer
|
|
//
|
|
// Delete a server and all its sessions from the session directory.
|
|
/****************************************************************************/
|
|
DWORD TSSDPurgeServer(
|
|
DWORD ServerID)
|
|
{
|
|
JET_SESID sesid = JET_sesidNil;
|
|
JET_TABLEID sessdirtableid;
|
|
JET_TABLEID servdirtableid;
|
|
JET_TABLEID clusdirtableid;
|
|
JET_DBID dbid;
|
|
JET_ERR err;
|
|
long ClusterID;
|
|
unsigned long cbActual;
|
|
char MultiSession = 0;
|
|
char SingleSessionMode;
|
|
WCHAR Msg[SDNAMELENGTH * 2 + 3], ServerIP[SDNAMELENGTH];
|
|
DWORD numSessionDeleted = 0; // number of session deleted for this server
|
|
BOOL bLoadServerIPSucceeeded = FALSE; // successful in loading serverip from table
|
|
|
|
// initialize string for event log
|
|
ZeroMemory( Msg, sizeof(Msg) );
|
|
ZeroMemory( ServerIP, sizeof(ServerIP) );
|
|
|
|
TSDISErrorOut(L"WARNING: In PurgeServer, ServerID=%d\n", ServerID);
|
|
|
|
CALL(JetBeginSession(g_instance, &sesid, "user", ""));
|
|
|
|
CALL(JetOpenDatabase(sesid, JETDBFILENAME, "", &dbid, 0));
|
|
|
|
CALL(JetOpenTable(sesid, dbid, "SessionDirectory", NULL, 0, 0,
|
|
&sessdirtableid));
|
|
CALL(JetOpenTable(sesid, dbid, "ServerDirectory", NULL, 0, 0,
|
|
&servdirtableid));
|
|
CALL(JetOpenTable(sesid, dbid, "ClusterDirectory", NULL, 0, 0,
|
|
&clusdirtableid));
|
|
|
|
CALL(JetBeginTransaction(sesid));
|
|
|
|
// Delete all sessions in session directory that have this serverid
|
|
CALL(JetSetCurrentIndex(sesid, sessdirtableid, "ServerIndex"));
|
|
CALL(JetMakeKey(sesid, sessdirtableid, &ServerID, sizeof(ServerID),
|
|
JET_bitNewKey));
|
|
err = JetSeek(sesid, sessdirtableid, JET_bitSeekEQ);
|
|
|
|
while (0 == err) {
|
|
CALL(JetDelete(sesid, sessdirtableid));
|
|
|
|
numSessionDeleted++;
|
|
CALL(JetMakeKey(sesid, sessdirtableid, &ServerID, sizeof(ServerID),
|
|
JET_bitNewKey));
|
|
err = JetSeek(sesid, sessdirtableid, JET_bitSeekEQ);
|
|
}
|
|
|
|
// Should be err -1601 -- JET_errRecordNotFound
|
|
|
|
// Delete the server in the server directory with this serverid
|
|
CALL(JetSetCurrentIndex(sesid, servdirtableid, "ServerIDIndex"));
|
|
CALL(JetMakeKey(sesid, servdirtableid, &ServerID, sizeof(ServerID),
|
|
JET_bitNewKey));
|
|
err = JetSeek(sesid, servdirtableid, JET_bitSeekEQ);
|
|
if (JET_errSuccess == err) {
|
|
CALL(JetRetrieveColumn(sesid, servdirtableid, servdircolumnid[
|
|
SERVDIR_CLUSID_INTERNAL_INDEX], &ClusterID,
|
|
sizeof(ClusterID), &cbActual, 0, NULL));
|
|
CALL(JetRetrieveColumn(sesid, servdirtableid, servdircolumnid[
|
|
SERVDIR_SINGLESESS_INTERNAL_INDEX], &SingleSessionMode,
|
|
sizeof(SingleSessionMode), &cbActual, 0, NULL));
|
|
// Get the server DNS name and IP
|
|
cbActual = SDNAMELENGTH * sizeof(WCHAR);
|
|
CALL(JetRetrieveColumn(sesid, servdirtableid, servdircolumnid[
|
|
SERVDIR_SERVDNSNAME_INTERNAL_INDEX], Msg,
|
|
cbActual, &cbActual, 0, NULL));
|
|
CALL(JetRetrieveColumn(sesid, servdirtableid, servdircolumnid[
|
|
SERVDIR_SERVADDR_INTERNAL_INDEX], ServerIP,
|
|
sizeof(ServerIP), &cbActual, 0, NULL));
|
|
|
|
bLoadServerIPSucceeeded = TRUE;
|
|
|
|
CALL(JetDelete(sesid, servdirtableid));
|
|
// If the server is the only one in cluster, delete this cluster in cluster directory
|
|
CALL(JetSetCurrentIndex(sesid, servdirtableid, "ClusterIDIndex"));
|
|
CALL(JetMakeKey(sesid, servdirtableid, &ClusterID, sizeof(ClusterID),
|
|
JET_bitNewKey));
|
|
err = JetSeek(sesid, servdirtableid, JET_bitSeekEQ);
|
|
if (JET_errRecordNotFound == err) {
|
|
// There's no other server in this cluster, delete this cluster
|
|
|
|
CALL(JetSetCurrentIndex(sesid, clusdirtableid, "ClusIDIndex"));
|
|
CALL(JetMakeKey(sesid, clusdirtableid, &ClusterID, sizeof(ClusterID), JET_bitNewKey));
|
|
err = JetSeek(sesid, clusdirtableid, JET_bitSeekEQ);
|
|
if (JET_errSuccess == err)
|
|
{
|
|
CALL(JetDelete(sesid, clusdirtableid));
|
|
}
|
|
}
|
|
else {
|
|
CALL(err);
|
|
// Update the SingleSessionMode of the cluster
|
|
// If server removed is SingleSession, the cluster single session mode won't be affected
|
|
// otherwise, seach the sever table for server in the cluster with multi-session mode
|
|
// if not found, change the cluster single-session mode to single-session, otherwise do nothing
|
|
if (SingleSessionMode == 0) {
|
|
CALL(JetSetCurrentIndex(sesid, servdirtableid, "SingleSessionIndex"));
|
|
CALL(JetMakeKey(sesid, servdirtableid, &ClusterID, sizeof(ClusterID),
|
|
JET_bitNewKey));
|
|
CALL(JetMakeKey(sesid, servdirtableid, &MultiSession, sizeof(MultiSession),
|
|
0));
|
|
err = JetSeek(sesid, servdirtableid, JET_bitSeekEQ);
|
|
if (JET_errRecordNotFound == err) {
|
|
// Set the cluster single-session mode to True
|
|
SingleSessionMode = (char)1;
|
|
CALL(JetSetCurrentIndex(sesid, clusdirtableid, "ClusIDIndex"));
|
|
CALL(JetMakeKey(sesid, clusdirtableid, &ClusterID, sizeof(ClusterID), JET_bitNewKey));
|
|
CALL(JetSeek(sesid, clusdirtableid, JET_bitSeekEQ));
|
|
|
|
CALL(JetPrepareUpdate(sesid, clusdirtableid, JET_prepReplace));
|
|
CALL(JetSetColumn(sesid, clusdirtableid, clusdircolumnid[
|
|
CLUSDIR_SINGLESESS_INTERNAL_INDEX], &SingleSessionMode, sizeof(SingleSessionMode), 0, NULL));
|
|
CALL(JetUpdate(sesid, clusdirtableid, NULL, 0, &cbActual));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CALL(JetCommitTransaction(sesid, 0));
|
|
|
|
CALL(JetCloseTable(sesid, servdirtableid));
|
|
CALL(JetCloseTable(sesid, sessdirtableid));
|
|
|
|
CALL(JetCloseDatabase(sesid, dbid, 0));
|
|
|
|
CALL(JetEndSession(sesid, 0));
|
|
|
|
// we don't want to log event if we can't load serverIP from table.
|
|
if( bLoadServerIPSucceeeded )
|
|
{
|
|
// Construct log msg to record TS leaving SD
|
|
wcscat(Msg, L"(");
|
|
wcsncat(Msg, ServerIP, SDNAMELENGTH);
|
|
wcscat(Msg, L")");
|
|
PostSessDirErrorMsgEvent(EVENT_SUCCESS_LEAVE_SESSIONDIRECTORY, Msg, EVENTLOG_SUCCESS);
|
|
}
|
|
else
|
|
{
|
|
TSDISErrorOut(L"WARNING: In PurgeServer() deleted %d "
|
|
L"sessions for ServerID=%d but failed to load IP\n", numSessionDeleted, ServerID);
|
|
}
|
|
|
|
return 0;
|
|
|
|
HandleError:
|
|
if (sesid != JET_sesidNil) {
|
|
// Can't really recover. Just bail out.
|
|
(VOID) JetRollback(sesid, JET_bitRollbackAll);
|
|
|
|
// Force the session closed
|
|
(VOID) JetEndSession(sesid, JET_bitForceSessionClosed);
|
|
}
|
|
|
|
return (DWORD) E_FAIL;
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
// TSSDRpcGetUserDisconnectedSessions
|
|
//
|
|
// Queries disconnected sessions from the session database.
|
|
/****************************************************************************/
|
|
DWORD TSSDRpcGetUserDisconnectedSessions(
|
|
handle_t Binding,
|
|
HCLIENTINFO *hCI,
|
|
WCHAR __RPC_FAR *UserName,
|
|
WCHAR __RPC_FAR *Domain,
|
|
/* out */ DWORD __RPC_FAR *pNumSessions,
|
|
/* out */ TSSD_DiscSessInfo __RPC_FAR __RPC_FAR **padsi)
|
|
{
|
|
JET_ERR err;
|
|
JET_SESID sesid = JET_sesidNil;
|
|
JET_DBID dbid;
|
|
JET_TABLEID sessdirtableid;
|
|
JET_TABLEID servdirtableid;
|
|
JET_TABLEID clusdirtableid;
|
|
*pNumSessions = 0;
|
|
unsigned i = 0;
|
|
unsigned j = 0;
|
|
unsigned long cbActual;
|
|
DWORD tempClusterID;
|
|
DWORD CallingServersClusID;
|
|
long ServerID;
|
|
CLIENTINFO *pCI = (CLIENTINFO *) hCI;
|
|
TSSD_DiscSessInfo *adsi = NULL;
|
|
char one = 1;
|
|
char bSingleSession = 0;
|
|
|
|
// "unreferenced" parameter (referenced by RPC)
|
|
Binding;
|
|
|
|
TSDISErrorOut(L"In GetUserDiscSess: ServID = %d, User: %s, "
|
|
L"Domain: %s\n", *pCI, UserName, Domain);
|
|
|
|
*padsi = (TSSD_DiscSessInfo *) MIDL_user_allocate(sizeof(TSSD_DiscSessInfo) *
|
|
TSSD_MaxDisconnectedSessions);
|
|
|
|
adsi = *padsi;
|
|
|
|
if (adsi == NULL) {
|
|
TSDISErrorOut(L"GetUserDisc: Memory alloc failed!\n");
|
|
goto HandleError;
|
|
}
|
|
|
|
// Set the pointers to 0 to be safe, and so that we can free uninitialized
|
|
// ones later without AVing.
|
|
for (j = 0; j < TSSD_MaxDisconnectedSessions; j++) {
|
|
adsi[j].ServerAddress = NULL;
|
|
adsi[j].AppType = NULL;
|
|
}
|
|
|
|
CALL(JetBeginSession(g_instance, &sesid, "user", ""));
|
|
CALL(JetOpenDatabase(sesid, JETDBFILENAME, "", &dbid, 0));
|
|
|
|
CALL(JetOpenTable(sesid, dbid, "SessionDirectory", NULL, 0, 0,
|
|
&sessdirtableid));
|
|
CALL(JetOpenTable(sesid, dbid, "ServerDirectory", NULL, 0, 0,
|
|
&servdirtableid));
|
|
CALL(JetOpenTable(sesid, dbid, "ClusterDirectory", NULL, 0, 0,
|
|
&clusdirtableid));
|
|
|
|
CALL(JetBeginTransaction(sesid));
|
|
|
|
// Verify that the ServerID passed in was OK.
|
|
if (TSSDVerifyServerIDValid(sesid, servdirtableid, PtrToUlong(*hCI)) == FALSE) {
|
|
TSDISErrorOut(L"Invalid ServerID was passed in\n");
|
|
goto HandleError;
|
|
}
|
|
|
|
// First, get the cluster ID for the server making the query.
|
|
CALL(JetSetCurrentIndex(sesid, servdirtableid, "ServerIDIndex"));
|
|
CALL(JetMakeKey(sesid, servdirtableid, (const void *)pCI, sizeof(DWORD),
|
|
JET_bitNewKey));
|
|
CALL(JetSeek(sesid, servdirtableid, JET_bitSeekEQ));
|
|
CALL(JetRetrieveColumn(sesid, servdirtableid, servdircolumnid[
|
|
SERVDIR_CLUSID_INTERNAL_INDEX], &CallingServersClusID, sizeof(
|
|
CallingServersClusID), &cbActual, 0, NULL));
|
|
|
|
// Now that we have the cluster id, check to see whether this cluster
|
|
// is in single session mode.
|
|
CALL(JetSetCurrentIndex(sesid, clusdirtableid, "ClusIDIndex"));
|
|
CALL(JetMakeKey(sesid, clusdirtableid, (const void *)&CallingServersClusID,
|
|
sizeof(CallingServersClusID), JET_bitNewKey));
|
|
CALL(JetSeek(sesid, clusdirtableid, JET_bitSeekEQ));
|
|
CALL(JetRetrieveColumn(sesid, clusdirtableid, clusdircolumnid[
|
|
CLUSDIR_SINGLESESS_INTERNAL_INDEX], &bSingleSession, sizeof(
|
|
bSingleSession), &cbActual, 0, NULL));
|
|
|
|
// Now, get all the disconnected or all sessions for this cluster, depending
|
|
// on the single session mode retrieved above.
|
|
if (bSingleSession == FALSE) {
|
|
CALL(JetSetCurrentIndex(sesid, sessdirtableid, "DiscSessionIndex"));
|
|
|
|
CALL(JetMakeKey(sesid, sessdirtableid, UserName, (unsigned)
|
|
(wcslen(UserName) + 1) * sizeof(WCHAR), JET_bitNewKey));
|
|
CALL(JetMakeKey(sesid, sessdirtableid, Domain, (unsigned)
|
|
(wcslen(Domain) + 1) * sizeof(WCHAR), 0));
|
|
CALL(JetMakeKey(sesid, sessdirtableid, &one, sizeof(one), 0));
|
|
}
|
|
else {
|
|
CALL(JetSetCurrentIndex(sesid, sessdirtableid, "AllSessionIndex"));
|
|
|
|
CALL(JetMakeKey(sesid, sessdirtableid, UserName, (unsigned)
|
|
(wcslen(UserName) + 1) * sizeof(WCHAR), JET_bitNewKey));
|
|
CALL(JetMakeKey(sesid, sessdirtableid, Domain, (unsigned)
|
|
(wcslen(Domain) + 1) * sizeof(WCHAR), 0));
|
|
}
|
|
|
|
err = JetSeek(sesid, sessdirtableid, JET_bitSeekEQ | JET_bitSetIndexRange);
|
|
|
|
while ((i < TSSD_MaxDisconnectedSessions) && (JET_errSuccess == err)) {
|
|
// Remember the initial retrieval does not have cluster id in the
|
|
// index, so filter by cluster id for each one.
|
|
|
|
// Get the ServerID for this record.
|
|
CALL(JetRetrieveColumn(sesid, sessdirtableid, sesdircolumnid[
|
|
SESSDIR_SERVERID_INTERNAL_INDEX], &ServerID, sizeof(ServerID),
|
|
&cbActual, 0, NULL));
|
|
|
|
// Get the clusterID
|
|
CALL(JetSetCurrentIndex(sesid, servdirtableid, "ServerIDIndex"));
|
|
CALL(JetMakeKey(sesid, servdirtableid, &ServerID, sizeof(ServerID),
|
|
JET_bitNewKey));
|
|
CALL(JetSeek(sesid, servdirtableid, JET_bitSeekEQ));
|
|
CALL(JetRetrieveColumn(sesid, servdirtableid, servdircolumnid[
|
|
SERVDIR_CLUSID_INTERNAL_INDEX], &tempClusterID,
|
|
sizeof(tempClusterID), &cbActual, 0, NULL));
|
|
|
|
// Compare to the passed-in cluster id.
|
|
if (tempClusterID == CallingServersClusID) {
|
|
// Allocate space.
|
|
adsi[i].ServerAddress = (WCHAR *) MIDL_user_allocate(64 *
|
|
sizeof(WCHAR));
|
|
adsi[i].AppType = (WCHAR *) MIDL_user_allocate(256 * sizeof(WCHAR));
|
|
|
|
if ((adsi[i].ServerAddress == NULL) || (adsi[i].AppType == NULL)) {
|
|
TSDISErrorOut(L"GetUserDisc: Memory alloc failed!\n");
|
|
goto HandleError;
|
|
}
|
|
|
|
// ServerAddress comes out of the server table
|
|
CALL(JetRetrieveColumn(sesid, servdirtableid, servdircolumnid[
|
|
SERVDIR_SERVADDR_INTERNAL_INDEX], adsi[i].ServerAddress,
|
|
128, &cbActual, 0, NULL));
|
|
// The rest come out of the session directory
|
|
// Session ID
|
|
CALL(JetRetrieveColumn(sesid, sessdirtableid,
|
|
sesdircolumnid[SESSDIR_SESSIONID_INTERNAL_INDEX],
|
|
&(adsi[i].SessionID), sizeof(DWORD), &cbActual, 0, NULL));
|
|
// TSProtocol
|
|
CALL(JetRetrieveColumn(sesid, sessdirtableid,
|
|
sesdircolumnid[SESSDIR_TSPROTOCOL_INTERNAL_INDEX],
|
|
&(adsi[i].TSProtocol), sizeof(DWORD), &cbActual, 0, NULL));
|
|
// Application Type
|
|
CALL(JetRetrieveColumn(sesid, sessdirtableid,
|
|
sesdircolumnid[SESSDIR_APPTYPE_INTERNAL_INDEX],
|
|
adsi[i].AppType, 512, &cbActual, 0, NULL));
|
|
// ResolutionWidth
|
|
CALL(JetRetrieveColumn(sesid, sessdirtableid,
|
|
sesdircolumnid[SESSDIR_RESWIDTH_INTERNAL_INDEX],
|
|
&(adsi[i].ResolutionWidth), sizeof(DWORD), &cbActual, 0,
|
|
NULL));
|
|
// ResolutionHeight
|
|
CALL(JetRetrieveColumn(sesid, sessdirtableid,
|
|
sesdircolumnid[SESSDIR_RESHEIGHT_INTERNAL_INDEX],
|
|
&(adsi[i].ResolutionHeight), sizeof(DWORD), &cbActual, 0,
|
|
NULL));
|
|
// Color Depth
|
|
CALL(JetRetrieveColumn(sesid, sessdirtableid,
|
|
sesdircolumnid[SESSDIR_COLORDEPTH_INTERNAL_INDEX],
|
|
&(adsi[i].ColorDepth), sizeof(DWORD), &cbActual, 0, NULL));
|
|
// CreateTimeLow
|
|
CALL(JetRetrieveColumn(sesid, sessdirtableid,
|
|
sesdircolumnid[SESSDIR_CTLOW_INTERNAL_INDEX],
|
|
&(adsi[i].CreateTimeLow), sizeof(DWORD), &cbActual, 0,
|
|
NULL));
|
|
// CreateTimeHigh
|
|
CALL(JetRetrieveColumn(sesid, sessdirtableid,
|
|
sesdircolumnid[SESSDIR_CTHIGH_INTERNAL_INDEX],
|
|
&(adsi[i].CreateTimeHigh), sizeof(DWORD), &cbActual, 0,
|
|
NULL));
|
|
// DisconnectTimeLow
|
|
CALL(JetRetrieveColumn(sesid, sessdirtableid,
|
|
sesdircolumnid[SESSDIR_DTLOW_INTERNAL_INDEX],
|
|
&(adsi[i].DisconnectTimeLow), sizeof(DWORD), &cbActual, 0,
|
|
NULL));
|
|
// DisconnectTimeHigh
|
|
CALL(JetRetrieveColumn(sesid, sessdirtableid,
|
|
sesdircolumnid[SESSDIR_DTHIGH_INTERNAL_INDEX],
|
|
&(adsi[i].DisconnectTimeHigh), sizeof(DWORD), &cbActual, 0,
|
|
NULL));
|
|
// State
|
|
// This is retrieving a byte that is 0xff or 0x0 into a DWORD
|
|
// pointer.
|
|
CALL(JetRetrieveColumn(sesid, sessdirtableid,
|
|
sesdircolumnid[SESSDIR_STATE_INTERNAL_INDEX],
|
|
&(adsi[i].State), sizeof(BYTE), &cbActual, 0,
|
|
NULL));
|
|
|
|
i += 1;
|
|
}
|
|
|
|
// Move to the next matching record.
|
|
err = JetMove(sesid, sessdirtableid, JET_MoveNext, 0);
|
|
}
|
|
|
|
*pNumSessions = i;
|
|
|
|
CALL(JetCommitTransaction(sesid, 0));
|
|
|
|
CALL(JetCloseTable(sesid, servdirtableid));
|
|
CALL(JetCloseTable(sesid, sessdirtableid));
|
|
CALL(JetCloseTable(sesid, clusdirtableid));
|
|
|
|
CALL(JetCloseDatabase(sesid, dbid, 0));
|
|
|
|
CALL(JetEndSession(sesid, 0));
|
|
|
|
#ifdef DBG
|
|
OutputAllTables();
|
|
#endif // DBG
|
|
|
|
return 0;
|
|
|
|
HandleError:
|
|
// Deallocate memory.
|
|
if (adsi != NULL) {
|
|
for (j = 0; j < TSSD_MaxDisconnectedSessions; j++) {
|
|
if (adsi[j].ServerAddress)
|
|
MIDL_user_free(adsi[j].ServerAddress);
|
|
if (adsi[j].AppType)
|
|
MIDL_user_free(adsi[j].AppType);
|
|
}
|
|
}
|
|
|
|
// Can't really recover. Just bail out.
|
|
if (sesid != JET_sesidNil) {
|
|
(VOID) JetRollback(sesid, JET_bitRollbackAll);
|
|
|
|
// Force the session closed.
|
|
(VOID) JetEndSession(sesid, JET_bitForceSessionClosed);
|
|
}
|
|
|
|
TSDISErrorOut(L"WARNING: TSSDRpcGetUserDisconnectedSessions() initiate TSSDPurgeServer()\n");
|
|
|
|
// Delete the server and close the context handle. Their states are bad.
|
|
TSSDPurgeServer(PtrToUlong(*hCI));
|
|
*hCI = NULL;
|
|
|
|
return (DWORD) E_FAIL;
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
// TSSDRpcCreateSession
|
|
//
|
|
// Called on a session logon.
|
|
/****************************************************************************/
|
|
DWORD TSSDRpcCreateSession(
|
|
handle_t Binding,
|
|
HCLIENTINFO *hCI,
|
|
WCHAR __RPC_FAR *UserName,
|
|
WCHAR __RPC_FAR *Domain,
|
|
DWORD SessionID,
|
|
DWORD TSProtocol,
|
|
WCHAR __RPC_FAR *AppType,
|
|
DWORD ResolutionWidth,
|
|
DWORD ResolutionHeight,
|
|
DWORD ColorDepth,
|
|
DWORD CreateTimeLow,
|
|
DWORD CreateTimeHigh)
|
|
{
|
|
JET_ERR err;
|
|
JET_SESID sesid = JET_sesidNil;
|
|
JET_DBID dbid;
|
|
JET_TABLEID sessdirtableid;
|
|
JET_TABLEID servdirtableid;
|
|
JET_SETCOLUMN scSessDir[NUM_SESSDIRCOLUMNS];
|
|
CLIENTINFO *pCI = (CLIENTINFO *) hCI;
|
|
unsigned count;
|
|
int zero = 0;
|
|
unsigned long cbActual;
|
|
char state = 0;
|
|
long numDeletedSession = 0;
|
|
|
|
// "unreferenced" parameter (referenced by RPC)
|
|
Binding;
|
|
|
|
|
|
TSDISErrorOut(L"Inside TSSDRpcCreateSession, ServID=%d, "
|
|
L"UserName=%s, Domain=%s, SessID=%d, TSProt=%d, AppType=%s, "
|
|
L"ResWidth=%d, ResHeight=%d, ColorDepth=%d\n", *pCI, UserName,
|
|
Domain, SessionID, TSProtocol, AppType, ResolutionWidth,
|
|
ResolutionHeight, ColorDepth);
|
|
TSDISErrorTimeOut(L" CreateTime=%s\n", CreateTimeLow, CreateTimeHigh);
|
|
|
|
memset(&scSessDir[0], 0, sizeof(JET_SETCOLUMN) * NUM_SESSDIRCOLUMNS);
|
|
|
|
CALL(JetBeginSession(g_instance, &sesid, "user", ""));
|
|
CALL(JetOpenDatabase(sesid, JETDBFILENAME, "", &dbid, 0));
|
|
|
|
CALL(JetOpenTable(sesid, dbid, "SessionDirectory", NULL, 0, 0,
|
|
&sessdirtableid));
|
|
CALL(JetOpenTable(sesid, dbid, "ServerDirectory", NULL, 0, 0,
|
|
&servdirtableid));
|
|
|
|
CALL(JetBeginTransaction(sesid));
|
|
|
|
// Verify that the ServerID passed in was OK.
|
|
if (TSSDVerifyServerIDValid(sesid, servdirtableid, PtrToUlong(*hCI)) == FALSE) {
|
|
TSDISErrorOut(L"Invalid ServerID was passed in\n");
|
|
goto HandleError;
|
|
}
|
|
|
|
numDeletedSession = DeleteExistingServerSession( sesid, sessdirtableid, pCI, SessionID );
|
|
if( numDeletedSession < 0 ) {
|
|
goto HandleError;
|
|
}
|
|
|
|
err = JetMove(sesid, sessdirtableid, JET_MoveLast, 0);
|
|
|
|
CALL(JetPrepareUpdate(sesid, sessdirtableid, JET_prepInsert));
|
|
|
|
for (count = 0; count < NUM_SESSDIRCOLUMNS; count++) {
|
|
scSessDir[count].columnid = sesdircolumnid[count];
|
|
scSessDir[count].cbData = 4; // most of them, set the rest individually
|
|
scSessDir[count].itagSequence = 1;
|
|
}
|
|
scSessDir[SESSDIR_USERNAME_INTERNAL_INDEX].cbData =
|
|
(unsigned) (wcslen(UserName) + 1) * sizeof(WCHAR);
|
|
scSessDir[SESSDIR_DOMAIN_INTERNAL_INDEX].cbData =
|
|
(unsigned) (wcslen(Domain) + 1) * sizeof(WCHAR);
|
|
scSessDir[SESSDIR_APPTYPE_INTERNAL_INDEX].cbData =
|
|
(unsigned) (wcslen(AppType) + 1) * sizeof(WCHAR);
|
|
scSessDir[SESSDIR_STATE_INTERNAL_INDEX].cbData = sizeof(char);
|
|
|
|
scSessDir[SESSDIR_USERNAME_INTERNAL_INDEX].pvData = UserName;
|
|
scSessDir[SESSDIR_DOMAIN_INTERNAL_INDEX].pvData = Domain;
|
|
scSessDir[SESSDIR_SERVERID_INTERNAL_INDEX].pvData = pCI;
|
|
scSessDir[SESSDIR_SESSIONID_INTERNAL_INDEX].pvData = &SessionID;
|
|
scSessDir[SESSDIR_TSPROTOCOL_INTERNAL_INDEX].pvData = &TSProtocol;
|
|
scSessDir[SESSDIR_CTLOW_INTERNAL_INDEX].pvData = &CreateTimeLow;
|
|
scSessDir[SESSDIR_CTHIGH_INTERNAL_INDEX].pvData = &CreateTimeHigh;
|
|
scSessDir[SESSDIR_DTLOW_INTERNAL_INDEX].pvData = &zero;
|
|
scSessDir[SESSDIR_DTHIGH_INTERNAL_INDEX].pvData = &zero;
|
|
scSessDir[SESSDIR_APPTYPE_INTERNAL_INDEX].pvData = AppType;
|
|
scSessDir[SESSDIR_RESWIDTH_INTERNAL_INDEX].pvData = &ResolutionWidth;
|
|
scSessDir[SESSDIR_RESHEIGHT_INTERNAL_INDEX].pvData = &ResolutionHeight;
|
|
scSessDir[SESSDIR_COLORDEPTH_INTERNAL_INDEX].pvData = &ColorDepth;
|
|
scSessDir[SESSDIR_STATE_INTERNAL_INDEX].pvData = &state;
|
|
|
|
CALL(JetSetColumns(sesid, sessdirtableid, scSessDir, NUM_SESSDIRCOLUMNS));
|
|
CALL(JetUpdate(sesid, sessdirtableid, NULL, 0, &cbActual));
|
|
CALL(JetCommitTransaction(sesid, 0));
|
|
|
|
CALL(JetCloseTable(sesid, sessdirtableid));
|
|
CALL(JetCloseTable(sesid, servdirtableid));
|
|
|
|
CALL(JetCloseDatabase(sesid, dbid, 0));
|
|
|
|
CALL(JetEndSession(sesid, 0));
|
|
|
|
return 0;
|
|
|
|
HandleError:
|
|
if (sesid != JET_sesidNil) {
|
|
// Can't really recover. Just bail out.
|
|
(VOID) JetRollback(sesid, JET_bitRollbackAll);
|
|
|
|
// Force the session closed.
|
|
(VOID) JetEndSession(sesid, JET_bitForceSessionClosed);
|
|
}
|
|
|
|
TSDISErrorOut(L"WARNING: TSSDRpcCreateSession failed, start TSSDPurgeServer()\n");
|
|
|
|
// Delete the server and close the context handle. Their states are bad.
|
|
TSSDPurgeServer(PtrToUlong(*hCI));
|
|
*hCI = NULL;
|
|
|
|
return (DWORD) E_FAIL;
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
// TSSDRpcDeleteSession
|
|
//
|
|
// Called on a session logoff.
|
|
/****************************************************************************/
|
|
DWORD TSSDRpcDeleteSession(
|
|
handle_t Binding,
|
|
HCLIENTINFO *hCI,
|
|
DWORD SessionID)
|
|
{
|
|
JET_ERR err;
|
|
JET_SESID sesid = JET_sesidNil;
|
|
JET_DBID dbid;
|
|
JET_TABLEID sessdirtableid;
|
|
JET_TABLEID servdirtableid;
|
|
CLIENTINFO *pCI = (CLIENTINFO *) hCI;
|
|
|
|
// "unreferenced" parameter (referenced by RPC)
|
|
Binding;
|
|
|
|
TSDISErrorOut(L"In DelSession, ServID=%d, "
|
|
L"SessID=%d\n", *pCI, SessionID);
|
|
|
|
|
|
CALL(JetBeginSession(g_instance, &sesid, "user", ""));
|
|
CALL(JetOpenDatabase(sesid, JETDBFILENAME, "", &dbid, 0));
|
|
|
|
CALL(JetOpenTable(sesid, dbid, "SessionDirectory", NULL, 0, 0,
|
|
&sessdirtableid));
|
|
CALL(JetOpenTable(sesid, dbid, "ServerDirectory", NULL, 0, 0,
|
|
&servdirtableid));
|
|
|
|
CALL(JetBeginTransaction(sesid));
|
|
|
|
// Verify that the ServerID passed in was OK.
|
|
if (TSSDVerifyServerIDValid(sesid, servdirtableid, PtrToUlong(*hCI)) == FALSE) {
|
|
TSDISErrorOut(L"Invalid ServerID was passed in\n");
|
|
goto HandleError;
|
|
}
|
|
|
|
// Delete all sessions in session directory that have this serverid
|
|
CALL(JetSetCurrentIndex(sesid, sessdirtableid, "primaryIndex"));
|
|
CALL(JetMakeKey(sesid, sessdirtableid, pCI,
|
|
sizeof(*pCI), JET_bitNewKey));
|
|
CALL(JetMakeKey(sesid, sessdirtableid, &SessionID, sizeof(SessionID),
|
|
0));
|
|
|
|
CALL(JetSeek(sesid, sessdirtableid, JET_bitSeekEQ));
|
|
|
|
CALL(JetDelete(sesid, sessdirtableid));
|
|
|
|
CALL(JetCommitTransaction(sesid, 0));
|
|
|
|
CALL(JetCloseTable(sesid, sessdirtableid));
|
|
CALL(JetCloseTable(sesid, servdirtableid));
|
|
|
|
CALL(JetCloseDatabase(sesid, dbid, 0));
|
|
|
|
CALL(JetEndSession(sesid, 0));
|
|
|
|
return 0;
|
|
|
|
HandleError:
|
|
if (sesid != JET_sesidNil) {
|
|
// Can't really recover. Just bail out.
|
|
(VOID) JetRollback(sesid, JET_bitRollbackAll);
|
|
|
|
// Force the session closed.
|
|
(VOID) JetEndSession(sesid, JET_bitForceSessionClosed);
|
|
}
|
|
|
|
TSDISErrorOut(L"WARNING: DelSession can't find ServID=%d SessID=%d, start TSSDPurgeServer()\n", *pCI, SessionID);
|
|
|
|
// Delete the server and close the context handle. Their states are bad.
|
|
TSSDPurgeServer(PtrToUlong(*hCI));
|
|
*hCI = NULL;
|
|
|
|
return (DWORD) E_FAIL;
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
// TSSDRpcSetSessionDisconnected
|
|
//
|
|
// Called on a session disconnection.
|
|
/****************************************************************************/
|
|
DWORD TSSDRpcSetSessionDisconnected(
|
|
handle_t Binding,
|
|
HCLIENTINFO *hCI,
|
|
DWORD SessionID,
|
|
DWORD DiscTimeLow,
|
|
DWORD DiscTimeHigh)
|
|
{
|
|
unsigned long cbActual;
|
|
JET_ERR err;
|
|
JET_SESID sesid = JET_sesidNil;
|
|
JET_DBID dbid;
|
|
JET_TABLEID sessdirtableid;
|
|
JET_TABLEID servdirtableid;
|
|
CLIENTINFO *pCI = (CLIENTINFO *) hCI;
|
|
char one = 1;
|
|
DWORD rc = (DWORD) E_FAIL;
|
|
|
|
// "unreferenced" parameter (referenced by RPC)
|
|
Binding;
|
|
|
|
TSDISErrorOut(L"In SetSessDisc, ServID=%d, SessID=%d\n", *pCI, SessionID);
|
|
TSDISErrorTimeOut(L" DiscTime=%s\n", DiscTimeLow, DiscTimeHigh);
|
|
|
|
CALL(JetBeginSession(g_instance, &sesid, "user", ""));
|
|
CALL(JetOpenDatabase(sesid, JETDBFILENAME, "", &dbid, 0));
|
|
|
|
CALL(JetOpenTable(sesid, dbid, "SessionDirectory", NULL, 0, 0,
|
|
&sessdirtableid));
|
|
CALL(JetOpenTable(sesid, dbid, "ServerDirectory", NULL, 0, 0,
|
|
&servdirtableid));
|
|
|
|
CALL(JetBeginTransaction(sesid));
|
|
|
|
// Verify that the ServerID passed in was OK.
|
|
if (TSSDVerifyServerIDValid(sesid, servdirtableid, PtrToUlong(*hCI)) == FALSE) {
|
|
TSDISErrorOut(L"Invalid ServerID was passed in\n");
|
|
goto HandleError;
|
|
}
|
|
CALL(JetSetCurrentIndex(sesid, sessdirtableid, "primaryIndex"));
|
|
|
|
// find the record with the serverid, sessionid we are looking for
|
|
CALL(JetMakeKey(sesid, sessdirtableid, pCI, sizeof(DWORD),
|
|
JET_bitNewKey));
|
|
CALL(JetMakeKey(sesid, sessdirtableid, &SessionID, sizeof(DWORD), 0));
|
|
|
|
CALL(JetSeek(sesid, sessdirtableid, JET_bitSeekEQ));
|
|
|
|
CALL(JetPrepareUpdate(sesid, sessdirtableid, JET_prepReplace));
|
|
CALL(JetSetColumn(sesid, sessdirtableid, sesdircolumnid[
|
|
SESSDIR_STATE_INTERNAL_INDEX], &one, sizeof(one), 0, NULL));
|
|
CALL(JetUpdate(sesid, sessdirtableid, NULL, 0, &cbActual));
|
|
|
|
CALL(JetCommitTransaction(sesid, 0));
|
|
|
|
CALL(JetCloseTable(sesid, sessdirtableid));
|
|
CALL(JetCloseTable(sesid, servdirtableid));
|
|
|
|
CALL(JetCloseDatabase(sesid, dbid, 0));
|
|
|
|
CALL(JetEndSession(sesid, 0));
|
|
|
|
rc = 0;
|
|
return rc;
|
|
|
|
HandleError:
|
|
if (sesid != JET_sesidNil) {
|
|
// Can't really recover. Just bail out.
|
|
(VOID) JetRollback(sesid, JET_bitRollbackAll);
|
|
|
|
// Force the session closed
|
|
(VOID) JetEndSession(sesid, JET_bitForceSessionClosed);
|
|
}
|
|
|
|
TSDISErrorOut(L"WARNING: SetSessDisc can't find ServID=%d SessID=%d, start TSSDPurgeServer()\n", *pCI, SessionID);
|
|
|
|
// Delete the server and close the context handle. Their states are bad.
|
|
TSSDPurgeServer(PtrToUlong(*hCI));
|
|
*hCI = NULL;
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
// TSSDRpcSetSessionReconnected
|
|
//
|
|
// Called on a session reconnection.
|
|
/****************************************************************************/
|
|
DWORD TSSDRpcSetSessionReconnected(
|
|
handle_t Binding,
|
|
HCLIENTINFO *hCI,
|
|
DWORD SessionID,
|
|
DWORD TSProtocol,
|
|
DWORD ResWidth,
|
|
DWORD ResHeight,
|
|
DWORD ColorDepth)
|
|
{
|
|
JET_ERR err;
|
|
JET_SESID sesid = JET_sesidNil;
|
|
JET_DBID dbid;
|
|
JET_TABLEID sessdirtableid;
|
|
JET_TABLEID servdirtableid;
|
|
CLIENTINFO *pCI = (CLIENTINFO *) hCI;
|
|
DWORD rc = (DWORD) E_FAIL;
|
|
|
|
char zero = 0;
|
|
unsigned long cbActual;
|
|
|
|
// "unreferenced" parameter (referenced by RPC)
|
|
Binding;
|
|
|
|
TSDISErrorOut(L"In SetSessRec, ServID=%d, SessID=%d, TSProt=%d, "
|
|
L"ResWid=%d, ResHt=%d, ColDepth=%d\n", *pCI,
|
|
SessionID, TSProtocol, ResWidth, ResHeight,
|
|
ColorDepth);
|
|
|
|
|
|
CALL(JetBeginSession(g_instance, &sesid, "user", ""));
|
|
CALL(JetOpenDatabase(sesid, JETDBFILENAME, "", &dbid, 0));
|
|
|
|
CALL(JetOpenTable(sesid, dbid, "SessionDirectory", NULL, 0, 0,
|
|
&sessdirtableid));
|
|
CALL(JetOpenTable(sesid, dbid, "ServerDirectory", NULL, 0, 0,
|
|
&servdirtableid));
|
|
|
|
CALL(JetBeginTransaction(sesid));
|
|
|
|
// Verify that the ServerID passed in was OK.
|
|
if (TSSDVerifyServerIDValid(sesid, servdirtableid, PtrToUlong(*hCI)) == FALSE) {
|
|
TSDISErrorOut(L"Invalid ServerID was passed in\n");
|
|
goto HandleError;
|
|
}
|
|
|
|
CALL(JetSetCurrentIndex(sesid, sessdirtableid, "primaryIndex"));
|
|
|
|
// Find the record with the serverid, sessionid we are looking for.
|
|
CALL(JetMakeKey(sesid, sessdirtableid, pCI, sizeof(DWORD),
|
|
JET_bitNewKey));
|
|
CALL(JetMakeKey(sesid, sessdirtableid, &SessionID, sizeof(DWORD), 0));
|
|
|
|
CALL(JetSeek(sesid, sessdirtableid, JET_bitSeekEQ));
|
|
|
|
CALL(JetPrepareUpdate(sesid, sessdirtableid, JET_prepReplace));
|
|
CALL(JetSetColumn(sesid, sessdirtableid, sesdircolumnid[
|
|
SESSDIR_TSPROTOCOL_INTERNAL_INDEX], &TSProtocol, sizeof(TSProtocol),
|
|
0, NULL));
|
|
CALL(JetSetColumn(sesid, sessdirtableid, sesdircolumnid[
|
|
SESSDIR_RESWIDTH_INTERNAL_INDEX], &ResWidth, sizeof(ResWidth),
|
|
0, NULL));
|
|
CALL(JetSetColumn(sesid, sessdirtableid, sesdircolumnid[
|
|
SESSDIR_RESHEIGHT_INTERNAL_INDEX], &ResHeight, sizeof(ResHeight),
|
|
0, NULL));
|
|
CALL(JetSetColumn(sesid, sessdirtableid, sesdircolumnid[
|
|
SESSDIR_COLORDEPTH_INTERNAL_INDEX], &ColorDepth, sizeof(ColorDepth),
|
|
0, NULL));
|
|
CALL(JetSetColumn(sesid, sessdirtableid, sesdircolumnid[
|
|
SESSDIR_STATE_INTERNAL_INDEX], &zero, sizeof(zero), 0, NULL));
|
|
CALL(JetUpdate(sesid, sessdirtableid, NULL, 0, &cbActual));
|
|
|
|
CALL(JetCommitTransaction(sesid, 0));
|
|
|
|
CALL(JetCloseTable(sesid, sessdirtableid));
|
|
CALL(JetCloseTable(sesid, servdirtableid));
|
|
|
|
CALL(JetCloseDatabase(sesid, dbid, 0));
|
|
|
|
CALL(JetEndSession(sesid, 0));
|
|
|
|
rc = 0;
|
|
return rc;
|
|
|
|
HandleError:
|
|
if (sesid != JET_sesidNil) {
|
|
// Can't really recover. Just bail out.
|
|
(VOID) JetRollback(sesid, JET_bitRollbackAll);
|
|
|
|
// Force the session closed.
|
|
(VOID) JetEndSession(sesid, JET_bitForceSessionClosed);
|
|
}
|
|
|
|
TSDISErrorOut(L"WARNING: SetSessRec can't find ServID=%d SessID=%d, start TSSDPurgeServer()\n", *pCI, SessionID);
|
|
|
|
// Delete the server and close the context handle. Their states are bad.
|
|
TSSDPurgeServer(PtrToUlong(*hCI));
|
|
*hCI = NULL;
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
DWORD TSSDRpcSetServerReconnectPending(
|
|
handle_t Binding,
|
|
WCHAR __RPC_FAR *ServerAddress,
|
|
DWORD AlmostTimeLow,
|
|
DWORD AlmostTimeHigh)
|
|
{
|
|
// Ignored parameters
|
|
Binding;
|
|
AlmostTimeLow;
|
|
AlmostTimeHigh;
|
|
|
|
|
|
return TSSDSetServerAITInternal(ServerAddress, FALSE, NULL);
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
// TSSDRpcUpdateConfigurationSetting
|
|
//
|
|
// Extensible interface to update a configuration setting.
|
|
/****************************************************************************/
|
|
DWORD TSSDSetServerAddress(HCLIENTINFO *hCI, WCHAR *ServerName)
|
|
{
|
|
JET_ERR err;
|
|
JET_SESID sesid = JET_sesidNil;
|
|
JET_DBID dbid;
|
|
JET_TABLEID servdirtableid;
|
|
unsigned long cbActual;
|
|
WCHAR Msg[SDNAMELENGTH * 2 + 3];
|
|
DWORD rc = (DWORD) E_FAIL;
|
|
|
|
TSDISErrorOut(L"INFO: TSSDSetServerAddress ServID=%d, %s\n", *hCI, ServerName);
|
|
|
|
CALL(JetBeginSession(g_instance, &sesid, "user", ""));
|
|
|
|
CALL(JetOpenDatabase(sesid, JETDBFILENAME, "", &dbid, 0));
|
|
|
|
CALL(JetOpenTable(sesid, dbid, "ServerDirectory", NULL, 0, 0,
|
|
&servdirtableid));
|
|
|
|
// Find the server in the server directory
|
|
CALL(JetBeginTransaction(sesid));
|
|
|
|
CALL(JetSetCurrentIndex(sesid, servdirtableid, "ServerIDIndex"));
|
|
CALL(JetMakeKey(sesid, servdirtableid, (const void *)hCI, sizeof(DWORD),
|
|
JET_bitNewKey));
|
|
CALL(JetSeek(sesid, servdirtableid, JET_bitSeekEQ));
|
|
|
|
// Get the server DNS name
|
|
cbActual = SDNAMELENGTH * sizeof(WCHAR);
|
|
CALL(JetRetrieveColumn(sesid, servdirtableid, servdircolumnid[
|
|
SERVDIR_SERVDNSNAME_INTERNAL_INDEX], Msg,
|
|
cbActual, &cbActual, 0, NULL));
|
|
|
|
// Prepare to update.
|
|
CALL(JetPrepareUpdate(sesid, servdirtableid, JET_prepReplace));
|
|
|
|
// Now set the column to what we want
|
|
CALL(JetSetColumn(sesid, servdirtableid, servdircolumnid[
|
|
SERVDIR_SERVADDR_INTERNAL_INDEX], (void *) ServerName,
|
|
(unsigned) (wcslen(ServerName) + 1) * sizeof(WCHAR), 0,
|
|
NULL));
|
|
|
|
CALL(JetUpdate(sesid, servdirtableid, NULL, 0, &cbActual));
|
|
|
|
|
|
CALL(JetCommitTransaction(sesid, 0));
|
|
|
|
// Clean up.
|
|
CALL(JetCloseTable(sesid, servdirtableid));
|
|
|
|
CALL(JetCloseDatabase(sesid, dbid, 0));
|
|
|
|
CALL(JetEndSession(sesid, 0));
|
|
|
|
// Construct log msg to record TS joining SD
|
|
wcscat(Msg, L"(");
|
|
wcsncat(Msg, ServerName, SDNAMELENGTH);
|
|
wcscat(Msg, L")");
|
|
PostSessDirErrorMsgEvent(EVENT_SUCCESS_JOIN_SESSIONDIRECTORY, Msg, EVENTLOG_SUCCESS);
|
|
|
|
rc = 0;
|
|
return rc;
|
|
|
|
HandleError:
|
|
if (sesid != JET_sesidNil) {
|
|
// Can't really recover. Just bail out.
|
|
(VOID) JetRollback(sesid, JET_bitRollbackAll);
|
|
|
|
// Force the session closed
|
|
(VOID) JetEndSession(sesid, JET_bitForceSessionClosed);
|
|
}
|
|
|
|
TSDISErrorOut(L"WARNING: TSSDSetServerAddress can't find ServID=%d, start TSSDPurgeServer()\n", *hCI);
|
|
TSSDPurgeServer(PtrToUlong(*hCI));
|
|
|
|
// Close the context handle.
|
|
*hCI = NULL;
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
// TSSDRpcUpdateConfigurationSetting
|
|
//
|
|
// Extensible interface to update a configuration setting.
|
|
/****************************************************************************/
|
|
DWORD TSSDRpcUpdateConfigurationSetting(
|
|
handle_t Binding,
|
|
HCLIENTINFO *hCI,
|
|
DWORD dwSetting,
|
|
DWORD dwSettingLength,
|
|
BYTE __RPC_FAR *pbValue)
|
|
{
|
|
// Unreferenced parameters.
|
|
Binding;
|
|
hCI;
|
|
dwSetting;
|
|
dwSettingLength;
|
|
pbValue;
|
|
|
|
if (dwSetting == SDCONFIG_SERVER_ADDRESS) {
|
|
TSDISErrorOut(L"Server is setting its address as %s\n",
|
|
(WCHAR *) pbValue);
|
|
return TSSDSetServerAddress(hCI, (WCHAR *) pbValue);
|
|
}
|
|
|
|
return (DWORD) E_NOTIMPL;
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
// TSSDSetServerAITInternal
|
|
//
|
|
// Called on a client redirection from one server to another, to let the
|
|
// integrity service determine how to ping the redirection target machine.
|
|
//
|
|
// Args:
|
|
// ServerAddress (in) - the server address to set values for
|
|
// bResetToZero (in) - whether to reset all AIT values to 0
|
|
// FailureCount (in/out) - Pointer to nonzero on entry means increment the
|
|
// failure count. Returns the result failure count.
|
|
/****************************************************************************/
|
|
DWORD TSSDSetServerAITInternal(
|
|
WCHAR *ServerAddress,
|
|
DWORD bResetToZero,
|
|
DWORD *FailureCount)
|
|
{
|
|
JET_ERR err;
|
|
JET_SESID sesid = JET_sesidNil;
|
|
JET_DBID dbid;
|
|
JET_TABLEID servdirtableid;
|
|
DWORD AITFromServDirLow;
|
|
DWORD AITFromServDirHigh;
|
|
unsigned long cbActual;
|
|
DWORD rc = (DWORD) E_FAIL;
|
|
|
|
TSDISErrorOut(L"SetServAITInternal: ServAddr=%s, bResetToZero=%d, bIncFail"
|
|
L"=%d\n", ServerAddress, bResetToZero, (FailureCount == NULL) ?
|
|
0 : *FailureCount);
|
|
|
|
CALL(JetBeginSession(g_instance, &sesid, "user", ""));
|
|
CALL(JetOpenDatabase(sesid, JETDBFILENAME, "", &dbid, 0));
|
|
|
|
CALL(JetOpenTable(sesid, dbid, "ServerDirectory", NULL, 0, 0,
|
|
&servdirtableid));
|
|
|
|
CALL(JetBeginTransaction(sesid));
|
|
CALL(JetSetCurrentIndex(sesid, servdirtableid, "ServNameIndex"));
|
|
|
|
CALL(JetMakeKey(sesid, servdirtableid, ServerAddress, (unsigned)
|
|
(wcslen(ServerAddress) + 1) * sizeof(WCHAR), JET_bitNewKey));
|
|
|
|
CALL(JetSeek(sesid, servdirtableid, JET_bitSeekEQ));
|
|
|
|
// Algorithm for set reconnect pending:
|
|
// 1) If server is not already pending a reconnect,
|
|
// 2) Set the AlmostTimeLow and High to locally computed times (using
|
|
// the times from the wire is dangerous and requires clocks to be the
|
|
// same).
|
|
|
|
// Retrieve the current values of AlmostInTimeLow and High
|
|
CALL(JetRetrieveColumn(sesid, servdirtableid, servdircolumnid[
|
|
SERVDIR_AITLOW_INTERNAL_INDEX], &AITFromServDirLow,
|
|
sizeof(AITFromServDirLow), &cbActual, 0, NULL));
|
|
CALL(JetRetrieveColumn(sesid, servdirtableid, servdircolumnid[
|
|
SERVDIR_AITHIGH_INTERNAL_INDEX], &AITFromServDirHigh,
|
|
sizeof(AITFromServDirHigh), &cbActual, 0, NULL));
|
|
|
|
|
|
// If it's time to reset, reset to 0.
|
|
if (bResetToZero != 0) {
|
|
DWORD zero = 0;
|
|
|
|
CALL(JetPrepareUpdate(sesid, servdirtableid, JET_prepReplace));
|
|
|
|
// Set the columns: Low, High, and NumFailedPings.
|
|
CALL(JetSetColumn(sesid, servdirtableid, servdircolumnid[
|
|
SERVDIR_AITLOW_INTERNAL_INDEX], &zero, sizeof(zero), 0, NULL));
|
|
CALL(JetSetColumn(sesid, servdirtableid, servdircolumnid[
|
|
SERVDIR_AITHIGH_INTERNAL_INDEX], &zero, sizeof(zero), 0, NULL));
|
|
CALL(JetSetColumn(sesid, servdirtableid, servdircolumnid[
|
|
SERVDIR_NUMFAILPINGS_INTERNAL_INDEX], &zero, sizeof(zero), 0,
|
|
NULL));
|
|
|
|
CALL(JetUpdate(sesid, servdirtableid, NULL, 0, &cbActual));
|
|
}
|
|
// Otherwise, if the server isn't already pending a reconnect,
|
|
else if ((AITFromServDirLow == 0) && (AITFromServDirHigh == 0)) {
|
|
FILETIME ft;
|
|
SYSTEMTIME st;
|
|
|
|
// Retrieve the time.
|
|
GetSystemTime(&st);
|
|
SystemTimeToFileTime(&st, &ft);
|
|
|
|
err = JetPrepareUpdate(sesid, servdirtableid, JET_prepReplace);
|
|
|
|
if (JET_errWriteConflict == err) {
|
|
// If we are here, it's that more than two threads are updating the time
|
|
// field at the same time. Since we only need to update it once, so just
|
|
// bail out the other ones, but still return success
|
|
rc = 0;
|
|
goto HandleError;
|
|
}
|
|
else {
|
|
CALL(err);
|
|
}
|
|
|
|
// Set the columns.
|
|
CALL(JetSetColumn(sesid, servdirtableid, servdircolumnid[
|
|
SERVDIR_AITLOW_INTERNAL_INDEX], &(ft.dwLowDateTime),
|
|
sizeof(ft.dwLowDateTime), 0, NULL));
|
|
CALL(JetSetColumn(sesid, servdirtableid, servdircolumnid[
|
|
SERVDIR_AITHIGH_INTERNAL_INDEX], &(ft.dwHighDateTime),
|
|
sizeof(ft.dwHighDateTime), 0, NULL));
|
|
|
|
CALL(JetUpdate(sesid, servdirtableid, NULL, 0, &cbActual));
|
|
}
|
|
// Else if we were told to increment the failure count
|
|
else if (FailureCount != NULL) {
|
|
if (*FailureCount != 0) {
|
|
DWORD FailureCountFromServDir;
|
|
|
|
// Get the current failure count.
|
|
CALL(JetRetrieveColumn(sesid, servdirtableid, servdircolumnid[
|
|
SERVDIR_NUMFAILPINGS_INTERNAL_INDEX],
|
|
&FailureCountFromServDir, sizeof(FailureCountFromServDir),
|
|
&cbActual, 0, NULL));
|
|
|
|
// Set return value, also value used for update.
|
|
*FailureCount = FailureCountFromServDir + 1;
|
|
|
|
CALL(JetPrepareUpdate(sesid, servdirtableid, JET_prepReplace));
|
|
|
|
// Set the column.
|
|
CALL(JetSetColumn(sesid, servdirtableid, servdircolumnid[
|
|
SERVDIR_NUMFAILPINGS_INTERNAL_INDEX],
|
|
FailureCount, sizeof(*FailureCount), 0, NULL));
|
|
CALL(JetUpdate(sesid, servdirtableid, NULL, 0, &cbActual));
|
|
|
|
}
|
|
}
|
|
|
|
CALL(JetCommitTransaction(sesid, 0));
|
|
|
|
CALL(JetCloseTable(sesid, servdirtableid));
|
|
|
|
CALL(JetCloseDatabase(sesid, dbid, 0));
|
|
|
|
CALL(JetEndSession(sesid, 0));
|
|
|
|
rc = 0;
|
|
return rc;
|
|
|
|
HandleError:
|
|
if (sesid != JET_sesidNil) {
|
|
// Can't really recover. Just bail out.
|
|
(VOID) JetRollback(sesid, JET_bitRollbackAll);
|
|
|
|
// Force the session closed
|
|
(VOID) JetEndSession(sesid, JET_bitForceSessionClosed);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
DWORD TSSDRpcRepopulateAllSessions(
|
|
handle_t Binding,
|
|
HCLIENTINFO *hCI,
|
|
DWORD NumSessions,
|
|
TSSD_RepopInfo rpi[])
|
|
{
|
|
JET_ERR err;
|
|
JET_SESID sesid = JET_sesidNil;
|
|
JET_DBID dbid;
|
|
JET_TABLEID sessdirtableid;
|
|
JET_TABLEID servdirtableid;
|
|
JET_SETCOLUMN scSessDir[NUM_SESSDIRCOLUMNS];
|
|
CLIENTINFO *pCI = (CLIENTINFO *) hCI;
|
|
unsigned count; // inside each record
|
|
unsigned iCurrSession;
|
|
unsigned long cbActual;
|
|
char State;
|
|
DWORD rc = (DWORD) E_FAIL;
|
|
long numDeletedSession = 0;
|
|
|
|
// "unreferenced" parameter (referenced by RPC)
|
|
Binding;
|
|
|
|
TSDISErrorOut(L"RepopAllSess: ServID = %d, NumSessions = %d, ...\n",
|
|
*pCI, NumSessions);
|
|
|
|
memset(&scSessDir[0], 0, sizeof(JET_SETCOLUMN) * NUM_SESSDIRCOLUMNS);
|
|
|
|
CALL(JetBeginSession(g_instance, &sesid, "user", ""));
|
|
CALL(JetOpenDatabase(sesid, JETDBFILENAME, "", &dbid, 0));
|
|
|
|
CALL(JetOpenTable(sesid, dbid, "SessionDirectory", NULL, 0, 0,
|
|
&sessdirtableid));
|
|
CALL(JetOpenTable(sesid, dbid, "ServerDirectory", NULL, 0, 0,
|
|
&servdirtableid));
|
|
|
|
CALL(JetBeginTransaction(sesid));
|
|
|
|
// Verify that the ServerID passed in was OK.
|
|
if (TSSDVerifyServerIDValid(sesid, servdirtableid, PtrToUlong(*hCI)) == FALSE) {
|
|
TSDISErrorOut(L"Invalid ServerID was passed in\n");
|
|
goto HandleError;
|
|
}
|
|
|
|
|
|
// Set up some constants for all updates.
|
|
for (count = 0; count < NUM_SESSDIRCOLUMNS; count++) {
|
|
scSessDir[count].columnid = sesdircolumnid[count];
|
|
scSessDir[count].cbData = 4; // most of them, set the rest individually
|
|
scSessDir[count].itagSequence = 1;
|
|
}
|
|
scSessDir[SESSDIR_STATE_INTERNAL_INDEX].cbData = sizeof(char);
|
|
|
|
// Now do each update in a loop.
|
|
for (iCurrSession = 0; iCurrSession < NumSessions; iCurrSession += 1) {
|
|
// make sure session does not exist at this point
|
|
numDeletedSession = DeleteExistingServerSession( sesid, sessdirtableid, pCI, rpi[iCurrSession].SessionID );
|
|
if( numDeletedSession < 0 ) {
|
|
goto HandleError;
|
|
}
|
|
|
|
err = JetMove(sesid, sessdirtableid, JET_MoveLast, 0);
|
|
|
|
CALL(JetPrepareUpdate(sesid, sessdirtableid, JET_prepInsert));
|
|
|
|
TSDISErrorOut(L"RepopAllSess: ServID = %d, SessionId = %d, %s %s...\n",
|
|
*pCI,
|
|
rpi[iCurrSession].SessionID,
|
|
rpi[iCurrSession].UserName,
|
|
rpi[iCurrSession].Domain
|
|
);
|
|
|
|
ASSERT( (wcslen(rpi[iCurrSession].UserName) > 0), (TB, "NULL User Name...") );
|
|
ASSERT( (wcslen(rpi[iCurrSession].Domain) > 0), (TB, "NULL Domain Name...") );
|
|
|
|
scSessDir[SESSDIR_USERNAME_INTERNAL_INDEX].cbData =
|
|
(unsigned) (wcslen(rpi[iCurrSession].UserName) + 1) *
|
|
sizeof(WCHAR);
|
|
scSessDir[SESSDIR_DOMAIN_INTERNAL_INDEX].cbData =
|
|
(unsigned) (wcslen(rpi[iCurrSession].Domain) + 1) *
|
|
sizeof(WCHAR);
|
|
scSessDir[SESSDIR_APPTYPE_INTERNAL_INDEX].cbData =
|
|
(unsigned) (wcslen(rpi[iCurrSession].AppType) + 1) *
|
|
sizeof(WCHAR);
|
|
|
|
scSessDir[SESSDIR_USERNAME_INTERNAL_INDEX].pvData =
|
|
rpi[iCurrSession].UserName;
|
|
scSessDir[SESSDIR_DOMAIN_INTERNAL_INDEX].pvData =
|
|
rpi[iCurrSession].Domain;
|
|
scSessDir[SESSDIR_SERVERID_INTERNAL_INDEX].pvData = pCI;
|
|
scSessDir[SESSDIR_SESSIONID_INTERNAL_INDEX].pvData =
|
|
&rpi[iCurrSession].SessionID;
|
|
scSessDir[SESSDIR_TSPROTOCOL_INTERNAL_INDEX].pvData =
|
|
&rpi[iCurrSession].TSProtocol;
|
|
scSessDir[SESSDIR_CTLOW_INTERNAL_INDEX].pvData =
|
|
&rpi[iCurrSession].CreateTimeLow;
|
|
scSessDir[SESSDIR_CTHIGH_INTERNAL_INDEX].pvData =
|
|
&rpi[iCurrSession].CreateTimeHigh;
|
|
scSessDir[SESSDIR_DTLOW_INTERNAL_INDEX].pvData =
|
|
&rpi[iCurrSession].DisconnectTimeLow;
|
|
scSessDir[SESSDIR_DTHIGH_INTERNAL_INDEX].pvData =
|
|
&rpi[iCurrSession].DisconnectTimeHigh;
|
|
scSessDir[SESSDIR_APPTYPE_INTERNAL_INDEX].pvData =
|
|
rpi[iCurrSession].AppType;
|
|
scSessDir[SESSDIR_RESWIDTH_INTERNAL_INDEX].pvData =
|
|
&rpi[iCurrSession].ResolutionWidth;
|
|
scSessDir[SESSDIR_RESHEIGHT_INTERNAL_INDEX].pvData =
|
|
&rpi[iCurrSession].ResolutionHeight;
|
|
scSessDir[SESSDIR_COLORDEPTH_INTERNAL_INDEX].pvData =
|
|
&rpi[iCurrSession].ColorDepth;
|
|
|
|
State = (char) rpi[iCurrSession].State;
|
|
scSessDir[SESSDIR_STATE_INTERNAL_INDEX].pvData = &State;
|
|
|
|
CALL(JetSetColumns(sesid, sessdirtableid, scSessDir,
|
|
NUM_SESSDIRCOLUMNS));
|
|
CALL(JetUpdate(sesid, sessdirtableid, NULL, 0, &cbActual));
|
|
}
|
|
|
|
CALL(JetCommitTransaction(sesid, 0));
|
|
|
|
CALL(JetCloseTable(sesid, sessdirtableid));
|
|
CALL(JetCloseTable(sesid, servdirtableid));
|
|
|
|
CALL(JetCloseDatabase(sesid, dbid, 0));
|
|
|
|
CALL(JetEndSession(sesid, 0));
|
|
|
|
rc = 0;
|
|
return rc;
|
|
|
|
HandleError:
|
|
if (sesid != JET_sesidNil) {
|
|
// Can't really recover. Just bail out.
|
|
(VOID) JetRollback(sesid, JET_bitRollbackAll);
|
|
|
|
// Force the session closed
|
|
(VOID) JetEndSession(sesid, JET_bitForceSessionClosed);
|
|
}
|
|
|
|
TSDISErrorOut(L"WARNING: TSSDRpcRepopulateAllSessions failed, ServID=%d\n", *pCI);
|
|
return rc;
|
|
}
|
|
|
|
|
|
//
|
|
// RPC call that caller uses to see if it have access to Session Directory
|
|
//
|
|
DWORD TSSDRpcPingSD(handle_t Binding)
|
|
{
|
|
Binding;
|
|
|
|
// RPC Security check is done at SDRPCAccessCheck() before this
|
|
// function is hit, just return RPC_S_OK
|
|
|
|
TRC1((TB,"Somebody calls pint sd"));
|
|
return RPC_S_OK;
|
|
}
|
|
|
|
// Called to determine whether a ServerID passed in is valid. TRUE if valid,
|
|
// FALSE otherwise.
|
|
//
|
|
// Must be inside a transaction, and sesid and servdirtableid must be ready to
|
|
// go.
|
|
BOOL TSSDVerifyServerIDValid(JET_SESID sesid, JET_TABLEID servdirtableid,
|
|
DWORD ServerID)
|
|
{
|
|
JET_ERR err;
|
|
|
|
CALL(JetSetCurrentIndex(sesid, servdirtableid, "ServerIDIndex"));
|
|
CALL(JetMakeKey(sesid, servdirtableid, (const void *) &ServerID,
|
|
sizeof(DWORD), JET_bitNewKey));
|
|
// If the ServerID is there, this will succeed, otherwise it will fail and
|
|
// jump to HandleError.
|
|
CALL(JetSeek(sesid, servdirtableid, JET_bitSeekEQ));
|
|
|
|
return TRUE;
|
|
|
|
HandleError:
|
|
return FALSE;
|
|
}
|
|
|
|
// Rundown procedure for when a CLIENTINFO is destroyed as a result of a
|
|
// connection loss or client termination.
|
|
void HCLIENTINFO_rundown(HCLIENTINFO hCI)
|
|
{
|
|
CLIENTINFO CI = PtrToUlong(hCI);
|
|
|
|
TSDISErrorOut(L"WARNING: In HCLIENTINFO_rundown: ServerID=%d\n", CI);
|
|
|
|
if (CI != NULL)
|
|
TSSDPurgeServer(CI);
|
|
|
|
hCI = NULL;
|
|
}
|
|
|
|
#pragma warning (pop)
|