|
|
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
regbind.c
Abstract:
This module contains routines for binding and unbinding to the Win32 Registry server.
Author:
David J. Gilman (davegi) 06-Feb-1992
Revision History: Dragos C. Sambotin (dragoss) 21-May-1999 Moved this code from ..\client\bind.c Added EndpointConn_np (pipe connecting) Added BaseBindToMachineShutdownInterface to bind to the new winlogon ShutDown interface
--*/
#include <ntrpcp.h>
#include <rpc.h>
#include "shutinit.h"
#include "regconn.h"
//
// wRegConn_bind - common function to bind to a transport and free the
// string binding.
//
wRegConn_bind( LPWSTR * StringBinding, RPC_BINDING_HANDLE * pBindingHandle ) { DWORD RpcStatus;
RpcStatus = RpcBindingFromStringBindingW(*StringBinding,pBindingHandle);
RpcStringFreeW(StringBinding); if ( RpcStatus != RPC_S_OK ) { *pBindingHandle = NULL; return RpcStatus; } return(ERROR_SUCCESS); }
/*++
Routine Description for the RegConn_* functions:
Bind to the RPC server over the specified transport
Arguments:
ServerName - Name of server to bind with (or netaddress).
pBindingHandle - Location where binding handle is to be placed
Return Value:
ERROR_SUCCESS - The binding has been successfully completed.
ERROR_INVALID_COMPUTER_NAME - The ServerName syntax is invalid.
ERROR_NO_MEMORY - There is not sufficient memory available to the caller to perform the binding.
--*/
//
// wRegConn_Netbios - Worker function to get a binding handle for any of the
// netbios protocols
//
DWORD wRegConn_Netbios( IN LPWSTR rpc_protocol, IN LPCWSTR ServerName, OUT RPC_BINDING_HANDLE * pBindingHandle )
{ RPC_STATUS RpcStatus; LPWSTR StringBinding; LPCWSTR PlainServerName;
*pBindingHandle = NULL;
//
// Ignore leading "\\"
//
if ((ServerName[0] == '\\') && (ServerName[1] == '\\')) { PlainServerName = &ServerName[2]; } else { PlainServerName = ServerName; }
RpcStatus = RpcStringBindingComposeW(0, rpc_protocol, (LPWSTR)PlainServerName, NULL, // endpoint
NULL, &StringBinding);
if ( RpcStatus != RPC_S_OK ) { return( ERROR_BAD_NETPATH ); } return(wRegConn_bind(&StringBinding, pBindingHandle)); }
DWORD RegConn_nb_nb( IN LPCWSTR ServerName, OUT RPC_BINDING_HANDLE * pBindingHandle ) { return(wRegConn_Netbios(L"ncacn_nb_nb", ServerName, pBindingHandle)); }
DWORD RegConn_nb_tcp( IN LPCWSTR ServerName, OUT RPC_BINDING_HANDLE * pBindingHandle ) { return(wRegConn_Netbios(L"ncacn_nb_tcp", ServerName, pBindingHandle)); }
DWORD RegConn_nb_ipx( IN LPCWSTR ServerName, OUT RPC_BINDING_HANDLE * pBindingHandle ) { return(wRegConn_Netbios(L"ncacn_nb_ipx", ServerName, pBindingHandle)); }
//
// EndpointConn_np - connects to a specific pipe on the remote machine
// (Win95 does not support server-side named pipes)
//
DWORD EndpointConn_np( IN LPCWSTR ServerName, IN unsigned short * Endpoint, OUT RPC_BINDING_HANDLE * pBindingHandle ) { RPC_STATUS RpcStatus; LPWSTR StringBinding; LPWSTR SlashServerName; int have_slashes; ULONG NameLen;
*pBindingHandle = NULL;
if (ServerName[1] == L'\\') { have_slashes = 1; } else { have_slashes = 0; }
//
// Be nice and prepend slashes if not supplied.
//
NameLen = lstrlenW(ServerName); if ((!have_slashes) && (NameLen > 0)) {
//
// Allocate new buffer large enough for two forward slashes and a
// NULL terminator.
//
SlashServerName = LocalAlloc(LMEM_FIXED, (NameLen + 3) * sizeof(WCHAR)); if (SlashServerName == NULL) { return(ERROR_NOT_ENOUGH_MEMORY); } SlashServerName[0] = L'\\'; SlashServerName[1] = L'\\'; lstrcpyW(&SlashServerName[2], ServerName); } else { SlashServerName = (LPWSTR)ServerName; }
RpcStatus = RpcStringBindingComposeW(0, L"ncacn_np", SlashServerName, Endpoint, NULL, &StringBinding); if (SlashServerName != ServerName) { LocalFree(SlashServerName); }
if ( RpcStatus != RPC_S_OK ) { return( ERROR_BAD_NETPATH ); }
return(wRegConn_bind(&StringBinding, pBindingHandle)); }
//
// RegConn_np - get a remote registry RPC binding handle for an NT server
// (Win95 does not support server-side named pipes)
//
DWORD RegConn_np( IN LPCWSTR ServerName, OUT RPC_BINDING_HANDLE * pBindingHandle ) { return EndpointConn_np(ServerName,L"\\PIPE\\winreg",pBindingHandle); }
//
// RegConn_spx - Use the Netbios connection function, RPC will resolve the name
// via winsock.
//
DWORD RegConn_spx( IN LPCWSTR ServerName, OUT RPC_BINDING_HANDLE * pBindingHandle ) { return(wRegConn_Netbios(L"ncacn_spx", ServerName, pBindingHandle)); }
DWORD RegConn_ip_tcp( IN LPCWSTR ServerName, OUT RPC_BINDING_HANDLE * pBindingHandle )
{ return(wRegConn_Netbios(L"ncacn_ip_tcp", ServerName, pBindingHandle)); }
RPC_BINDING_HANDLE PREGISTRY_SERVER_NAME_bind( PREGISTRY_SERVER_NAME ServerName )
/*++
Routine Description:
To make the remote registry multi-protocol aware, PREGISTRY_SERVER_NAME parameter actually points to an already bound binding handle. PREGISTRY_SERVER_NAME is declared a PWSTR only to help maintain compatibility with NT.
--*/
{ return(*(RPC_BINDING_HANDLE *)ServerName); }
void PREGISTRY_SERVER_NAME_unbind( PREGISTRY_SERVER_NAME ServerName, RPC_BINDING_HANDLE BindingHandle )
/*++
Routine Description:
This routine unbinds the RPC client from the server. It is called directly from the RPC stub that references the handle.
Arguments:
ServerName - Not used.
BindingHandle - Supplies the handle to unbind.
Return Value:
None.
--*/
{ DWORD Status;
UNREFERENCED_PARAMETER( ServerName ); return;
}
LONG BaseBindToMachineShutdownInterface( IN LPCWSTR lpMachineName, IN PBIND_CALLBACK BindCallback, IN PVOID Context1, IN PVOID Context2 )
/*++
Routine Description:
This is a helper routine used to create an RPC binding from a given machine name to the shutdown interface (now residing in winlogon)
Arguments:
lpMachineName - Supplies a pointer to a machine name. Must not be NULL.
BindCallback - Supplies the function that should be called once a binding has been created to initiate the connection.
Context1 - Supplies the first parameter to pass to the callback routine.
Context2 - Supplies the second parameter to pass to the callback routine.
Return Value:
Returns ERROR_SUCCESS (0) for success; error-code for failure.
--*/
{ LONG Error; RPC_BINDING_HANDLE binding;
Error = EndpointConn_np(lpMachineName,L"\\PIPE\\InitShutdown",&binding);
if (Error == ERROR_SUCCESS) {
//
// For the named pipes protocol, we use a static endpoint, so the
// call to RpcEpResolveBinding is not needed.
// Also, the server checks the user's credentials on opening
// the named pipe, so RpcBindingSetAuthInfo is not needed.
//
Error = (BindCallback)(&binding, Context1, Context2); RpcBindingFree(&binding); if (Error != RPC_S_SERVER_UNAVAILABLE) { return Error; } }
if (Error != ERROR_SUCCESS) { if ((Error == RPC_S_INVALID_ENDPOINT_FORMAT) || (Error == RPC_S_INVALID_NET_ADDR) ) { Error = ERROR_INVALID_COMPUTERNAME; } else { Error = ERROR_BAD_NETPATH; } }
return(Error); }
|