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

292 lines
7.6 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:
Reg.c
Abstract:
This C file includes sample code for registration portion of
an nspv2 naming provider
--********************************************************************/
#include "Reg.h"
CRITICAL_SECTION g_cs;
RegInfo g_Registrations[MAX_REGISTRATIONS];
ULONG g_cRegistrations = 0;
// Utility routine to get the number of bytes in a string
//
ULONG StringSize(PCWSTR wz)
{
if (wz == NULL)
return 0;
else
return (ULONG) ((wcslen(wz) + 1) * sizeof(WCHAR));
}
// Utility routine which allocates memory and copies a string
//
INT CopyString(PCWSTR wzSrc, __deref_out PWSTR *pwzDest)
{
INT err = NO_ERROR;
ULONG cb = StringSize(wzSrc);
*pwzDest = malloc(cb);
if (*pwzDest == NULL)
{
err = WSA_NOT_ENOUGH_MEMORY;
}
else
{
memcpy(*pwzDest, wzSrc, cb);
}
return err;
}
// Utility routine to allocate memory and copy an array of CSADDR_INFO
//
INT CopyAddrs(__in_ecount(cAddrs) CSADDR_INFO *rgAddrsSrc,
DWORD cAddrs,
__deref_out CSADDR_INFO **prgAddrsDest)
{
INT err = NO_ERROR;
ULONG i = 0;
CSADDR_INFO *rgAddrsDest = (CSADDR_INFO *)malloc(cAddrs * sizeof(CSADDR_INFO));
if (rgAddrsDest == NULL)
{
return WSA_NOT_ENOUGH_MEMORY;
}
ZeroMemory(rgAddrsDest, cAddrs * sizeof(CSADDR_INFO));
for (i = 0; i < cAddrs; i++)
{
// copy static members
rgAddrsDest[i] = rgAddrsSrc[i];
// copy embedded memory
if (rgAddrsSrc[i].LocalAddr.lpSockaddr != NULL)
{
rgAddrsDest[i].LocalAddr.lpSockaddr =
(LPSOCKADDR) malloc(rgAddrsDest[i].LocalAddr.iSockaddrLength);
if (rgAddrsDest[i].LocalAddr.lpSockaddr == NULL)
{
err = WSA_NOT_ENOUGH_MEMORY;
goto cleanup;
}
// copy address byte-for-byte
memcpy(rgAddrsDest[i].LocalAddr.lpSockaddr,
rgAddrsSrc[i].LocalAddr.lpSockaddr,
rgAddrsDest[i].LocalAddr.iSockaddrLength);
}
// copy embedded memory
if (rgAddrsSrc[i].RemoteAddr.lpSockaddr != NULL)
{
rgAddrsDest[i].RemoteAddr.lpSockaddr =
(LPSOCKADDR)malloc(rgAddrsDest[i].RemoteAddr.iSockaddrLength);
if (rgAddrsDest[i].RemoteAddr.lpSockaddr == NULL)
{
err = WSA_NOT_ENOUGH_MEMORY;
goto cleanup;
}
// copy address byte-for-byte
memcpy(rgAddrsDest[i].RemoteAddr.lpSockaddr,
rgAddrsSrc[i].RemoteAddr.lpSockaddr,
rgAddrsDest[i].RemoteAddr.iSockaddrLength);
}
}
// success
*prgAddrsDest = rgAddrsDest;
return NO_ERROR;
// failure
cleanup:
for (i = 0; i < cAddrs; i++)
{
if (rgAddrsDest[i].LocalAddr.lpSockaddr != NULL)
free(rgAddrsDest[i].LocalAddr.lpSockaddr);
if (rgAddrsDest[i].RemoteAddr.lpSockaddr != NULL)
free(rgAddrsDest[i].RemoteAddr.lpSockaddr);
}
free(rgAddrsDest);
return err;
}
// Note: Caller must take g_cs lock in order to call this safely
//
BOOL FindRegistration(PCWSTR pcwzEmailAddress, PCWSTR pcwzServiceName, __out RegInfo **ppRegInfo)
{
ULONG i = 0;
for (i = 0; i < g_cRegistrations; i++)
{
if ( (_wcsicmp(pcwzEmailAddress, g_Registrations[i].pwzEmailAddress) == 0) &&
(_wcsicmp(pcwzServiceName, g_Registrations[i].pwzServiceName) == 0)
)
{
break;
}
}
if (i == g_cRegistrations)
{
return FALSE;
}
else
{
*ppRegInfo = &g_Registrations[i];
return TRUE;
}
}
// Add a registration to the cache
//
INT AddRegistration(__in LPWSAQUERYSET2 pQuerySet)
{
INT err = NO_ERROR;
EnterCriticalSection(&g_cs);
// If it already exists, we remove it
RemoveRegistration(pQuerySet);
if (g_cRegistrations == MAX_REGISTRATIONS)
{
err = WSA_NOT_ENOUGH_MEMORY;
goto cleanup;
}
err = CopyString(pQuerySet->lpszServiceInstanceName,
&g_Registrations[g_cRegistrations].pwzEmailAddress);
if (err != NO_ERROR)
{
goto cleanup;
}
err = CopyString(pQuerySet->lpszContext,
&g_Registrations[g_cRegistrations].pwzServiceName);
if (err != NO_ERROR)
{
goto cleanup;
}
err = CopyAddrs(pQuerySet->lpcsaBuffer,
pQuerySet->dwNumberOfCsAddrs,
&g_Registrations[g_cRegistrations].prgAddresses);
if (err != NO_ERROR)
{
goto cleanup;
}
printf("Registration for %S (service = %S) added.\n",
pQuerySet->lpszServiceInstanceName,
pQuerySet->lpszContext);
g_Registrations[g_cRegistrations].cAddresses = pQuerySet->dwNumberOfCsAddrs;
g_cRegistrations++;
LeaveCriticalSection(&g_cs);
return err;
cleanup:
free(g_Registrations[g_cRegistrations].pwzEmailAddress);
free(g_Registrations[g_cRegistrations].pwzServiceName);
LeaveCriticalSection(&g_cs);
return err;
}
void RemoveAllRegistrations()
{
ULONG i;
EnterCriticalSection(&g_cs);
while (g_cRegistrations > 0)
{
free(g_Registrations[g_cRegistrations-1].pwzEmailAddress);
for (i = 0; i < g_Registrations[g_cRegistrations-1].cAddresses; i++)
{
if (g_Registrations[g_cRegistrations-1].prgAddresses[i].LocalAddr.lpSockaddr != NULL)
free(g_Registrations[g_cRegistrations-1].prgAddresses[i].LocalAddr.lpSockaddr);
if (g_Registrations[g_cRegistrations-1].prgAddresses[i].RemoteAddr.lpSockaddr != NULL)
free(g_Registrations[g_cRegistrations-1].prgAddresses[i].RemoteAddr.lpSockaddr);
}
free(g_Registrations[g_cRegistrations-1].prgAddresses);
g_cRegistrations--;
}
LeaveCriticalSection(&g_cs);
printf("All registrations removed.\n");
}
INT RemoveRegistration(__in LPWSAQUERYSET2 pQuerySet)
{
ULONG i, j;
int err;
err = WSAHOST_NOT_FOUND;
EnterCriticalSection(&g_cs);
for (i = 0; i < g_cRegistrations; i++)
{
if ( (wcscmp(pQuerySet->lpszServiceInstanceName, g_Registrations[i].pwzEmailAddress) == 0) &&
(wcscmp(pQuerySet->lpszContext, g_Registrations[i].pwzServiceName) == 0)
)
{
// found registration to remove
free(g_Registrations[i].pwzEmailAddress);
for (j = 0; j < g_Registrations[i].cAddresses; j++)
{
if (g_Registrations[i].prgAddresses[j].LocalAddr.lpSockaddr != NULL)
free(g_Registrations[i].prgAddresses[j].LocalAddr.lpSockaddr);
if (g_Registrations[i].prgAddresses[j].RemoteAddr.lpSockaddr != NULL)
free(g_Registrations[i].prgAddresses[j].RemoteAddr.lpSockaddr);
}
free(g_Registrations[i].prgAddresses);
g_Registrations[i] = g_Registrations[g_cRegistrations-1];
g_cRegistrations--;
printf("Registration for %S removed.\n", pQuerySet->lpszServiceInstanceName);
err = NO_ERROR;
break;
}
}
LeaveCriticalSection(&g_cs);
return err;
}