2025-11-28 00:35:46 +09:00

277 lines
7.7 KiB
C

/********************************************************************++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) Microsoft Corporation. All Rights Reserved.
Module Name:
SampleClient.c
Abstract:
This C file includes sample code for registering a name with
the nspv2 naming apis
--********************************************************************/
#include <winsock2.h>
#include <ws2ipdef.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <strsafe.h>
#ifndef MIN
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif
#ifndef celems
#define celems(x) (sizeof(x)/sizeof((x)[0]))
#endif
#define MAX_ADDR 16
void PrintIPV6Addr(
__in SOCKADDR_IN6 * pSockAddr)
{
WORD * pwAddr = (WORD *)(&(pSockAddr->sin6_addr));
printf("[%x:%x:%x:%x%x:%x:%x:%x]:%d\n",
htons(pwAddr[0]), htons(pwAddr[1]), htons(pwAddr[2]),
htons(pwAddr[3]), htons(pwAddr[4]), htons(pwAddr[5]),
htons(pwAddr[6]), htons(pwAddr[7]),
htons(pSockAddr->sin6_port));
}
//
// Publish or Delete an e-mail address via the WSASetService API
// This sample only accepts ipv6 addresses.
//
HRESULT Publish(BOOL fPublish,
PCWSTR pwzEmailName,
PCWSTR pwzServiceName,
ULONG cIPV6Addrs,
__in_ecount(cIPV6Addrs) SOCKADDR_IN6 *pIPV6Sockaddr)
{
HRESULT hr = S_OK;
INT iErr = 0;
WSAQUERYSETW querySet = {0};
CSADDR_INFO rgAddrs[MAX_ADDR] = {0};
ULONG i = 0;
// Initialize the array of CSADDR_INFO
//
for(i = 0; i < cIPV6Addrs && i < celems(rgAddrs); i++)
{
rgAddrs[i].iProtocol = IPPROTO_TCP;
rgAddrs[i].iSocketType = SOCK_STREAM;
rgAddrs[i].LocalAddr.iSockaddrLength = sizeof(*pIPV6Sockaddr);
rgAddrs[i].LocalAddr.lpSockaddr = (SOCKADDR*) pIPV6Sockaddr + i;
rgAddrs[i].RemoteAddr.iSockaddrLength = sizeof(*pIPV6Sockaddr);
rgAddrs[i].RemoteAddr.lpSockaddr = (SOCKADDR*) pIPV6Sockaddr + i;
}
querySet.dwSize = sizeof(WSAQUERYSETW);
querySet.lpszServiceInstanceName = (PWSTR) pwzEmailName;
querySet.lpszContext = (PWSTR) pwzServiceName;
querySet.lpNSProviderId = NULL;
querySet.lpServiceClassId = NULL;
querySet.dwNameSpace = NS_EMAIL;
querySet.dwNumberOfCsAddrs = MIN(celems(rgAddrs), cIPV6Addrs);
querySet.lpcsaBuffer = (LPCSADDR_INFO) rgAddrs;
iErr = WSASetService(&querySet, fPublish ? RNRSERVICE_REGISTER : RNRSERVICE_DELETE, 0);
if (SOCKET_ERROR == iErr)
{
hr = HRESULT_FROM_WIN32(WSAGetLastError());
}
return hr;
}
void Usage(PCWSTR wzProgram)
{
printf("Usage: %S [-u] email_address\n\n", wzProgram);
printf("\nOptions:\t-u : unpublish (default: publish)\n");
printf("\n");
printf("This sample will \"publish\" the {email address, ip address} pair\n");
printf("with all naming providers registered to accept the specified domain.\n");
printf("For use with the sample provider, use @sampleprovider.net domain\n");
}
HRESULT ParseCmdLine(
int argc,
__in_ecount(argc) LPWSTR *argv,
__out BOOL *pfPublish,
ULONG cchMailAddress,
__out_ecount(cchMailAddress) WCHAR *wzEmailAddress,
ULONG cchServiceName,
__out_ecount(cchServiceName) WCHAR *wzServiceName)
{
int index = 1;
PWSTR pwzPos = argv[index];
HRESULT hr = S_OK;
if (argc < 2)
{
Usage(argv[0]);
return E_FAIL;
}
*pfPublish = TRUE;
if ('-' == *pwzPos || '/' == *pwzPos)
{
pwzPos++;
if (0 == lstrcmpiW(pwzPos, L"u"))
{
*pfPublish = FALSE;
}
else
{
Usage(argv[0]);
return E_FAIL;
}
pwzPos = argv[++index];
}
if (NULL == wcschr(pwzPos,'@'))
{
Usage(argv[0]);
return E_FAIL;
}
else
{
hr = StringCchCopy(wzEmailAddress, cchMailAddress, pwzPos);
pwzPos = argv[++index];
}
if (index < argc)
{
hr = StringCchCopy(wzServiceName, cchServiceName, pwzPos);
}
return hr;
}
//
// Get the ipv6 addresses for the local machine
//
HRESULT GetAddresses(__inout ULONG *pcAddrs,
__out_ecount(*pcAddrs) SOCKADDR_IN6 *rgAddrs)
{
HRESULT hr = S_OK;
CHAR szHostName[MAX_PATH] = {0};
DWORD cchHostName = celems(szHostName);
struct addrinfo aiHints = {0};
struct addrinfo *pResults = NULL;
struct addrinfo *pCurrent = NULL;
ULONG cAddrs = 0;
if (!GetComputerNameA(szHostName, &cchHostName))
{
DWORD dwErr = GetLastError();
hr = HRESULT_FROM_WIN32(dwErr);
fprintf(stderr, "GetComputerName failed error = %u\n", dwErr);
}
else
{
aiHints.ai_family = PF_INET6;
if (getaddrinfo(szHostName, NULL, &aiHints, &pResults) == SOCKET_ERROR)
{
int iErr = WSAGetLastError();
hr = HRESULT_FROM_WIN32(iErr);
fprintf (stderr, "getaddrinfo(local machine name) failed error = %d\n", iErr);
}
}
if (SUCCEEDED(hr))
{
pCurrent = pResults;
while (pCurrent && cAddrs < *pcAddrs)
{
if (AF_INET6 == pCurrent->ai_family)
{
CopyMemory(rgAddrs + cAddrs, pCurrent->ai_addr, sizeof(SOCKADDR_IN6));
cAddrs++;
}
pCurrent = pCurrent->ai_next;
}
}
*pcAddrs = cAddrs;
freeaddrinfo(pResults);
return hr;
}
int __cdecl wmain(int argc, __in_ecount(argc) LPWSTR * argv)
{
HRESULT hr = S_OK;
int iErr = 0;
BOOL fPublish = TRUE;
WORD wVersionRequested = MAKEWORD( 2, 2 );
WSADATA wsaData = { 0 };
WCHAR wzServiceName[MAX_PATH] = {0};
WCHAR wzEmailAddress[MAX_PATH] = {0};
SOCKADDR_IN6 rgAddrs[MAX_ADDR] = { 0 };
ULONG cAddrs = celems(rgAddrs);
ULONG i ;
iErr = WSAStartup(wVersionRequested, &wsaData);
if (iErr != 0)
{
hr = HRESULT_FROM_WIN32(iErr);
}
if (SUCCEEDED(hr))
{
hr = ParseCmdLine(argc, argv, &fPublish, celems(wzEmailAddress), wzEmailAddress,
celems(wzServiceName), wzServiceName);
}
if (SUCCEEDED(hr))
{
hr = GetAddresses(&cAddrs, rgAddrs);
if (SUCCEEDED(hr) && cAddrs == 0)
{
hr = E_UNEXPECTED;
fprintf (stderr, "No address available to register/unregister\n");
}
}
if (SUCCEEDED(hr))
{
printf ("----------------------------------------------------------------------\n");
printf ("%s the following addresses:\n", fPublish ? "Publishing" : "Unpublishing");
for (i = 0; i < cAddrs; i++)
{
PrintIPV6Addr(rgAddrs + i);
}
printf ("----------------------------------------------------------------------\n");
printf ("\n");
hr = Publish(fPublish, wzEmailAddress, wzServiceName, cAddrs, rgAddrs);
fprintf (stderr, "%s %s - hr = %x\n",
fPublish ? "Publishing" : "Unpublishing",
SUCCEEDED(hr) ? "SUCCEEDED" : "FAILED",
hr);
}
iErr = WSACleanup();
if (0 != iErr)
{
iErr = WSAGetLastError();
fprintf (stderr, "WSACleanup failed WSAError = 0x%x\n", iErr);
}
return hr;
}