You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
904 lines
25 KiB
904 lines
25 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ioctl.c
|
|
|
|
Abstract:
|
|
|
|
Implements resource and resource type IOCTL interfaces in
|
|
the CLUSAPI.
|
|
|
|
Author:
|
|
|
|
John Vert (jvert) 10/9/1996
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#include "clusapip.h"
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ClusterResourceControl(
|
|
IN HRESOURCE hResource,
|
|
IN OPTIONAL HNODE hHostNode,
|
|
IN DWORD dwControlCode,
|
|
IN LPVOID lpInBuffer,
|
|
IN DWORD nInBufferSize,
|
|
OUT LPVOID lpOutBuffer,
|
|
IN DWORD nOutBufferSize,
|
|
OUT LPDWORD lpBytesReturned
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Provides for arbitrary communication and control between an application
|
|
and a specific instance of a resource.
|
|
|
|
Arguments:
|
|
|
|
hResource - Supplies a handle to the resource to be controlled.
|
|
|
|
hHostNode - Supplies a handle to the node on which the resource
|
|
control should be delivered. If this is NULL, the node where
|
|
the resource is online is used.
|
|
|
|
dwControlCode- Supplies the control code that defines the
|
|
structure and action of the resource control.
|
|
Values of dwControlCode between 0 and 0x10000000 are reserved
|
|
for future definition and use by Microsoft. All other values
|
|
are available for use by ISVs.
|
|
|
|
lpInBuffer- Supplies a pointer to the input buffer to be passed
|
|
to the resource.
|
|
|
|
nInBufferSize- Supplies the size, in bytes, of the data pointed
|
|
to by lpInBuffer.
|
|
|
|
lpOutBuffer- Supplies a pointer to the output buffer to be
|
|
filled in by the resource.
|
|
|
|
nOutBufferSize- Supplies the size, in bytes, of the available
|
|
space pointed to by lpOutBuffer.
|
|
|
|
lpBytesReturned - Returns the number of bytes of lpOutBuffer
|
|
actually filled in by the resource.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful
|
|
|
|
Win32 error code otherwise
|
|
|
|
--*/
|
|
|
|
{
|
|
PCRESOURCE Resource;
|
|
HNODE_RPC hDestNode;
|
|
DWORD Status;
|
|
DWORD Required;
|
|
PVOID Buffer;
|
|
DWORD Dummy;
|
|
DWORD BytesReturned;
|
|
|
|
Buffer = lpOutBuffer;
|
|
if ((Buffer == NULL) &&
|
|
(nOutBufferSize == 0)) {
|
|
Buffer = &Dummy;
|
|
}
|
|
|
|
Resource = (PCRESOURCE)hResource;
|
|
if (ARGUMENT_PRESENT(hHostNode)) {
|
|
hDestNode = ((PCNODE)hHostNode)->hNode;
|
|
WRAP(Status,
|
|
(ApiNodeResourceControl(Resource->hResource,
|
|
hDestNode,
|
|
dwControlCode,
|
|
lpInBuffer,
|
|
nInBufferSize,
|
|
Buffer,
|
|
nOutBufferSize,
|
|
&BytesReturned,
|
|
&Required)),
|
|
Resource->Cluster);
|
|
} else {
|
|
|
|
WRAP(Status,
|
|
(ApiResourceControl(Resource->hResource,
|
|
dwControlCode,
|
|
lpInBuffer,
|
|
nInBufferSize,
|
|
Buffer,
|
|
nOutBufferSize,
|
|
&BytesReturned,
|
|
&Required)),
|
|
Resource->Cluster);
|
|
}
|
|
if ( (Status == ERROR_SUCCESS) ||
|
|
(Status == ERROR_MORE_DATA) ) {
|
|
if ( (Status == ERROR_MORE_DATA) &&
|
|
(lpOutBuffer == NULL) ) {
|
|
Status = ERROR_SUCCESS;
|
|
}
|
|
if ( !BytesReturned ) {
|
|
BytesReturned = Required;
|
|
}
|
|
}
|
|
|
|
if ( ARGUMENT_PRESENT(lpBytesReturned) ) {
|
|
*lpBytesReturned = BytesReturned;
|
|
} else {
|
|
if ( (Status == ERROR_SUCCESS) &&
|
|
(BytesReturned > nOutBufferSize) ) {
|
|
Status = ERROR_MORE_DATA;
|
|
}
|
|
}
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ClusterResourceTypeControl(
|
|
IN HCLUSTER hCluster,
|
|
IN LPCWSTR lpszResourceTypeName,
|
|
IN OPTIONAL HNODE hHostNode,
|
|
IN DWORD dwControlCode,
|
|
IN LPVOID lpInBuffer,
|
|
IN DWORD nInBufferSize,
|
|
OUT LPVOID lpOutBuffer,
|
|
IN DWORD nOutBufferSize,
|
|
OUT LPDWORD lpBytesReturned
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Provides for arbitrary communication and control between an application
|
|
and a specific instance of a resource type.
|
|
|
|
Arguments:
|
|
|
|
lpszResourceTypename - Supplies the name of the resource type to be
|
|
controlled.
|
|
|
|
hHostNode - Supplies a handle to the node on which the resource type
|
|
control should be delivered. If this is NULL, the node where
|
|
the application is bound performs the request.
|
|
|
|
dwControlCode- Supplies the control code that defines the
|
|
structure and action of the resource type control.
|
|
Values of dwControlCode between 0 and 0x10000000 are reserved
|
|
for future definition and use by Microsoft. All other values
|
|
are available for use by ISVs
|
|
|
|
lpInBuffer- Supplies a pointer to the input buffer to be passed
|
|
to the resource type.
|
|
|
|
nInBufferSize- Supplies the size, in bytes, of the data pointed
|
|
to by lpInBuffer.
|
|
|
|
lpOutBuffer- Supplies a pointer to the output buffer to be
|
|
filled in by the resource type.
|
|
|
|
nOutBufferSize- Supplies the size, in bytes, of the available
|
|
space pointed to by lpOutBuffer.
|
|
|
|
lpBytesReturned - Returns the number of bytes of lpOutBuffer
|
|
actually filled in by the resource type.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful
|
|
|
|
Win32 error code otherwise
|
|
|
|
--*/
|
|
|
|
{
|
|
PCLUSTER Cluster;
|
|
HNODE_RPC hDestNode;
|
|
DWORD Status;
|
|
DWORD Required;
|
|
PVOID Buffer;
|
|
DWORD Dummy;
|
|
DWORD BytesReturned;
|
|
|
|
Buffer = lpOutBuffer;
|
|
if ((Buffer == NULL) &&
|
|
(nOutBufferSize == 0)) {
|
|
Buffer = &Dummy;
|
|
}
|
|
|
|
Cluster = (PCLUSTER)hCluster;
|
|
if (ARGUMENT_PRESENT(hHostNode)) {
|
|
hDestNode = ((PCNODE)hHostNode)->hNode;
|
|
WRAP(Status,
|
|
(ApiNodeResourceTypeControl(Cluster->hCluster,
|
|
lpszResourceTypeName,
|
|
hDestNode,
|
|
dwControlCode,
|
|
lpInBuffer,
|
|
nInBufferSize,
|
|
Buffer,
|
|
nOutBufferSize,
|
|
&BytesReturned,
|
|
&Required)),
|
|
Cluster);
|
|
} else {
|
|
WRAP(Status,
|
|
(ApiResourceTypeControl(Cluster->hCluster,
|
|
lpszResourceTypeName,
|
|
dwControlCode,
|
|
lpInBuffer,
|
|
nInBufferSize,
|
|
Buffer,
|
|
nOutBufferSize,
|
|
&BytesReturned,
|
|
&Required)),
|
|
Cluster);
|
|
}
|
|
|
|
if ( (Status == ERROR_SUCCESS) ||
|
|
(Status == ERROR_MORE_DATA) ) {
|
|
if ( (Status == ERROR_MORE_DATA) &&
|
|
(lpOutBuffer == NULL) ) {
|
|
Status = ERROR_SUCCESS;
|
|
}
|
|
if ( !BytesReturned ) {
|
|
BytesReturned = Required;
|
|
}
|
|
}
|
|
|
|
if ( ARGUMENT_PRESENT(lpBytesReturned) ) {
|
|
*lpBytesReturned = BytesReturned;
|
|
} else {
|
|
if ( (Status == ERROR_SUCCESS) &&
|
|
(BytesReturned > nOutBufferSize) ) {
|
|
Status = ERROR_MORE_DATA;
|
|
}
|
|
}
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ClusterGroupControl(
|
|
IN HGROUP hGroup,
|
|
IN OPTIONAL HNODE hHostNode,
|
|
IN DWORD dwControlCode,
|
|
IN LPVOID lpInBuffer,
|
|
IN DWORD nInBufferSize,
|
|
OUT LPVOID lpOutBuffer,
|
|
IN DWORD nOutBufferSize,
|
|
OUT LPDWORD lpBytesReturned
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Provides for arbitrary communication and control between an application
|
|
and a specific instance of a group.
|
|
|
|
Arguments:
|
|
|
|
hGroup - Supplies a handle to the group to be controlled.
|
|
|
|
hHostNode - Supplies a handle to the node on which the group
|
|
control should be delivered. If this is NULL, the node where
|
|
the group is owned is used.
|
|
|
|
dwControlCode- Supplies the control code that defines the
|
|
structure and action of the resource control.
|
|
Values of dwControlCode between 0 and 0x10000000 are reserved
|
|
for future definition and use by Microsoft. All other values
|
|
are available for use by ISVs.
|
|
|
|
lpInBuffer- Supplies a pointer to the input buffer to be passed
|
|
to the group.
|
|
|
|
nInBufferSize- Supplies the size, in bytes, of the data pointed
|
|
to by lpInBuffer.
|
|
|
|
lpOutBuffer- Supplies a pointer to the output buffer to be
|
|
filled in by the group.
|
|
|
|
nOutBufferSize- Supplies the size, in bytes, of the available
|
|
space pointed to by lpOutBuffer.
|
|
|
|
lpBytesReturned - Returns the number of bytes of lpOutBuffer
|
|
actually filled in by the resource.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful
|
|
|
|
Win32 error code otherwise
|
|
|
|
--*/
|
|
|
|
{
|
|
PCGROUP Group;
|
|
HNODE_RPC hDestNode;
|
|
DWORD Status;
|
|
DWORD Required;
|
|
PVOID Buffer;
|
|
DWORD Dummy;
|
|
DWORD BytesReturned;
|
|
|
|
Buffer = lpOutBuffer;
|
|
if ((Buffer == NULL) &&
|
|
(nOutBufferSize == 0)) {
|
|
Buffer = &Dummy;
|
|
}
|
|
|
|
Group = (PCGROUP)hGroup;
|
|
if (ARGUMENT_PRESENT(hHostNode)) {
|
|
hDestNode = ((PCNODE)hHostNode)->hNode;
|
|
WRAP(Status,
|
|
(ApiNodeGroupControl(Group->hGroup,
|
|
hDestNode,
|
|
dwControlCode,
|
|
lpInBuffer,
|
|
nInBufferSize,
|
|
Buffer,
|
|
nOutBufferSize,
|
|
&BytesReturned,
|
|
&Required)),
|
|
Group->Cluster);
|
|
} else {
|
|
|
|
WRAP(Status,
|
|
(ApiGroupControl(Group->hGroup,
|
|
dwControlCode,
|
|
lpInBuffer,
|
|
nInBufferSize,
|
|
Buffer,
|
|
nOutBufferSize,
|
|
&BytesReturned,
|
|
&Required)),
|
|
Group->Cluster);
|
|
}
|
|
if ( (Status == ERROR_SUCCESS) ||
|
|
(Status == ERROR_MORE_DATA) ) {
|
|
if ( (Status == ERROR_MORE_DATA) &&
|
|
(lpOutBuffer == NULL) ) {
|
|
Status = ERROR_SUCCESS;
|
|
}
|
|
if ( !BytesReturned ) {
|
|
BytesReturned = Required;
|
|
}
|
|
}
|
|
|
|
if ( ARGUMENT_PRESENT(lpBytesReturned) ) {
|
|
*lpBytesReturned = BytesReturned;
|
|
} else {
|
|
if ( (Status == ERROR_SUCCESS) &&
|
|
(BytesReturned > nOutBufferSize) ) {
|
|
Status = ERROR_MORE_DATA;
|
|
}
|
|
}
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ClusterNodeControl(
|
|
IN HNODE hNode,
|
|
IN OPTIONAL HNODE hHostNode,
|
|
IN DWORD dwControlCode,
|
|
IN LPVOID lpInBuffer,
|
|
IN DWORD nInBufferSize,
|
|
OUT LPVOID lpOutBuffer,
|
|
IN DWORD nOutBufferSize,
|
|
OUT LPDWORD lpBytesReturned
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Provides for arbitrary communication and control between an application
|
|
and a specific instance of a node.
|
|
|
|
Arguments:
|
|
|
|
hNode - Supplies a handle to the node to be controlled.
|
|
|
|
hHostNode - Supplies a handle to the node on which the node
|
|
control should be delivered. If this is NULL, the node where
|
|
the application is bound performs the request.
|
|
|
|
dwControlCode- Supplies the control code that defines the
|
|
structure and action of the resource control.
|
|
Values of dwControlCode between 0 and 0x10000000 are reserved
|
|
for future definition and use by Microsoft. All other values
|
|
are available for use by ISVs.
|
|
|
|
lpInBuffer- Supplies a pointer to the input buffer to be passed
|
|
to the node.
|
|
|
|
nInBufferSize- Supplies the size, in bytes, of the data pointed
|
|
to by lpInBuffer.
|
|
|
|
lpOutBuffer- Supplies a pointer to the output buffer to be
|
|
filled in by the node.
|
|
|
|
nOutBufferSize- Supplies the size, in bytes, of the available
|
|
space pointed to by lpOutBuffer.
|
|
|
|
lpBytesReturned - Returns the number of bytes of lpOutBuffer
|
|
actually filled in by the node.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful
|
|
|
|
Win32 error code otherwise
|
|
|
|
--*/
|
|
|
|
{
|
|
PCNODE Node;
|
|
HNODE_RPC hDestNode;
|
|
DWORD Status;
|
|
DWORD Required;
|
|
PVOID Buffer;
|
|
DWORD Dummy;
|
|
DWORD BytesReturned;
|
|
|
|
Buffer = lpOutBuffer;
|
|
if ((Buffer == NULL) &&
|
|
(nOutBufferSize == 0)) {
|
|
Buffer = &Dummy;
|
|
}
|
|
|
|
Node = (PCNODE)hNode;
|
|
if (ARGUMENT_PRESENT(hHostNode)) {
|
|
hDestNode = ((PCNODE)hHostNode)->hNode;
|
|
WRAP(Status,
|
|
(ApiNodeNodeControl(Node->hNode,
|
|
hDestNode,
|
|
dwControlCode,
|
|
lpInBuffer,
|
|
nInBufferSize,
|
|
Buffer,
|
|
nOutBufferSize,
|
|
&BytesReturned,
|
|
&Required)),
|
|
Node->Cluster);
|
|
} else {
|
|
|
|
WRAP(Status,
|
|
(ApiNodeControl(Node->hNode,
|
|
dwControlCode,
|
|
lpInBuffer,
|
|
nInBufferSize,
|
|
Buffer,
|
|
nOutBufferSize,
|
|
&BytesReturned,
|
|
&Required)),
|
|
Node->Cluster);
|
|
}
|
|
if ( (Status == ERROR_SUCCESS) ||
|
|
(Status == ERROR_MORE_DATA) ) {
|
|
if ( (Status == ERROR_MORE_DATA) &&
|
|
(lpOutBuffer == NULL) ) {
|
|
Status = ERROR_SUCCESS;
|
|
}
|
|
if ( !BytesReturned ) {
|
|
BytesReturned = Required;
|
|
}
|
|
}
|
|
|
|
if ( ARGUMENT_PRESENT(lpBytesReturned) ) {
|
|
*lpBytesReturned = BytesReturned;
|
|
} else {
|
|
if ( (Status == ERROR_SUCCESS) &&
|
|
(BytesReturned > nOutBufferSize) ) {
|
|
Status = ERROR_MORE_DATA;
|
|
}
|
|
}
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ClusterNetworkControl(
|
|
IN HNETWORK hNetwork,
|
|
IN OPTIONAL HNODE hHostNode,
|
|
IN DWORD dwControlCode,
|
|
IN LPVOID lpInBuffer,
|
|
IN DWORD nInBufferSize,
|
|
OUT LPVOID lpOutBuffer,
|
|
IN DWORD nOutBufferSize,
|
|
OUT LPDWORD lpBytesReturned
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Provides for arbitrary communication and control between an application
|
|
and a specific instance of a network.
|
|
|
|
Arguments:
|
|
|
|
hNetwork - Supplies a handle to the network to be controlled.
|
|
|
|
hHostNode - Supplies a handle to the node on which the node
|
|
control should be delivered. If this is NULL, the node where
|
|
the application is bound performs the request.
|
|
|
|
dwControlCode- Supplies the control code that defines the
|
|
structure and action of the resource control.
|
|
Values of dwControlCode between 0 and 0x10000000 are reserved
|
|
for future definition and use by Microsoft. All other values
|
|
are available for use by ISVs.
|
|
|
|
lpInBuffer- Supplies a pointer to the input buffer to be passed
|
|
to the network.
|
|
|
|
nInBufferSize- Supplies the size, in bytes, of the data pointed
|
|
to by lpInBuffer.
|
|
|
|
lpOutBuffer- Supplies a pointer to the output buffer to be
|
|
filled in by the network.
|
|
|
|
nOutBufferSize- Supplies the size, in bytes, of the available
|
|
space pointed to by lpOutBuffer.
|
|
|
|
lpBytesReturned - Returns the number of bytes of lpOutBuffer
|
|
actually filled in by the network.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful
|
|
|
|
Win32 error code otherwise
|
|
|
|
--*/
|
|
|
|
{
|
|
PCNETWORK Network;
|
|
HNODE_RPC hDestNode;
|
|
DWORD Status;
|
|
DWORD Required;
|
|
PVOID Buffer;
|
|
DWORD Dummy;
|
|
DWORD BytesReturned = 0;
|
|
|
|
Buffer = lpOutBuffer;
|
|
if ((Buffer == NULL) && (nOutBufferSize == 0)) {
|
|
Buffer = &Dummy;
|
|
}
|
|
|
|
Network = (PCNETWORK)hNetwork;
|
|
|
|
//
|
|
// another node was specified so redirect the request to it
|
|
//
|
|
|
|
if (ARGUMENT_PRESENT(hHostNode)) {
|
|
|
|
hDestNode = ((PCNODE)hHostNode)->hNode;
|
|
WRAP(Status,
|
|
(ApiNodeNetworkControl(Network->hNetwork,
|
|
hDestNode,
|
|
dwControlCode,
|
|
lpInBuffer,
|
|
nInBufferSize,
|
|
Buffer,
|
|
nOutBufferSize,
|
|
&BytesReturned,
|
|
&Required)),
|
|
Network->Cluster);
|
|
} else {
|
|
|
|
WRAP(Status,
|
|
(ApiNetworkControl(Network->hNetwork,
|
|
dwControlCode,
|
|
lpInBuffer,
|
|
nInBufferSize,
|
|
Buffer,
|
|
nOutBufferSize,
|
|
&BytesReturned,
|
|
&Required)),
|
|
Network->Cluster);
|
|
}
|
|
|
|
if ( (Status == ERROR_SUCCESS) || (Status == ERROR_MORE_DATA) ) {
|
|
|
|
if ( (Status == ERROR_MORE_DATA) && (lpOutBuffer == NULL) ) {
|
|
Status = ERROR_SUCCESS;
|
|
}
|
|
|
|
if ( !BytesReturned ) {
|
|
BytesReturned = Required;
|
|
}
|
|
}
|
|
|
|
if ( ARGUMENT_PRESENT(lpBytesReturned) ) {
|
|
*lpBytesReturned = BytesReturned;
|
|
} else {
|
|
if ( (Status == ERROR_SUCCESS) &&
|
|
(BytesReturned > nOutBufferSize) ) {
|
|
Status = ERROR_MORE_DATA;
|
|
}
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ClusterNetInterfaceControl(
|
|
IN HNETINTERFACE hNetInterface,
|
|
IN OPTIONAL HNODE hHostNode,
|
|
IN DWORD dwControlCode,
|
|
IN LPVOID lpInBuffer,
|
|
IN DWORD nInBufferSize,
|
|
OUT LPVOID lpOutBuffer,
|
|
IN DWORD nOutBufferSize,
|
|
OUT LPDWORD lpBytesReturned
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Provides for arbitrary communication and control between an application
|
|
and a specific instance of a network interface.
|
|
|
|
Arguments:
|
|
|
|
hNetInterface - Supplies a handle to the netinterface to be controlled.
|
|
|
|
hHostNode - Supplies a handle to the node on which the node
|
|
control should be delivered. If this is NULL, the node where
|
|
the application is bound performs the request.
|
|
|
|
dwControlCode- Supplies the control code that defines the
|
|
structure and action of the resource control.
|
|
Values of dwControlCode between 0 and 0x10000000 are reserved
|
|
for future definition and use by Microsoft. All other values
|
|
are available for use by ISVs.
|
|
|
|
lpInBuffer- Supplies a pointer to the input buffer to be passed
|
|
to the network.
|
|
|
|
nInBufferSize- Supplies the size, in bytes, of the data pointed
|
|
to by lpInBuffer.
|
|
|
|
lpOutBuffer- Supplies a pointer to the output buffer to be
|
|
filled in by the network.
|
|
|
|
nOutBufferSize- Supplies the size, in bytes, of the available
|
|
space pointed to by lpOutBuffer.
|
|
|
|
lpBytesReturned - Returns the number of bytes of lpOutBuffer
|
|
actually filled in by the network.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful
|
|
|
|
Win32 error code otherwise
|
|
|
|
--*/
|
|
|
|
{
|
|
PCNETINTERFACE NetInterface;
|
|
HNODE_RPC hDestNode;
|
|
DWORD Status;
|
|
DWORD Required;
|
|
PVOID Buffer;
|
|
DWORD Dummy;
|
|
DWORD BytesReturned = 0;
|
|
|
|
Buffer = lpOutBuffer;
|
|
if ((Buffer == NULL) && (nOutBufferSize == 0)) {
|
|
Buffer = &Dummy;
|
|
}
|
|
|
|
NetInterface = (PCNETINTERFACE)hNetInterface;
|
|
|
|
//
|
|
// another node was specified so redirect the request to it
|
|
//
|
|
|
|
if (ARGUMENT_PRESENT(hHostNode)) {
|
|
|
|
hDestNode = ((PCNODE)hHostNode)->hNode;
|
|
WRAP(Status,
|
|
(ApiNodeNetInterfaceControl(NetInterface->hNetInterface,
|
|
hDestNode,
|
|
dwControlCode,
|
|
lpInBuffer,
|
|
nInBufferSize,
|
|
Buffer,
|
|
nOutBufferSize,
|
|
&BytesReturned,
|
|
&Required)),
|
|
NetInterface->Cluster);
|
|
} else {
|
|
|
|
WRAP(Status,
|
|
(ApiNetInterfaceControl(NetInterface->hNetInterface,
|
|
dwControlCode,
|
|
lpInBuffer,
|
|
nInBufferSize,
|
|
Buffer,
|
|
nOutBufferSize,
|
|
&BytesReturned,
|
|
&Required)),
|
|
NetInterface->Cluster);
|
|
}
|
|
|
|
if ( (Status == ERROR_SUCCESS) || (Status == ERROR_MORE_DATA) ) {
|
|
|
|
if ( (Status == ERROR_MORE_DATA) && (lpOutBuffer == NULL) ) {
|
|
Status = ERROR_SUCCESS;
|
|
}
|
|
|
|
if ( !BytesReturned ) {
|
|
BytesReturned = Required;
|
|
}
|
|
}
|
|
|
|
if ( ARGUMENT_PRESENT(lpBytesReturned) ) {
|
|
*lpBytesReturned = BytesReturned;
|
|
} else {
|
|
if ( (Status == ERROR_SUCCESS) &&
|
|
(BytesReturned > nOutBufferSize) ) {
|
|
Status = ERROR_MORE_DATA;
|
|
}
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ClusterControl(
|
|
IN HCLUSTER hCluster,
|
|
IN OPTIONAL HNODE hHostNode,
|
|
IN DWORD dwControlCode,
|
|
IN LPVOID lpInBuffer,
|
|
IN DWORD nInBufferSize,
|
|
OUT LPVOID lpOutBuffer,
|
|
IN DWORD nOutBufferSize,
|
|
OUT LPDWORD lpBytesReturned
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Provides for arbitrary communication and control between an application
|
|
and a specific instance of a cluster.
|
|
|
|
Arguments:
|
|
|
|
hCluster - Supplies a handle to the cluster to be controlled.
|
|
|
|
hHostNode - Supplies a handle to the node on which the cluster
|
|
control should be delivered. If this is NULL, the node where
|
|
the application is bound performs the request.
|
|
|
|
dwControlCode- Supplies the control code that defines the
|
|
structure and action of the cluster control.
|
|
Values of dwControlCode between 0 and 0x10000000 are reserved
|
|
for future definition and use by Microsoft. All other values
|
|
are available for use by ISVs.
|
|
|
|
lpInBuffer- Supplies a pointer to the input buffer to be passed
|
|
to the cluster.
|
|
|
|
nInBufferSize- Supplies the size, in bytes, of the data pointed
|
|
to by lpInBuffer.
|
|
|
|
lpOutBuffer- Supplies a pointer to the output buffer to be
|
|
filled in by the cluster.
|
|
|
|
nOutBufferSize- Supplies the size, in bytes, of the available
|
|
space pointed to by lpOutBuffer.
|
|
|
|
lpBytesReturned - Returns the number of bytes of lpOutBuffer
|
|
actually filled in by the cluster.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful
|
|
|
|
Win32 error code otherwise
|
|
|
|
--*/
|
|
|
|
{
|
|
HNODE_RPC hDestNode;
|
|
DWORD Status;
|
|
DWORD Required;
|
|
PVOID Buffer;
|
|
DWORD Dummy;
|
|
DWORD BytesReturned;
|
|
PCLUSTER pCluster;
|
|
|
|
|
|
Buffer = lpOutBuffer;
|
|
if ((Buffer == NULL) &&
|
|
(nOutBufferSize == 0)) {
|
|
Buffer = &Dummy;
|
|
}
|
|
|
|
pCluster = GET_CLUSTER(hCluster);
|
|
|
|
if (ARGUMENT_PRESENT(hHostNode)) {
|
|
hDestNode = ((PCNODE)hHostNode)->hNode;
|
|
WRAP(Status,
|
|
(ApiNodeClusterControl(pCluster->hCluster,
|
|
hDestNode,
|
|
dwControlCode,
|
|
lpInBuffer,
|
|
nInBufferSize,
|
|
Buffer,
|
|
nOutBufferSize,
|
|
&BytesReturned,
|
|
&Required)),
|
|
pCluster);
|
|
} else {
|
|
|
|
WRAP(Status,
|
|
(ApiClusterControl(pCluster->hCluster,
|
|
dwControlCode,
|
|
lpInBuffer,
|
|
nInBufferSize,
|
|
Buffer,
|
|
nOutBufferSize,
|
|
&BytesReturned,
|
|
&Required)),
|
|
pCluster);
|
|
}
|
|
if ( (Status == ERROR_SUCCESS) ||
|
|
(Status == ERROR_MORE_DATA) ) {
|
|
if ( (Status == ERROR_MORE_DATA) &&
|
|
(lpOutBuffer == NULL) ) {
|
|
Status = ERROR_SUCCESS;
|
|
}
|
|
if ( !BytesReturned ) {
|
|
BytesReturned = Required;
|
|
}
|
|
}
|
|
|
|
if ( ARGUMENT_PRESENT(lpBytesReturned) ) {
|
|
*lpBytesReturned = BytesReturned;
|
|
} else {
|
|
if ( (Status == ERROR_SUCCESS) &&
|
|
(BytesReturned > nOutBufferSize) ) {
|
|
Status = ERROR_MORE_DATA;
|
|
}
|
|
}
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
|
|
|