//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
//------------------------------------------------------------------------------
// 
//      Bluetooth Name Space Layer
// 
// 
// Module Name:
// 
//      bthns.cxx
// 
// Abstract:
// 
//      This file implements the Name Space provider.  This name space provider
//      lives in btd.dll and is called by Winsock2 during WSASetService
//      and WSALookup calls.
// 
// 
//------------------------------------------------------------------------------


#include <windows.h>
#include <winsock2.h>
#include <ws2spi.h>
#include <svsutil.hxx>
#include <bt_api.h>



#define BTHNS_THREAD_SAFTEY 0

#if 0

#if BTHNS_THREAD_SAFTEY
// Currently there is no need for any thread saftey at this level,
// leaving code in place (#ifdef'd out) in case this changes.
// Note that if this is added, would need to be placed in btdrt.dll's DllMain.
CRITICAL_SECTION    g_bthNsCritSec;
static int            g_cStartups;
#endif

BOOL WINAPI DllMain(HANDLE hInstance, DWORD dwReason, LPVOID lpReserved) {
#if BTHNS_THREAD_SAFTEY
    switch (dwReason) {
    case DLL_PROCESS_ATTACH:
        g_cStartups = 0;
        InitializeCriticalSection(&g_bthNsCritSec);
        DisableThreadLibraryCalls ((HMODULE)hInstance);
        break;

    case DLL_PROCESS_DETACH:
        DeleteCriticalSection(&g_bthNsCritSec);
        break;

    default:
        break;
    }
#endif // BTHNS_THREAD_SAFTEY
    return TRUE;
}
#endif // 0


int WINAPI BTH_NSPCleanup(LPGUID lpProviderId) {
#if BTHNS_THREAD_SAFTEY
    int iError = ERROR_SUCCESS;

    __try {
        if (memcmp(lpProviderId, &NsId, sizeof(GUID)))
            iError = WSAEINVAL;
        else {
            EnterCriticalSection(&g_bthNsCritSec);
            g_cStartups--;
            if (g_cStartups == 0) {
                // cleanup - currently nothing is allocated at this layer.
            }

            LeaveCriticalSection(&g_bthNsCritSec);
        }
    }
    __except (EXCEPTION_EXECUTE_HANDLER) {
        iError = WSAEFAULT;
    }

    if (iError) {
        SetLastError(iError);
        iError = SOCKET_ERROR;
    }
    return iError;
#else
    return ERROR_SUCCESS;
#endif // BTHNS_THREAD_SAFTEY
}

int WSAAPI BTH_NSPSetServiceThunk(LPGUID lpProviderId, LPWSASERVICECLASSINFOW lpServiceClassInfo, LPWSAQUERYSETW lpqsRegInfo, WSAESETSERVICEOP essOperation, DWORD dwControlFlags) {
    return BthNsSetService(lpqsRegInfo,essOperation,dwControlFlags);
}

int WSAAPI BTH_NSPLookupServiceBeginThunk(LPGUID pProviderId, LPWSAQUERYSETW pRestrict, LPWSASERVICECLASSINFOW pServiceClass, DWORD ControlFlags, LPHANDLE phLookup) {
    return BthNsLookupServiceBegin(pRestrict,ControlFlags,phLookup);
}

int WSAAPI BTH_NSPLookupServiceNextThunk(HANDLE hLookup, DWORD ControlFlags, DWORD *pcBuf, LPWSAQUERYSETW pResults) {
    return BthNsLookupServiceNext(hLookup,ControlFlags,pcBuf,pResults);
}

int WINAPI BTH_NSPLookupServiceEndThunk(HANDLE hLookup) {
    return BthNsLookupServiceEnd(hLookup);
}

int WSAAPI BTH_NSPRemoveServiceClass(LPGUID pProviderId, LPGUID lpServiceClassId) {
    ASSERT(0);
    SetLastError(WSAEOPNOTSUPP);
    return SOCKET_ERROR;
}

int WSAAPI BTH_NSPGetServiceClassInfo(LPGUID lpProviderId, LPDWORD lpdwBufSize, LPWSASERVICECLASSINFOW lpServiceClass) {
    ASSERT(0);
    SetLastError(WSAEOPNOTSUPP);
    return SOCKET_ERROR;
}

int WSAAPI BTH_NSPIoctlThunk(HANDLE hLookup,    DWORD dwControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer, LPVOID lpvOutBuffer,
                    DWORD cbOutBuffer, LPDWORD lpcbBytesReturned, LPWSACOMPLETION lpCompletion,    LPWSATHREADID lpThreadId) 
{
    ASSERT(0);
    SetLastError(WSAEOPNOTSUPP);
    return SOCKET_ERROR;
}

int WINAPI BTH_NSPInstallServiceClass(LPGUID pProviderId, PWSASERVICECLASSINFOW  pServiceClassInfo) {
    ASSERT(0);
    SetLastError( WSAEOPNOTSUPP );
    return( SOCKET_ERROR );
}

//
//   Called during name space provider installation.
//
int WSAAPI NSPStartup(LPGUID lpProviderId, LPNSP_ROUTINE lpnspRoutines) {
    int iError = ERROR_SUCCESS;

    __try {
        // should we check the provider id???
        
        // NSPIoctl was apparently newly added so size they give us may not
        // include it
        if (lpnspRoutines->cbSize < ((int)(&(((NSP_ROUTINE *)0)->NSPIoctl)))) {
            iError = WSAEINVAL;
        } else {
            lpnspRoutines->dwMajorVersion = 1;
            lpnspRoutines->dwMinorVersion = 1;

            lpnspRoutines->NSPCleanup = &BTH_NSPCleanup;
            lpnspRoutines->NSPLookupServiceBegin = &BTH_NSPLookupServiceBeginThunk;
            lpnspRoutines->NSPLookupServiceNext = &BTH_NSPLookupServiceNextThunk;
            lpnspRoutines->NSPLookupServiceEnd = &BTH_NSPLookupServiceEndThunk;
            lpnspRoutines->NSPSetService = &BTH_NSPSetServiceThunk;
            lpnspRoutines->NSPInstallServiceClass = &BTH_NSPInstallServiceClass;
            lpnspRoutines->NSPRemoveServiceClass = &BTH_NSPRemoveServiceClass;
            lpnspRoutines->NSPGetServiceClassInfo = &BTH_NSPGetServiceClassInfo;

#if BTHNS_THREAD_SAFTEY
            EnterCriticalSection(&g_bthNsCritSec);
            g_cStartups++;
            ASSERT(g_cStartups > 0);
            LeaveCriticalSection(&g_bthNsCritSec);
#endif // BTHNS_THREAD_SAFTEY
        }
    }
    __except (EXCEPTION_EXECUTE_HANDLER) {
        iError = WSAEFAULT;
    }

    if (iError) {
        SetLastError(iError);
        iError = SOCKET_ERROR;
    }

    return iError;
}
