387 lines
8.7 KiB
C
387 lines
8.7 KiB
C
|
/*++
|
||
|
|
||
|
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);
|
||
|
}
|
||
|
|
||
|
|