⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nspsvc.cpp

📁 《Windows网络编程技术》附书源码源码. 运行环境:9x/Me/NT/2000/XP/ 源码语言:简体中文 第十四章
💻 CPP
字号:
// Module: nspsvc.cpp
//
// Description:
//    This file contains support routines used both by our namespace
//    DLL and by our namespace service. These functions pertain to 
//    marshalling and demarshalling WSASERVICECLASSINFO and 
//    WSAQUERYSET structures. Additionally, this module contains
//    functions for sending and receiving data.
//
#define UNICODE
#define _UNICODE

#include <winsock2.h>
#include <windows.h>

#include "nspsvc.h"

#include <stdio.h>
#include <stdlib.h>

//
// Function: MarshallServiceClassInfo
//
// Description:
//    This routine takes a WSASERVICECLASSINFO structure and marshalls
//    the data contained within into a contiguous buffer. This is done
//    so the structure can be sent across a socket connection and the
//    other side can reassemble the structure. The size parameter will
//    be set to the total size of the marshalled structure.
//
int _cdecl MarshallServiceClassInfo(WSASERVICECLASSINFO *sc, char *buf, int *size)
{
    BYTE *ptr;
    int   totalsz, sz;

    ptr = (BYTE *)buf;
    totalsz = 0;

    // First copy the structure into the buffer
    //
    memcpy(buf, sc, (sz = sizeof(WSASERVICECLASSINFO)));
    ptr += sz;
    totalsz += sz;

    // For each field in the structure copy its data into the buffer
    //
    if (sc->lpServiceClassId)
    {
        memcpy(ptr, sc->lpServiceClassId, (sz = sizeof(GUID)));
        ptr += sz;
        totalsz += sz;
    }
    if (sc->lpszServiceClassName)
    {        
        memcpy(ptr, sc->lpszServiceClassName, 
            (sz = (lstrlenW(sc->lpszServiceClassName)+1) * sizeof(WCHAR)));
        ptr += sz;
        totalsz += sz; 
    }
    if (sc->lpClassInfos)
    {
        memcpy(ptr, sc->lpClassInfos, (sz = sizeof(WSANSCLASSINFO) * sc->dwCount));
        ptr += sz;
        totalsz += sz;
    }
    *size = totalsz;

    return 0;
}

//
// Function: DeMarshallServiceClassInfo
//
// Description:
//    This routine is the opposite of MarshallServiceClassInfo. It takes
//    a buffer which contains the raw data received on a socket and
//    reassembles it into a WSASERVICECLASSINFO structure.
//
int _cdecl DeMarshallServiceClassInfo(WSASERVICECLASSINFO *sc, char *buf)
{
    BYTE          *ptr=NULL,            // source buffer
                  *ptrdest=NULL;        // the reassembled structure
    unsigned int   sz;

    // Setup some pointers to both the source and destination buffers
    //
    ptr = (BYTE *)buf;
    ptrdest = (BYTE *)sc;
    //
    // Copy the first part of the source into the destinatin buffer.
    //  This is the WSASERVICECLASSINFO structure.
    //
    sz = sizeof(WSASERVICECLASSINFO);
    memcpy(sc, ptr, sz);
    ptr = ptr + sz;
    ptrdest = ptrdest + sz;
    //
    // Copy each field that is present into the destination buffer.
    //  If the source field is a pointer and is NULL this means 
    //  there is no data for that field (i.e. a NULL pointer).
    //  Otherwise make sure the field that do contain data point
    //  to memory locations valid on this side of the connection.
    // 
    if (sc->lpServiceClassId)
    {
        sz = sizeof(GUID);
        memcpy(ptrdest, ptr, sz);
        sc->lpServiceClassId = (LPGUID)ptrdest;

        ptr = ptr + sz;
        ptrdest = ptrdest + sz;
    }
    if (sc->lpszServiceClassName)
    {
        sz = (lstrlenW((WCHAR *)ptr) + 1) * sizeof(WCHAR);
        memcpy(ptrdest, ptr, sz);
        sc->lpszServiceClassName = (LPTSTR)ptrdest;

        ptr = ptr + sz;
        ptrdest = ptrdest + sz;
    }
    if (sc->lpClassInfos)
    {
        sz = sizeof(WSANSCLASSINFO) * sc->dwCount;
        memcpy(ptrdest, ptr, sz);
        sc->lpClassInfos = (LPWSANSCLASSINFO)ptrdest;

        ptr = ptr + sz;
        ptrdest = ptrdest + sz;
    }

    return 0;
}

//
// Function: MarshallServiceInfo
//
// Description:
//    This routine takes a WSAQUERYSET structure and marshalls
//    the data contained within into a contiguous buffer. This is done
//    so the structure can be sent across a socket connection and the
//    other side can reassemble the structure. The size parameter will
//    be set to the total size of the marshalled structure.
//
int _cdecl MarshallServiceInfo(WSAQUERYSET *qs, char *buf, int *size)
{
    BYTE        *ptr=NULL;
    unsigned int sz;
    int          totalsz;
        
    // Setup a pointer to the destination buffer
    //
    ptr = (BYTE *)buf;
    totalsz = 0;
    //
    // Copy the WSAQUERYSET structure at the head of the buffer
    //
    memcpy(buf, qs, sizeof(WSAQUERYSET));
        sz = sizeof(WSAQUERYSET);
        
    ptr = ptr + sz;
    totalsz += sz;
    //
    // Take each non-NULL pointer and copy its data into the buffer
    //
    if (qs->lpszServiceInstanceName)
    {
        sz = (lstrlenW(qs->lpszServiceInstanceName) + 1) * sizeof(WCHAR);
        memcpy(ptr, qs->lpszServiceInstanceName, sz);

        ptr = ptr + sz;        	
        totalsz += sz;
    }
    if (qs->lpServiceClassId)
    {
        sz = sizeof(GUID);
        memcpy(ptr, qs->lpServiceClassId, sz);

        ptr = ptr + sz;
        totalsz += sz; 
    }
    if (qs->lpVersion)
    {
        sz = sizeof(WSAVERSION);
        memcpy(ptr, qs->lpVersion, sz);
        
        ptr = ptr + sz;
        totalsz += sz;
    }
    if (qs->lpszComment)
    {
        sz = (lstrlenW(qs->lpszComment) + 1) * sizeof(WCHAR);
        memcpy(ptr, qs->lpszComment, sz);
                
        ptr = ptr + sz;
        totalsz += sz;
    }
    if (qs->lpNSProviderId)
    {
        sz = sizeof(GUID);
        memcpy(ptr, qs->lpNSProviderId, sz);
        
        ptr = ptr + sz;
        totalsz += sz;
    }
    if (qs->lpszContext)
    {
        sz = (lstrlenW(qs->lpszContext) + 1) * sizeof(WCHAR);
        memcpy(ptr, qs->lpszContext, sz);

        ptr = ptr + sz;
        totalsz += sz;
    }
    if (qs->lpafpProtocols)
    {
        sz = sizeof(AFPROTOCOLS) * qs->dwNumberOfProtocols;
        memcpy(ptr, qs->lpafpProtocols, sz);
        
        ptr = ptr + sz;
        totalsz += sz;
    }
    if (qs->lpszQueryString)
    {
        sz = (lstrlenW(qs->lpszQueryString) + 1) * sizeof(WCHAR);
        memcpy(ptr, qs->lpszQueryString, sz);
        
        ptr = ptr + sz;
        totalsz += sz;
    }
    if (qs->lpcsaBuffer)
    {
        sz = sizeof(CSADDR_INFO) * qs->dwNumberOfCsAddrs;
        memcpy(ptr, qs->lpcsaBuffer, sz);

        ptr = ptr + sz;
        totalsz += sz;

        for(DWORD i=0; i < qs->dwNumberOfCsAddrs ;i++)
        {
            sz = qs->lpcsaBuffer[i].LocalAddr.iSockaddrLength;
            memcpy(ptr, qs->lpcsaBuffer[i].LocalAddr.lpSockaddr, sz);
            ptr = ptr + sz;
            totalsz += sz;
            
            sz = qs->lpcsaBuffer[i].RemoteAddr.iSockaddrLength;
            memcpy(ptr, qs->lpcsaBuffer[i].RemoteAddr.lpSockaddr, sz);
            ptr = ptr + sz;
            totalsz += sz;
        }
    }

    *size = totalsz;
    return 0;
}

// 
// Function: DeMarshallServiceInfo
//
// Description:
//    This routine is the opposite of MarshallServiceInfo. It takes
//    a buffer which contains the raw data received on a socket and
//    reassembles it into a WSAQUERYSET structure.
//
int _cdecl DeMarshallServiceInfo(WSAQUERYSET *qs, char *buf)
{
    BYTE         *ptr=NULL,
                 *ptrdest=NULL;
    unsigned int  sz=0;

    // Setup pointers to the source and destination buffers 
    //
    ptr = (BYTE *)buf;
    ptrdest = (BYTE *)qs;
    //
    // Copy the first portion of the source into the destination.
    //  This is the WSAQUERYSET structure
    //
    sz = sizeof(WSAQUERYSET);
    memcpy(qs, ptr, sz);

    ptr = ptr + sz;
    ptrdest = ptrdest + sz;
    //
    // For each non-NULL member of the WSAQUERYSET, we need to copy
    //  data from the source into the destination and fix the pointer
    //  to point to the correct memory location
    // 
    if (qs->lpszServiceInstanceName)
    {
        sz = (lstrlenW((WCHAR *)ptr)+1) * sizeof(WCHAR);
        memcpy(ptrdest, ptr, sz);
        qs->lpszServiceInstanceName = (LPTSTR)ptrdest;

        ptr = ptr + sz;
        ptrdest = ptrdest + sz;
    }
    if (qs->lpServiceClassId)
    {
        sz = sizeof(GUID);
        memcpy(ptrdest, ptr, sz);
        qs->lpServiceClassId = (LPGUID)ptrdest;
        
            ptr = ptr + sz;
        ptrdest = ptrdest + sz;
    }
    if (qs->lpVersion)
    {
        sz = sizeof(WSAVERSION);
        memcpy(ptrdest, ptr, sz);
        qs->lpVersion = (WSAVERSION *)ptrdest;

            ptr = ptr + sz;
        ptrdest = ptrdest + sz;
    }
    if (qs->lpszComment)
    {
        sz = (lstrlenW((WCHAR *)ptr)+1) * sizeof(WCHAR);
        memcpy(ptrdest, ptr, sz); 
        qs->lpszComment = (LPTSTR)ptrdest;

        ptr = ptr + sz;
        ptrdest = ptrdest + sz;
    }
    if (qs->lpNSProviderId)
    {
        sz = sizeof(GUID);
        memcpy(ptrdest, ptr, sz);
        qs->lpNSProviderId = (GUID *)ptrdest;

        ptr = ptr + sz;
        ptrdest = ptrdest + sz;
    }
    if (qs->lpszContext)
    {
        sz = (lstrlenW((WCHAR *)ptr) + 1) * sizeof(WCHAR);
        memcpy(ptrdest, ptr, sz);
        qs->lpszContext = (LPTSTR)ptrdest;

        ptr = ptr + sz;
        ptrdest = ptrdest + sz;
    }
    if (qs->lpafpProtocols)
    {
        sz = sizeof(AFPROTOCOLS) * qs->dwNumberOfProtocols;
        memcpy(ptrdest, ptr, sz);
        qs->lpafpProtocols = (AFPROTOCOLS *)ptrdest;

        ptr = ptr + sz;
        ptrdest = ptrdest + sz;
    }
    if (qs->lpszQueryString)
    {
        sz = (lstrlenW((WCHAR *)ptr)+1) * sizeof(WCHAR);
        memcpy(ptrdest, ptr, sz);
        qs->lpszQueryString = (LPTSTR)ptrdest;

        ptr = ptr + sz;
        ptrdest = ptrdest + sz;
    }
    if (qs->lpcsaBuffer)
    {
        sz = sizeof(CSADDR_INFO) * qs->dwNumberOfCsAddrs;
        memcpy(ptrdest, ptr, sz);
        qs->lpcsaBuffer = (CSADDR_INFO *)ptrdest;

        ptr = ptr + sz;
        ptrdest = ptrdest + sz;
        
        for(DWORD i=0; i < qs->dwNumberOfCsAddrs ;i++)
        {
            sz = qs->lpcsaBuffer[i].LocalAddr.iSockaddrLength;
            memcpy(ptrdest, ptr, sz);
            qs->lpcsaBuffer[i].LocalAddr.lpSockaddr = (SOCKADDR *)ptrdest;
            ptr = ptr + sz;
            ptrdest = ptrdest + sz;
            
            sz = qs->lpcsaBuffer[i].RemoteAddr.iSockaddrLength;
            memcpy(ptrdest, ptr, sz);
            qs->lpcsaBuffer[i].RemoteAddr.lpSockaddr = (SOCKADDR *)ptrdest;
            ptr = ptr + sz;
            ptrdest = ptrdest + sz;            
        }
    }

    return 0;
}

//
// Function: readdata
//
// Description:
//    This function performs a blocking read for the given number of 
//    bytes. The bytesread parameter indicates the number of bytes 
//    to be read. Upon completion it is updated to indicate the 
//    actual number of bytes read. However, under normal circumstances
//    this function will not return until the requested number of bytes
//    have been read.
//
int _cdecl readdata(SOCKET s, char *buffer, int buffersz, int *bytesread)
{
    int        ret, 
               nbytes;
    ULONG      nLeft;

    nLeft = *bytesread; 

    nbytes = 0;
    *bytesread = 0; 
    //
    // Loop until all data has been read. Make sure we don't
    //  exceed the buffer size.
    //
    while ((nLeft > 0) && (nbytes < buffersz))
    {
        ret = recv(s, &buffer[nbytes], buffersz - nbytes, 0);
        if (ret == SOCKET_ERROR)
        {
            printf("recv() failed: %d\n", WSAGetLastError());
            closesocket(s);
            break;
        }
        else if (ret == 0)        // socket has been closed
        {
            closesocket(s);
            break;
        }
        // Update counters
        //
        nbytes += ret;
        nLeft -= ret;
    }
    // Update the byte count
    //
    *bytesread = nbytes;

    return 0;
}

//
// Function: writedata
//
// Description:
//    This function writes the requested number of bytes to the socket.
//    The numwrite parameter indicates how many bytes should be written
//    while byteswritten is an out parameter indicating how many were
//    actually written. Under normal circumstances, the function will
//    not return until all bytes have been written.
//
int _cdecl writedata(SOCKET s, char *buffer, int numwrite, int *byteswritten)
{
    int        nbytes,
               ret;

    nbytes = 0;
    *byteswritten = 0;
    //
    // Write the data in a loop until all is sent
    //
    while (numwrite > 0)
    {
        ret = send(s, &buffer[nbytes], numwrite, 0);
        if (ret == SOCKET_ERROR)
        {
            printf("send() failed: %d\n", WSAGetLastError());
            return 1;
        }
        else if (ret == 0)
        {
            return 0;
        }
        numwrite -= ret;
        nbytes   += ret;
    }
    // Update bytes written
    //
    *byteswritten = nbytes;

    return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -