|
|
/******************************************************************************\
* This is a part of the Microsoft Source Code Samples. * Copyright 1995 - 1997 Microsoft Corporation. * All rights reserved. * This source code is only intended as a supplement to * Microsoft Development Tools and/or WinHelp documentation. * See these sources for detailed information regarding the * Microsoft samples programs. \******************************************************************************/
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
SrvQuery.c
Abstract:
The server component of Remote. Respond to client "remote /q" requests to list available remote servers on this machine.
Author:
Dave Hart 30 May 1997 derived from code by Mihai Costea in server.c.
Environment:
Console App. User mode.
Revision History:
--*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <io.h>
#include <string.h>
#include "Remote.h"
#include "Server.h"
VOID FASTCALL InitializeQueryServer( VOID ) { //
// hQPipe is the handle to the listening query pipe,
// if we're serving it.
//
hQPipe = INVALID_HANDLE_VALUE;
QueryOverlapped.hEvent = CreateEvent( NULL, // security
TRUE, // manual-reset
FALSE, // initially nonsignaled
NULL // unnamed
);
rghWait[WAITIDX_QUERYSRV_WAIT] = CreateMutex( &saPublic, // security
FALSE, // not owner in case we open not create
"MS RemoteSrv Q Mutex" );
if (INVALID_HANDLE_VALUE == rghWait[WAITIDX_QUERYSRV_WAIT]) {
ErrorExit("Remote: Unable to create/open query server mutex.\n"); } }
VOID FASTCALL QueryWaitCompleted( VOID ) { HANDLE hWait; DWORD dwThreadId; BOOL b; DWORD dwRead;
//
// The remote server (not us) which was servicing the query
// pipe has left the arena. Or someone has connected.
//
hWait = rghWait[WAITIDX_QUERYSRV_WAIT];
if (hWait == QueryOverlapped.hEvent) {
//
// We're the query server and someone has connected.
// Start a thread to service them.
//
b = GetOverlappedResult(hQPipe, &QueryOverlapped, &dwRead, TRUE);
if ( !b && ERROR_PIPE_CONNECTED != GetLastError()) {
TRACE(QUERY,("Connect Query Pipe returned %d\n", GetLastError()));
if (INVALID_HANDLE_VALUE != hQPipe) {
CloseHandle(hQPipe); hQPipe = INVALID_HANDLE_VALUE; }
} else {
TRACE(QUERY, ("Client connected to query pipe.\n"));
ResetEvent(hWait);
CloseHandle( (HANDLE) _beginthreadex( NULL, // security
0, // default stack size
QueryHandlerThread, (LPVOID) hQPipe, // parameter
0, // not suspended
&dwThreadId ));
hQPipe = INVALID_HANDLE_VALUE; }
} else {
TRACE(QUERY, ("Remote server entered query mutex, will handle queries.\n"));
rghWait[WAITIDX_QUERYSRV_WAIT] = QueryOverlapped.hEvent; }
//
// Either a client has connected and we've handed that pipe
// off to a query thread to deal with, or we're just starting
// to serve the query pipe, or we had an error from
// ConnectNamedPipe. In any case we want to create another
// query pipe instance and start listening on it.
//
ASSERT(INVALID_HANDLE_VALUE == hQPipe);
StartServingQueryPipe(); }
VOID FASTCALL StartServingQueryPipe( VOID ) { BOOL b; DWORD dwThreadId; char fullname[BUFFSIZE];
sprintf(fullname, QUERY_DEBUGGERS_PIPE, ".");
do { // hand off each pipe as connected until IO_PENDING
hQPipe = CreateNamedPipe( fullname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 0, 0, 0, &saPublic ); if (INVALID_HANDLE_VALUE == hQPipe) {
ErrorExit("Unable to create query server pipe."); }
b = ConnectNamedPipe(hQPipe, &QueryOverlapped);
if ( ! b && ERROR_PIPE_CONNECTED == GetLastError()) {
b = TRUE; }
if (b) {
//
// That was fast.
//
TRACE(QUERY, ("Client connected quickly to query pipe.\n"));
CloseHandle( (HANDLE) _beginthreadex( NULL, // security
0, // default stack size
QueryHandlerThread, (LPVOID) hQPipe, // parameter
0, // not suspended
&dwThreadId ));
hQPipe = INVALID_HANDLE_VALUE;
} else if (ERROR_IO_PENDING == GetLastError()) {
//
// The main thread will call QueryWaitCompleted when
// someone connects.
//
TRACE(QUERY, ("Awaiting query pipe connect\n"));
} else {
sprintf(fullname, "Remote: error %d connecting query pipe.\n", GetLastError());
OutputDebugString(fullname); ErrorExit(fullname); }
} while (b); }
DWORD WINAPI QueryHandlerThread( LPVOID lpvArg ) { HANDLE hQueryPipe = (HANDLE) lpvArg; DWORD cb; BOOL b; OVERLAPPED ol; QUERY_MESSAGE QData; char pIn[1];
ZeroMemory(&ol, sizeof(ol));
ol.hEvent = CreateEvent( NULL, // security
TRUE, // manual-reset
FALSE, // initially nonsignaled
NULL // unnamed
);
// get command
b = ReadFileSynch( hQueryPipe, pIn, 1, &cb, 0, &ol );
if ( ! b || 1 != cb ) { TRACE(QUERY, ("Query server unable to read byte from query pipe.\n")); goto failure; }
TRACE(QUERY, ("Query server read command '%c'\n", pIn[0]));
//
// !!!!!!
// REMOVE 'h' support, it's only here for transitional compatibility
// with 1570+ remote /q original server implementation.
//
if(pIn[0] == 'h') {
DWORD dwMinusOne = (DWORD) -1;
b = WriteFileSynch( hQueryPipe, &dwMinusOne, sizeof(dwMinusOne), &cb, 0, &ol );
if ( !b || sizeof(dwMinusOne) != cb ) { goto failure; } }
if(pIn[0] == 'q') {
QData.size = 0; QData.allocated = 0; QData.out = NULL; EnumWindows(EnumWindowProc, (LPARAM)&QData);
b = WriteFileSynch( hQueryPipe, &QData.size, sizeof(QData.size), &cb, 0, &ol );
if ( ! b || sizeof(int) != cb) {
TRACE(QUERY, ("Remote: Can't write query length\n")); goto failure; } if (QData.size) { // anything to say?
b = WriteFileSynch( hQueryPipe, QData.out, QData.size * sizeof(char), &cb, 0, &ol );
free(QData.out);
if ( ! b || QData.size * sizeof(char) != cb) {
TRACE(QUERY, ("Remote: Can't write query")); goto failure; }
TRACE(QUERY, ("Sent query response\n")); } } FlushFileBuffers(hQueryPipe);
failure: DisconnectNamedPipe(hQueryPipe); CloseHandle(hQueryPipe); CloseHandle(ol.hEvent);
return 0; }
BOOL CALLBACK EnumWindowProc( HWND hWnd, LPARAM lParam ) { #define MAX_TITLELEN 200
QUERY_MESSAGE *pQm; int titleLen; char title[MAX_TITLELEN]; char* tmp;
pQm = (QUERY_MESSAGE*)lParam;
if(titleLen = GetWindowText(hWnd, title, sizeof(title)/sizeof(title[0]))) { //
// search for all windows that are visible
//
if (strstr(title, "] visible") && strstr(title, "[Remote ")) { if(pQm->size) // if message not empty
pQm->out[(pQm->size)++] = '\n'; // overwrite ending null with \n
else { pQm->out = (char*)malloc(MAX_TITLELEN); // first allocation
if(!pQm->out) { printf("\nOut of memory\n"); return FALSE; } pQm->allocated = MAX_TITLELEN; }
// fill the result
if((pQm->size + titleLen) >= pQm->allocated) { tmp = (char*)realloc(pQm->out, pQm->allocated + MAX_TITLELEN); if(!tmp) { printf("\nOut of memory\n"); free(pQm->out); pQm->size = 0; return FALSE; } pQm->out = tmp; pQm->allocated += MAX_TITLELEN; } strcpy(pQm->out + pQm->size, title); pQm->size += titleLen; } } return TRUE; #undef MAX_TITLELEN
}
|