📄 mynspsvc.cpp
字号:
// Module: mynspsvc.cpp
//
// Description:
// This is the implementation of our namespace service. This
// is what persists the data registered by applications. This
// is implemented as a simple Winsock application which listens
// for connections on a specific port (5150). Our namespace DLL
// connects to this service and sends commands indicating to
// register and lookup services as well as register and remove
// service classes, etc. This service maintains a list of all
// registered service classes and services as well as queries
// intiated by clients.
//
// This service is implemented using the TCP protocol for the
// sake of simplicity. A real name space would most likely use
// UDP for the sake of speed. Of course, this would require
// more logic to ensure that operations are successfully sent
// and received by both this service and the namespace DLL.
//
// Compile:
// cl mynspsvc.cpp nspsvc.cpp printobj.cpp ws2_32.lib
//
// Command Line Arguments/Parameters
// None
//
#define UNICODE
#define _UNICODE
#include <winsock2.h>
#include <windows.h>
#include "nspsvc.h"
#include "printobj.h"
#include "mynsp.h"
#include <stdio.h>
#include <stdlib.h>
#define BUFFER_SZ 4096
#define MAX_SERVICE_CLASSES 25
#define MAX_SERVICES 50
#define MAX_SERVICE_NAME_SZ 128
#define MAX_QUERIES 50
// These two globals contain all service classes registered
// by the namespace DLL
//
WSASERVICECLASSINFO *ServiceClasses[MAX_SERVICE_CLASSES];
DWORD dwNumServiceClasses = 0;
// These two globals contain all services registered by the
// namespace DLL
//
WSAQUERYSET *Services[MAX_SERVICES];
DWORD dwNumServices = 0;
// This structure maintains each client query as well as the
// current state of the query
//
typedef struct _QUERYINFO
{
HANDLE hHandle; // query handle
int iIndex; // last position in Services which
// we found a service instance
WSAQUERYSET *Query; // query parameters
} QUERYINFO;
// These two globals maintain those queries currently registered
//
QUERYINFO QueryInfo[MAX_QUERIES];
DWORD dwNumQueries = 0;
DWORD dwHandleValue = 0; // Next handle to return
//
// Function: DeregisterServiceClass
//
// Description:
// This routine removes the given service class. The GUID
// corresponding to the service class is the only parameter.
//
int DeregisterServiceClass(GUID *guid)
{
DWORD i, j;
for(i=0; i < dwNumServiceClasses ;i++)
{
// Try to find a match
//
if (!memcmp(guid, &ServiceClasses[i]->lpServiceClassId, sizeof(GUID)))
{
for(j=0; j < dwNumServices ;j++)
{
// If an installed services references this service class
// we can't delete it.
//
if (!memcpy(guid, &Services[j]->lpServiceClassId, sizeof(GUID)))
return MYNSP_ERROR;
}
// Free the memory
//
GlobalFree(ServiceClasses[i]);
for(j=i; j < dwNumServiceClasses-1 ;j++)
{
ServiceClasses[j] = ServiceClasses[j+1];
}
dwNumServiceClasses--;
return MYNSP_SUCCESS;
}
}
return MYNSP_ERROR;
}
//
// Function: LookupServiceClass
//
// Description:
// This function simply searches through the registered service
// classes for a specific instance. If found that service class
// structure is returned.
//
WSASERVICECLASSINFO *LookupServiceClass(GUID *guid)
{
for(DWORD i = 0; i < dwNumServiceClasses; i++)
{
if (!memcmp(guid, ServiceClasses[i]->lpServiceClassId, sizeof(GUID)))
{
return ServiceClasses[i];
}
}
return NULL;
}
//
// Function: LookupService
//
// Description:
// This function looks up a service. First it makes sure
// that the service class specified in the query does exist.
// If it does then search through all registered service
// instances for a service of the given name. If so that
// service is returned.
//
WSAQUERYSET *LookupService(GUID *guid, WCHAR *service)
{
WSASERVICECLASSINFO *si=NULL;
// Make sure the service class exists
//
si = LookupServiceClass(guid);
if (!si)
return NULL;
//
// Search through the registered services
//
for(DWORD i=0; i < dwNumServices ;i++)
{
if (!lstrcmpW(service, Services[i]->lpszServiceInstanceName))
{
return Services[i];
}
}
return NULL;
}
//
// Function: DeregisterService
//
// Description:
// This function removes an instance of a service of the given
// service name. First a search is performed to find the service.
// If found, the last service in the array is copied into the
// just removed service's location.
//
int DeregisterService(GUID *guid, TCHAR *service)
{
WSASERVICECLASSINFO *si=NULL;
// Make sure the given service class exists
//
si = LookupServiceClass(guid);
if (!si)
{
return MYNSP_ERROR;
}
for(DWORD i=0; i < dwNumServices ;i++)
{
// Try to find a match
//
if (!lstrcmp(service, Services[i]->lpszServiceInstanceName))
{
// Free the memory
//
GlobalFree(Services[i]);
Services[i] = NULL;
Services[i] = Services[dwNumServices-1];
dwNumServices--;
return MYNSP_SUCCESS;
}
}
return MYNSP_ERROR;
}
//
// Function: RegisterQuery
//
// Description:
// This function registers a user query and returns a unique
// handle to identify the query.
//
BOOL RegisterQuery(WSAQUERYSET *qs, HANDLE *handle)
{
if (dwNumQueries >= MAX_QUERIES)
return FALSE;
//
// Assign the next handle value to this query. Set the iIndex
// to -1 to indicate no query has actually been performed
// yet.
//
QueryInfo[dwNumQueries].hHandle = (HANDLE)++dwHandleValue;
QueryInfo[dwNumQueries].iIndex = -1;
QueryInfo[dwNumQueries].Query = qs;
dwNumQueries++;
*handle = (HANDLE)dwHandleValue;
return TRUE;
}
//
// Function: FindQuery
//
// Description:
// This function find a query based on the query handle. If
// found, the index of the QueryInfo array which contains the
// match is returned.
//
int FindQuery(HANDLE hQuery)
{
for(DWORD i=0; i < dwNumQueries ;i++)
{
if (QueryInfo[i].hHandle == hQuery)
return i;
}
return -1;
}
// Function: PerformQuery
//
// Description:
// This funcion performs the query for the given query handle.
// First the actual query is retrieved based on its handle.
// Next we iterate through all registered services looking
// for those that match the search criteria.
// NOTE! For simplicity our service only attempts to match
// service names (either an exact match or through the wildcard
// asterisk). To make a full fledged namespace provider you need
// to match all the criteria supplied in the query!
//
int PerformQuery(HANDLE hQuery, int *iError)
{
BOOL bFound;
int index;
// Lookup the query parameters
//
*iError = 0;
index = FindQuery(hQuery);
//
// Search for an instance of the service starting where
// we left off (i.e. the iIndex value of the QueryInfo
// structure).
//
bFound = FALSE;
for(DWORD i=QueryInfo[index].iIndex+1; i < dwNumServices ;i++)
{
// If the query is a wildcard we automatically match names
//
if (QueryInfo[index].Query->lpszServiceInstanceName[0] == '*')
{
bFound = TRUE;
}
else
{
if (!lstrcmpW(QueryInfo[index].Query->lpszServiceInstanceName,
Services[i]->lpszServiceInstanceName))
{
bFound = TRUE;
}
}
// If we found a match update the index value
//
if (bFound)
{
QueryInfo[index].iIndex = i;
return i;
}
}
if (QueryInfo[index].iIndex == -1)
*iError = WSASERVICE_NOT_FOUND;
else
*iError = WSA_E_NO_MORE;
return -1;
}
//
// Function: DeleteQuery
//
// Description:
// This function removes a query associated with a query handle.
// We first make sure the query is valid and we then move the
// last query in the array into the position of the deleted
// query.
//
int DeleteQuery(HANDLE hQuery)
{
int index;
// Make sure the query handle is valid
//
index = FindQuery(hQuery);
if (index == -1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -