|
|
/*++
Copyright (c) 1998-2000 Microsoft Corporation
Module Name: server.c
Abstract: This module contains the server code for dealing with clients.
Author: Michael Tsang (MikeTs) 02-May-2000
Environment: User mode
Revision History:
--*/
#include "pch.h"
/*++
@doc INTERNAL
@func VOID | ServerThread | Server thread procedure.
@parm IN PVOID | pv | (Not Used).
@rvalue None. --*/
VOID __cdecl ServerThread( IN PVOID pv ) { TRTRACEPROC("ServerThread", 1) RPC_STATUS status; RPC_BINDING_VECTOR *BindingVector = NULL;
TRENTER(("(pv=%p)\n", pv));
if ((status = RpcServerUseProtseq("ncalrpc", RPC_C_PROTSEQ_MAX_REQS_DEFAULT, // "\\pipe\\tracer",
NULL)) != RPC_S_OK) { TRERRPRINT(("RpcServerUseProtseq failed (status=%d)\n", status)); } else if ((status = RpcServerRegisterIf(WTServer_v1_0_s_ifspec, NULL, NULL)) != RPC_S_OK) { TRERRPRINT(("RpcServerRegisterIf failed (status=%d)\n", status)); } else if ((status = RpcServerInqBindings(&BindingVector)) != RPC_S_OK) { TRERRPRINT(("RpcServerInqBindings failed (status=%d)\n", status)); } else if ((status = RpcEpRegister(WTServer_v1_0_s_ifspec, BindingVector, NULL, NULL)) != RPC_S_OK) { RpcBindingVectorFree(&BindingVector); TRERRPRINT(("RpcEpRegister failed (status=%d)\n", status)); } else if ((status = RpcServerRegisterAuthInfo(NULL, RPC_C_AUTHN_WINNT, NULL, NULL)) != RPC_S_OK) { RpcEpUnregister(WTServer_v1_0_s_ifspec, BindingVector, NULL); RpcBindingVectorFree(&BindingVector); TRERRPRINT(("RpcServerRegisterAuthInfo failed (status=%d)\n", status)); } else { status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, FALSE); TRASSERT(status == RPC_S_OK); RpcEpUnregister(WTServer_v1_0_s_ifspec, BindingVector, NULL); RpcBindingVectorFree(&BindingVector); } _endthread();
TREXIT(("!\n")); return; } //ServerThread
/*++
@doc EXTERNAL
@func HCLIENT | WTRegisterClient | Register a new client.
@parm IN handle_t | hBinding | RPC binding handle. @parm IN unsigned char * | pszClientName | Points to the client name string.
@rvalue SUCCESS | Returns new client handle. @rvalue FAILURE | Returns NULL. --*/
HCLIENT WTRegisterClient( IN handle_t hBinding, IN unsigned char *pszClientName ) { TRTRACEPROC("WTRegisterClient", 1) PCLIENT_ENTRY ClientEntry;
TRENTER(("(hBinding=%p,ClientName=%s)\n", hBinding, pszClientName));
ClientEntry = (PCLIENT_ENTRY)malloc(sizeof(CLIENT_ENTRY)); if (ClientEntry != NULL) { memset(ClientEntry, 0, sizeof(*ClientEntry)); lstrcpynA(ClientEntry->szClientName, pszClientName, sizeof(ClientEntry->szClientName)); InsertTailList(&glistClients, &ClientEntry->list); WTGetClientInfo(&ClientEntry->ClientInfo); if ((ClientEntry->ClientInfo.Settings.iVerboseLevel + ClientEntry->ClientInfo.Settings.iTraceLevel + ClientEntry->ClientInfo.Settings.dwfSettings == 0) && (gDefGlobalSettings.iVerboseLevel + gDefGlobalSettings.iTraceLevel + gDefGlobalSettings.dwfSettings != 0)) { ClientEntry->ClientInfo.Settings = gDefGlobalSettings; WTSetClientInfo(&ClientEntry->ClientInfo); }
if (ghwndPropSheet != NULL) { PROPSHEETPAGEA psp; HPROPSHEETPAGE hpsp;
psp.dwSize = sizeof(psp); psp.dwFlags = PSP_USETITLE; psp.hInstance = ghInstance; psp.pszTitle = ClientEntry->szClientName; psp.lParam = (LPARAM)ClientEntry; psp.pszTemplate = (LPSTR)MAKEINTRESOURCE(IDD_CLIENTSETTINGS); psp.pfnDlgProc = ClientSettingsDlgProc; hpsp = CreatePropertySheetPageA(&psp);
ClientEntry->hPage = hpsp; PropSheet_AddPage(ghwndPropSheet, hpsp); } } else { TRERRPRINT(("failed to allocate client entry for %s\n", pszClientName)); }
TREXIT(("=%p\n", ClientEntry)); return (HCLIENT)ClientEntry; } //WTRegisterClient
/*++
@doc EXTERNAL
@func VOID | WTDeregisterClient | Deregister a client.
@parm IN handle_t | hBinding | RPC binding handle. @parm IN HCLIENT | hClient | Client handle.
@rvalue None. --*/
VOID WTDeregisterClient( IN handle_t hBinding, IN HCLIENT hClient ) { TRTRACEPROC("WTDeregisterClient", 1) PCLIENT_ENTRY ClientEntry = (PCLIENT_ENTRY)hClient;
TRENTER(("(hBinding=%p,hClient=%p)\n", hBinding, hClient));
RemoveEntryList(&ClientEntry->list); if (ghwndPropSheet != NULL) { PropSheet_RemovePage(ghwndPropSheet, 0, ClientEntry->hPage); } SendServerRequest(ClientEntry, SRVREQ_TERMINATE, NULL); free(ClientEntry);
TREXIT(("!\n")); return; } //WTDeregisterClient
/*++
@doc EXTERNAL
@func VOID | WTTraceProc | Print the TraceProc text.
@parm IN handle_t | hBinding | RPC binding handle. @parm IN HCLIENT | hClient | Client handle. @parm IN DWORD | dwThreadId | Thread ID. @parm IN int | iIndentLevel | Specifies the level of indentation. @parm IN unsigned char * | pszText | Points to the TraceProc text.
@rvalue None. --*/
VOID WTTraceProc( IN handle_t hBinding, IN HCLIENT hClient, IN DWORD dwThreadId, IN int iIndentLevel, IN unsigned char *pszText ) { TRTRACEPROC("WTTraceProc", 1) PCLIENT_ENTRY ClientEntry = (PCLIENT_ENTRY)hClient; static char szText[1024]; int i; LONG lSel;
TRENTER(("(hBinding=%p,hClient=%p,ThreadId=%x,IndentLevel=%d,Text=%s)\n", hBinding, hClient, dwThreadId, iIndentLevel, pszText));
wsprintfA(szText, "[%08x]%s: ", dwThreadId, ClientEntry->szClientName); for (i = 0; i < iIndentLevel; ++i) { lstrcpyA(&szText[lstrlenA(szText)], "| "); } CopyStr(&szText[lstrlenA(szText)], pszText); lSel = (LONG)SendMessage(ghwndEdit, WM_GETTEXTLENGTH, 0, 0); SendMessage(ghwndEdit, EM_SETSEL, lSel, lSel); SendMessage(ghwndEdit, EM_REPLACESEL, 0, (LPARAM)szText);
TREXIT(("!\n")); return; } //WTTraceProc
/*++
@doc EXTERNAL
@func VOID | WTTraceMsg | Print the TraceMsg text.
@parm IN handle_t | hBinding | RPC binding handle. @parm IN HCLIENT | hClient | Client handle. @parm IN unsigned char * | pszMsg | Points to the TraceMsg text.
@rvalue None. --*/
VOID WTTraceMsg( IN handle_t hBinding, IN HCLIENT hClient, IN unsigned char *pszMsg ) { TRTRACEPROC("WTTraceMsg", 1) PCLIENT_ENTRY ClientEntry = (PCLIENT_ENTRY)hClient; static char szText[1024]; LONG lSel;
TRENTER(("(hBinding=%p,hClient=%p,Msg=%s)\n", hBinding, hClient, pszMsg));
CopyStr(szText, pszMsg); lSel = (LONG)SendMessage(ghwndEdit, WM_GETTEXTLENGTH, 0, 0); SendMessage(ghwndEdit, EM_SETSEL, lSel, lSel); SendMessage(ghwndEdit, EM_REPLACESEL, 0, (LPARAM)szText);
TREXIT(("!\n")); return; } //WTTraceMsg
/*++
@doc EXTERNAL
@func VOID | WTDispatchServerRequests | Dispatch server requests to the client.
@parm IN handle_t | hBinding | RPC binding handle. @parm IN HCLIENT | hClient | Client handle.
@rvalue None. --*/
VOID WTDispatchServerRequests( IN handle_t hBinding, IN HCLIENT hClient ) { TRTRACEPROC("WTDispatchServerRequests", 1) PCLIENT_ENTRY ClientEntry = (PCLIENT_ENTRY)hClient;
TRENTER(("(hBinding=%p,hClient=%p)\n", hBinding, hClient));
TRASSERT(ClientEntry->hSrvReqEvent == 0); ClientEntry->hSrvReqEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (ClientEntry->hSrvReqEvent == NULL) { TRERRPRINT(("failed to create server request event (err=%d)\n", GetLastError())); } else { BOOL fDone = FALSE; LONG Req; DWORD rcWait;
while (!fDone) { Req = InterlockedExchange(&ClientEntry->SrvReq.lRequest, SRVREQ_BUSY); switch (Req) { case SRVREQ_NONE: Req = InterlockedExchange(&ClientEntry->SrvReq.lRequest, Req); TRASSERT(Req == SRVREQ_BUSY); rcWait = WaitForSingleObject(ClientEntry->hSrvReqEvent, INFINITE); if (rcWait != WAIT_OBJECT_0) { TRERRPRINT(("failed waiting for server request event (err=%d)\n", GetLastError)); } break;
case SRVREQ_BUSY: //
// Try again.
//
break;
case SRVREQ_GETCLIENTINFO: WTGetClientInfo((PCLIENTINFO)ClientEntry->SrvReq.Context); Req = InterlockedExchange(&ClientEntry->SrvReq.lRequest, SRVREQ_NONE); TRASSERT(Req == SRVREQ_BUSY); break;
case SRVREQ_SETCLIENTINFO: WTSetClientInfo((PCLIENTINFO)ClientEntry->SrvReq.Context); Req = InterlockedExchange(&ClientEntry->SrvReq.lRequest, SRVREQ_NONE); TRASSERT(Req == SRVREQ_BUSY); break;
case SRVREQ_TERMINATE: fDone = TRUE; Req = InterlockedExchange(&ClientEntry->SrvReq.lRequest, SRVREQ_NONE); TRASSERT(Req == SRVREQ_BUSY); break;
default: TRERRPRINT(("unexpected server request %x.\n", Req)); Req = InterlockedExchange(&ClientEntry->SrvReq.lRequest, SRVREQ_NONE); TRASSERT(Req == SRVREQ_BUSY); } }
CloseHandle(ClientEntry->hSrvReqEvent); ClientEntry->hSrvReqEvent = 0; }
TREXIT(("!\n")); return; } //WTDispatchServerRequests
/*++
@doc INTERNAL
@func VOID | SendServerRequest | Send a server request to the client.
@parm IN PCLIENT_ENTRY | ClientEntry | Points to the client entry. @parm IN LONG | lRequest | Request. @parm IN PVOID | Context | Request context.
@rvalue None. --*/
VOID SendServerRequest( IN PCLIENT_ENTRY ClientEntry, IN LONG lRequest, IN PVOID Context ) { TRTRACEPROC("SendServerRequest", 1) LONG Req;
TRENTER(("(ClientEntry=%p,Request=%x,Context=%p)\n", ClientEntry, lRequest, Context));
while (InterlockedCompareExchange(&ClientEntry->SrvReq.lRequest, SRVREQ_BUSY, SRVREQ_NONE) != SRVREQ_NONE) ; ClientEntry->SrvReq.Context = Context; Req = InterlockedExchange(&ClientEntry->SrvReq.lRequest, lRequest); TRASSERT(Req == SRVREQ_BUSY); SetEvent(ClientEntry->hSrvReqEvent);
TREXIT(("!\n")); return; } //SendServerRequest
/*++
@doc INTERNAL
@func LPSTR | CopyStr | Copy string from source to destination and replaces all the '\n' to '\r\n'.
@parm OUT LPSTR | pszDest | Points to the destination string. @parm IN LPCSTR | pszSrc | Points to the source string.
@rvalue Returns pointer to the destination string. --*/
LPSTR CopyStr( OUT LPSTR pszDest, IN LPCSTR pszSrc ) { TRTRACEPROC("CopyStr", 3) LPSTR psz;
TRENTER(("(Dest=%p,Src=%s)\n", pszDest, pszSrc));
for (psz = pszDest; *pszSrc != '\0'; psz++, pszSrc++) { if (*pszSrc != '\n') { *psz = *pszSrc; } else { *psz = '\r'; psz++; *psz = '\n'; } } *psz = '\0';
TREXIT(("=%p (Dest=%s)\n", pszDest, pszDest)); return pszDest; } //CopyStr
/*++
@doc EXTERNAL
@func void __RPC_FAR * | MIDL_user_allocate | MIDL allocate.
@parm IN size_t | len | size of allocation.
@rvalue SUCCESS | Returns the pointer to the memory allocated. @rvalue FAILURE | Returns NULL. --*/
void __RPC_FAR * __RPC_USER MIDL_user_allocate( IN size_t len ) { TRTRACEPROC("MIDL_user_allocate", 5) void __RPC_FAR *ptr;
TRENTER(("(len=%d)\n", len));
ptr = malloc(len);
TREXIT(("=%p\n", ptr)); return ptr; } //MIDL_user_allocate
/*++
@doc EXTERNAL
@func void | MIDL_user_free | MIDL free.
@parm IN void __PRC_FAR * | ptr | Points to the memory to be freed.
@rvalue None. --*/
void __RPC_USER MIDL_user_free( IN void __RPC_FAR *ptr ) { TRTRACEPROC("MIDL_user_free", 5)
TRENTER(("(ptr=%p)\n", ptr));
free(ptr);
TREXIT(("!\n")); return; } //MIDL_user_free
|