home *** CD-ROM | disk | FTP | other *** search
-
- /******************************************************************************\
- * 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
- }
-