1053 lines
24 KiB
C
1053 lines
24 KiB
C
#include <nt.h>
|
||
#include <ntrtl.h>
|
||
#include <nturtl.h>
|
||
#include <windows.h>
|
||
#include <objbase.h>
|
||
#include <wchar.h>
|
||
#include <cluster.h>
|
||
#include <clusrpc.h>
|
||
#include <clnetcfg.h>
|
||
#include <iphlpapi.h>
|
||
#include <winsock2.h>
|
||
|
||
#define NM_WCSLEN(_string) ((lstrlenW(_string) + 1) * sizeof(WCHAR))
|
||
|
||
CLNET_CONFIG_LISTS ConfigLists;
|
||
LPWSTR NodeName = L"TestComputer";
|
||
LPWSTR NodeId = L"1";
|
||
|
||
#if 0
|
||
#include <dm.h>
|
||
#include <dmp.h>
|
||
|
||
HKEY DmpRoot;
|
||
LIST_ENTRY KeyList;
|
||
CRITICAL_SECTION KeyLock;
|
||
HDMKEY DmClusterParametersKey;
|
||
HDMKEY DmResourcesKey;
|
||
HDMKEY DmResourceTypesKey;
|
||
HDMKEY DmGroupsKey;
|
||
HDMKEY DmNodesKey;
|
||
HDMKEY DmNetworksKey;
|
||
HDMKEY DmNetInterfacesKey;
|
||
HDMKEY DmQuorumKey;
|
||
HANDLE ghQuoLogOpenEvent=NULL;
|
||
|
||
typedef struct _DMP_KEY_DEF {
|
||
HDMKEY *pKey;
|
||
LPWSTR Name;
|
||
} DMP_KEY_DEF;
|
||
|
||
DMP_KEY_DEF DmpKeyTable[] = {
|
||
{&DmResourcesKey, CLUSREG_KEYNAME_RESOURCES},
|
||
{&DmResourceTypesKey, CLUSREG_KEYNAME_RESOURCE_TYPES},
|
||
{&DmQuorumKey, CLUSREG_KEYNAME_QUORUM},
|
||
{&DmGroupsKey, CLUSREG_KEYNAME_GROUPS},
|
||
{&DmNodesKey, CLUSREG_KEYNAME_NODES},
|
||
{&DmNetworksKey, CLUSREG_KEYNAME_NETWORKS},
|
||
{&DmNetInterfacesKey, CLUSREG_KEYNAME_NETINTERFACES}};
|
||
#endif
|
||
|
||
VOID
|
||
ClNetPrint(
|
||
IN ULONG LogLevel,
|
||
IN PCHAR FormatString,
|
||
...
|
||
)
|
||
{
|
||
CHAR buffer[256];
|
||
DWORD bytes;
|
||
va_list argList;
|
||
|
||
va_start(argList, FormatString);
|
||
|
||
bytes = FormatMessageA(
|
||
FORMAT_MESSAGE_FROM_STRING,
|
||
FormatString,
|
||
0,
|
||
0,
|
||
buffer,
|
||
sizeof(buffer),
|
||
&argList
|
||
);
|
||
|
||
va_end(argList);
|
||
|
||
if (bytes != 0) {
|
||
printf("%s", buffer);
|
||
}
|
||
|
||
return;
|
||
|
||
} // ClNetPrint
|
||
|
||
VOID
|
||
ClNetLogEvent(
|
||
IN DWORD LogLevel,
|
||
IN DWORD MessageId
|
||
)
|
||
{
|
||
return;
|
||
|
||
} // ClNetLogEvent
|
||
|
||
VOID
|
||
ClNetLogEvent1(
|
||
IN DWORD LogLevel,
|
||
IN DWORD MessageId,
|
||
IN LPCWSTR Arg1
|
||
)
|
||
{
|
||
return;
|
||
|
||
} // ClNetLogEvent1
|
||
|
||
|
||
VOID
|
||
ClNetLogEvent2(
|
||
IN DWORD LogLevel,
|
||
IN DWORD MessageId,
|
||
IN LPCWSTR Arg1,
|
||
IN LPCWSTR Arg2
|
||
)
|
||
{
|
||
return;
|
||
|
||
} // ClNetLogEvent2
|
||
|
||
|
||
VOID
|
||
ClNetLogEvent3(
|
||
IN DWORD LogLevel,
|
||
IN DWORD MessageId,
|
||
IN LPCWSTR Arg1,
|
||
IN LPCWSTR Arg2,
|
||
IN LPCWSTR Arg3
|
||
)
|
||
{
|
||
return;
|
||
|
||
} // ClNetLogEvent3
|
||
|
||
|
||
void
|
||
PrintConfigEntry(
|
||
PCLNET_CONFIG_ENTRY ConfigEntry
|
||
)
|
||
{
|
||
PNM_NETWORK_INFO Network = &(ConfigEntry->NetworkInfo);
|
||
PNM_INTERFACE_INFO Interface = &(ConfigEntry->InterfaceInfo);
|
||
|
||
printf("\t*************\n");
|
||
printf("\tNet Id\t\t%ws\n", Network->Id);
|
||
printf("\tName\t\t%ws\n", Network->Name);
|
||
printf("\tDesc\t\t%ws\n", Network->Description);
|
||
printf("\tRole\t\t%u\n", Network->Role);
|
||
printf("\tPriority\t%u\n", Network->Priority);
|
||
printf("\tTransport\t%ws\n", Network->Transport);
|
||
printf("\tAddress\t\t%ws\n", Network->Address);
|
||
printf("\tMask\t\t%ws\n", Network->AddressMask);
|
||
printf("\tIf Id\t\t%ws\n", Interface->Id);
|
||
printf("\tName\t\t%ws\n", Interface->Name);
|
||
printf("\tDesc\t\t%ws\n", Interface->Description);
|
||
printf("\tNodeId\t\t%ws\n", Interface->NodeId);
|
||
printf("\tAdapter\t\t%ws\n", Interface->Adapter);
|
||
printf("\tAddress\t\t%ws\n", Interface->Address);
|
||
printf("\tEndpoint\t%ws\n", Interface->ClusnetEndpoint);
|
||
printf("\tState\t\t%u\n\n", Interface->State);
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
void
|
||
PrintResults(void)
|
||
{
|
||
PCLNET_CONFIG_ENTRY configEntry;
|
||
PLIST_ENTRY listEntry;
|
||
|
||
|
||
printf("Renamed interface list:\n");
|
||
|
||
for ( listEntry = ConfigLists.RenamedInterfaceList.Flink;
|
||
listEntry != &ConfigLists.RenamedInterfaceList;
|
||
listEntry = listEntry->Flink
|
||
)
|
||
{
|
||
configEntry = CONTAINING_RECORD(
|
||
listEntry,
|
||
CLNET_CONFIG_ENTRY,
|
||
Linkage
|
||
);
|
||
PrintConfigEntry(configEntry);
|
||
}
|
||
|
||
printf("Deleted interface list:\n");
|
||
|
||
for ( listEntry = ConfigLists.DeletedInterfaceList.Flink;
|
||
listEntry != &ConfigLists.DeletedInterfaceList;
|
||
listEntry = listEntry->Flink
|
||
)
|
||
{
|
||
configEntry = CONTAINING_RECORD(
|
||
listEntry,
|
||
CLNET_CONFIG_ENTRY,
|
||
Linkage
|
||
);
|
||
PrintConfigEntry(configEntry);
|
||
}
|
||
|
||
printf("Updated interface list:\n");
|
||
|
||
for ( listEntry = ConfigLists.UpdatedInterfaceList.Flink;
|
||
listEntry != &ConfigLists.UpdatedInterfaceList;
|
||
listEntry = listEntry->Flink
|
||
)
|
||
{
|
||
configEntry = CONTAINING_RECORD(
|
||
listEntry,
|
||
CLNET_CONFIG_ENTRY,
|
||
Linkage
|
||
);
|
||
PrintConfigEntry(configEntry);
|
||
}
|
||
|
||
printf("Created interface list:\n");
|
||
|
||
for ( listEntry = ConfigLists.CreatedInterfaceList.Flink;
|
||
listEntry != &ConfigLists.CreatedInterfaceList;
|
||
listEntry = listEntry->Flink
|
||
)
|
||
{
|
||
configEntry = CONTAINING_RECORD(
|
||
listEntry,
|
||
CLNET_CONFIG_ENTRY,
|
||
Linkage
|
||
);
|
||
PrintConfigEntry(configEntry);
|
||
}
|
||
|
||
printf("Created network list:\n");
|
||
|
||
for ( listEntry = ConfigLists.CreatedNetworkList.Flink;
|
||
listEntry != &ConfigLists.CreatedNetworkList;
|
||
listEntry = listEntry->Flink
|
||
)
|
||
{
|
||
configEntry = CONTAINING_RECORD(
|
||
listEntry,
|
||
CLNET_CONFIG_ENTRY,
|
||
Linkage
|
||
);
|
||
PrintConfigEntry(configEntry);
|
||
}
|
||
|
||
printf("Unchanged interface list:\n");
|
||
|
||
for ( listEntry = ConfigLists.InputConfigList.Flink;
|
||
listEntry != &ConfigLists.InputConfigList;
|
||
listEntry = listEntry->Flink
|
||
)
|
||
{
|
||
configEntry = CONTAINING_RECORD(
|
||
listEntry,
|
||
CLNET_CONFIG_ENTRY,
|
||
Linkage
|
||
);
|
||
PrintConfigEntry(configEntry);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
void
|
||
ConsolidateLists(
|
||
PLIST_ENTRY MasterList,
|
||
PLIST_ENTRY OtherList
|
||
)
|
||
{
|
||
PLIST_ENTRY entry;
|
||
|
||
while (!IsListEmpty(OtherList)) {
|
||
entry = RemoveHeadList(OtherList);
|
||
InsertTailList(MasterList, entry);
|
||
}
|
||
|
||
return;
|
||
}
|
||
#if 0
|
||
DWORD
|
||
DmpOpenKeys(
|
||
IN REGSAM samDesired
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Opens all the standard cluster registry keys. If any of the
|
||
keys are already opened, they will be closed and reopened.
|
||
|
||
Arguments:
|
||
|
||
samDesired - Supplies the access that the keys will be opened with.
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if successful.
|
||
|
||
Win32 error code otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD i;
|
||
DWORD status;
|
||
|
||
status = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
||
L"Cluster",
|
||
0,
|
||
samDesired,
|
||
&ClusterRegKey);
|
||
|
||
if ( status == ERROR_SUCCESS ) {
|
||
for (i=0;
|
||
i<sizeof(DmpKeyTable)/sizeof(DMP_KEY_DEF);
|
||
i++) {
|
||
|
||
*DmpKeyTable[i].pKey = DmOpenKey(DmClusterParametersKey,
|
||
DmpKeyTable[i].Name,
|
||
samDesired);
|
||
if (*DmpKeyTable[i].pKey == NULL) {
|
||
Status = GetLastError();
|
||
CsDbgPrint(LOG_CRITICAL,
|
||
("[DM]: Failed to open key %1!ws!, status %2!u!\n",
|
||
DmpKeyTable[i].Name,
|
||
Status));
|
||
CL_UNEXPECTED_ERROR( Status );
|
||
return(Status);
|
||
}
|
||
}
|
||
}
|
||
return status;
|
||
}
|
||
|
||
HDMKEY
|
||
DmOpenKey(
|
||
IN HDMKEY hKey,
|
||
IN LPCWSTR lpSubKey,
|
||
IN DWORD samDesired
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Opens a key in the cluster registry. If the key exists, it
|
||
is opened. If it does not exist, the call fails.
|
||
|
||
Arguments:
|
||
|
||
hKey - Supplies the key that the open is relative to.
|
||
|
||
lpSubKey - Supplies the key name relative to hKey
|
||
|
||
samDesired - Supplies desired security access mask
|
||
|
||
Return Value:
|
||
|
||
A handle to the specified key if successful
|
||
|
||
NULL otherwise. LastError will be set to the specific error code.
|
||
|
||
--*/
|
||
|
||
{
|
||
PDMKEY Parent;
|
||
PDMKEY Key=NULL;
|
||
DWORD NameLength;
|
||
DWORD Status = ERROR_SUCCESS;
|
||
|
||
Parent = (PDMKEY)hKey;
|
||
|
||
//check if the key was deleted and invalidated
|
||
if (ISKEYDELETED(Parent))
|
||
{
|
||
Status = ERROR_KEY_DELETED;
|
||
goto FnExit;
|
||
}
|
||
//
|
||
// Allocate the DMKEY structure.
|
||
//
|
||
NameLength = (lstrlenW(Parent->Name) + 1 + lstrlenW(lpSubKey) + 1)*sizeof(WCHAR);
|
||
Key = LocalAlloc(LMEM_FIXED, sizeof(DMKEY)+NameLength);
|
||
if (Key == NULL) {
|
||
Status = ERROR_NOT_ENOUGH_MEMORY;
|
||
CL_UNEXPECTED_ERROR(Status);
|
||
goto FnExit;
|
||
}
|
||
|
||
//
|
||
// Open the key on the local machine.
|
||
//
|
||
Status = RegOpenKeyEx(Parent->hKey,
|
||
lpSubKey,
|
||
0,
|
||
samDesired,
|
||
&Key->hKey);
|
||
if (Status != ERROR_SUCCESS) {
|
||
goto FnExit;
|
||
}
|
||
|
||
//
|
||
// Create the key name
|
||
//
|
||
lstrcpyW(Key->Name, Parent->Name);
|
||
if (Key->Name[0] != UNICODE_NULL) {
|
||
lstrcatW(Key->Name, L"\\");
|
||
}
|
||
lstrcatW(Key->Name, lpSubKey);
|
||
Key->GrantedAccess = samDesired;
|
||
|
||
EnterCriticalSection(&KeyLock);
|
||
InsertHeadList(&KeyList, &Key->ListEntry);
|
||
InitializeListHead(&Key->NotifyList);
|
||
LeaveCriticalSection(&KeyLock);
|
||
|
||
FnExit:
|
||
if (Status != ERROR_SUCCESS)
|
||
{
|
||
if (Key) LocalFree(Key);
|
||
SetLastError(Status);
|
||
return(NULL);
|
||
}
|
||
else
|
||
return((HDMKEY)Key);
|
||
|
||
|
||
}
|
||
|
||
|
||
DWORD
|
||
NmpQueryString(
|
||
IN HDMKEY Key,
|
||
IN LPCWSTR ValueName,
|
||
IN DWORD ValueType,
|
||
IN LPWSTR *StringBuffer,
|
||
IN OUT LPDWORD StringBufferSize,
|
||
OUT LPDWORD StringSize
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Reads a REG_SZ or REG_MULTI_SZ registry value. If the StringBuffer is
|
||
not large enough to hold the data, it is reallocated.
|
||
|
||
Arguments:
|
||
|
||
Key - Open key for the value to be read.
|
||
|
||
ValueName - Unicode name of the value to be read.
|
||
|
||
ValueType - REG_SZ or REG_MULTI_SZ.
|
||
|
||
StringBuffer - Buffer into which to place the value data.
|
||
|
||
StringBufferSize - Pointer to the size of the StringBuffer. This parameter
|
||
is updated if StringBuffer is reallocated.
|
||
|
||
StringSize - The size of the data returned in StringBuffer, including
|
||
the terminating null character.
|
||
|
||
Return Value:
|
||
|
||
The status of the registry query.
|
||
|
||
--*/
|
||
{
|
||
DWORD status;
|
||
DWORD valueType;
|
||
WCHAR *temp;
|
||
DWORD oldBufferSize = *StringBufferSize;
|
||
BOOL noBuffer = FALSE;
|
||
|
||
|
||
if (*StringBufferSize == 0) {
|
||
noBuffer = TRUE;
|
||
}
|
||
|
||
*StringSize = *StringBufferSize;
|
||
|
||
status = DmQueryValue( Key,
|
||
ValueName,
|
||
&valueType,
|
||
(LPBYTE) *StringBuffer,
|
||
StringSize
|
||
);
|
||
|
||
if (status == NO_ERROR) {
|
||
if (!noBuffer ) {
|
||
if (valueType == ValueType) {
|
||
return(NO_ERROR);
|
||
}
|
||
else {
|
||
return(ERROR_INVALID_PARAMETER);
|
||
}
|
||
}
|
||
|
||
status = ERROR_MORE_DATA;
|
||
}
|
||
|
||
if (status == ERROR_MORE_DATA) {
|
||
temp = MIDL_user_allocate(*StringSize);
|
||
|
||
if (temp == NULL) {
|
||
*StringSize = 0;
|
||
return(ERROR_NOT_ENOUGH_MEMORY);
|
||
}
|
||
|
||
if (!noBuffer) {
|
||
MIDL_user_free(*StringBuffer);
|
||
}
|
||
|
||
*StringBuffer = temp;
|
||
*StringBufferSize = *StringSize;
|
||
|
||
status = DmQueryValue( Key,
|
||
ValueName,
|
||
&valueType,
|
||
(LPBYTE) *StringBuffer,
|
||
StringSize
|
||
);
|
||
|
||
if (status == NO_ERROR) {
|
||
if (valueType == ValueType) {
|
||
return(NO_ERROR);
|
||
}
|
||
else {
|
||
*StringSize = 0;
|
||
return(ERROR_INVALID_PARAMETER);
|
||
}
|
||
}
|
||
}
|
||
|
||
return(status);
|
||
|
||
} // NmpQueryString
|
||
|
||
|
||
DWORD
|
||
NmpGetNetworkDefinition(
|
||
IN LPWSTR NetworkId,
|
||
OUT PNM_NETWORK_INFO NetworkInfo
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Reads information about a defined cluster network from the cluster
|
||
database and fills in a structure describing it.
|
||
|
||
Arguments:
|
||
|
||
NetworkId - A pointer to a unicode string containing the ID of the
|
||
network to query.
|
||
|
||
NetworkInfo - A pointer to the network info structure to fill in.
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if the routine succeeds.
|
||
A Win32 error code otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD status;
|
||
HDMKEY networkKey = NULL;
|
||
DWORD valueLength, valueSize;
|
||
DWORD i;
|
||
PNM_INTERFACE_ENUM interfaceEnum;
|
||
|
||
|
||
ZeroMemory(NetworkInfo, sizeof(NM_NETWORK_INFO));
|
||
|
||
//
|
||
// Open the network's key.
|
||
//
|
||
networkKey = DmOpenKey(DmNetworksKey, NetworkId, KEY_READ);
|
||
|
||
if (networkKey == NULL) {
|
||
status = GetLastError();
|
||
ClNetPrint(LOG_CRITICAL,
|
||
"[NM] Failed to open network key, status %1!u!\n",
|
||
status
|
||
);
|
||
goto error_exit;
|
||
}
|
||
|
||
//
|
||
// Copy the ID value.
|
||
//
|
||
NetworkInfo->Id = MIDL_user_allocate(NM_WCSLEN(NetworkId));
|
||
|
||
if (NetworkInfo->Id == NULL) {
|
||
status = ERROR_NOT_ENOUGH_MEMORY;
|
||
goto error_exit;
|
||
}
|
||
|
||
wcscpy(NetworkInfo->Id, NetworkId);
|
||
|
||
//
|
||
// Read the network's name.
|
||
//
|
||
valueLength = 0;
|
||
|
||
status = NmpQueryString(
|
||
networkKey,
|
||
CLUSREG_NAME_NET_NAME,
|
||
REG_SZ,
|
||
&(NetworkInfo->Name),
|
||
&valueLength,
|
||
&valueSize
|
||
);
|
||
|
||
if (status != ERROR_SUCCESS) {
|
||
ClNetPrint(LOG_CRITICAL,
|
||
"[NM] Query of name value failed for network %1!ws!, status %2!u!.\n",
|
||
NetworkId,
|
||
status
|
||
);
|
||
goto error_exit;
|
||
}
|
||
|
||
//
|
||
// Read the description value.
|
||
//
|
||
valueLength = 0;
|
||
|
||
status = NmpQueryString(
|
||
networkKey,
|
||
CLUSREG_NAME_NET_DESC,
|
||
REG_SZ,
|
||
&(NetworkInfo->Description),
|
||
&valueLength,
|
||
&valueSize
|
||
);
|
||
|
||
if (status != ERROR_SUCCESS) {
|
||
ClNetPrint(LOG_CRITICAL,
|
||
"[NM] Query of description value failed for network %1!ws!, status %2!u!.\n",
|
||
NetworkId,
|
||
status
|
||
);
|
||
goto error_exit;
|
||
}
|
||
|
||
//
|
||
// Read the role value.
|
||
//
|
||
status = DmQueryDword(
|
||
networkKey,
|
||
CLUSREG_NAME_NET_ROLE,
|
||
&(NetworkInfo->Role),
|
||
NULL
|
||
);
|
||
|
||
if (status != ERROR_SUCCESS) {
|
||
ClNetPrint(LOG_CRITICAL,
|
||
"[NM] Query of role value failed for network %1!ws!, status %2!u!.\n",
|
||
NetworkId,
|
||
status
|
||
);
|
||
goto error_exit;
|
||
}
|
||
|
||
//
|
||
// Read the priority value.
|
||
//
|
||
status = DmQueryDword(
|
||
networkKey,
|
||
CLUSREG_NAME_NET_PRIORITY,
|
||
&(NetworkInfo->Priority),
|
||
NULL
|
||
);
|
||
|
||
if (status != ERROR_SUCCESS) {
|
||
ClNetPrint(LOG_CRITICAL,
|
||
"[NM] Query of priority value failed for network %1!ws!, status %2!u!.\n",
|
||
NetworkId,
|
||
status
|
||
);
|
||
goto error_exit;
|
||
}
|
||
|
||
//
|
||
// Read the address value.
|
||
//
|
||
valueLength = 0;
|
||
|
||
status = NmpQueryString(
|
||
networkKey,
|
||
CLUSREG_NAME_NET_ADDRESS,
|
||
REG_SZ,
|
||
&(NetworkInfo->Address),
|
||
&valueLength,
|
||
&valueSize
|
||
);
|
||
|
||
if (status != ERROR_SUCCESS) {
|
||
ClNetPrint(LOG_CRITICAL,
|
||
"[NM] Query of address value failed for network %1!ws!, status %2!u!.\n",
|
||
NetworkId,
|
||
status
|
||
);
|
||
goto error_exit;
|
||
}
|
||
|
||
//
|
||
// Read the address mask.
|
||
//
|
||
valueLength = 0;
|
||
|
||
status = NmpQueryString(
|
||
networkKey,
|
||
CLUSREG_NAME_NET_ADDRESS_MASK,
|
||
REG_SZ,
|
||
&(NetworkInfo->AddressMask),
|
||
&valueLength,
|
||
&valueSize
|
||
);
|
||
|
||
if (status != ERROR_SUCCESS) {
|
||
ClNetPrint(LOG_CRITICAL,
|
||
"[NM] Query of address mask value failed for network %1!ws!, status %2!u!.\n",
|
||
NetworkId,
|
||
status
|
||
);
|
||
goto error_exit;
|
||
}
|
||
|
||
//
|
||
// Read the transport name.
|
||
//
|
||
valueLength = 0;
|
||
|
||
status = NmpQueryString(
|
||
networkKey,
|
||
CLUSREG_NAME_NET_TRANSPORT,
|
||
REG_SZ,
|
||
&(NetworkInfo->Transport),
|
||
&valueLength,
|
||
&valueSize
|
||
);
|
||
|
||
if (status != ERROR_SUCCESS) {
|
||
ClNetPrint(LOG_CRITICAL,
|
||
"[NM] Query of transport value failed for network %1!ws!, status %2!u!.\n",
|
||
NetworkId,
|
||
status
|
||
);
|
||
goto error_exit;
|
||
}
|
||
|
||
error_exit:
|
||
|
||
if (status != ERROR_SUCCESS) {
|
||
ClNetFreeNetworkInfo(NetworkInfo);
|
||
}
|
||
|
||
if (networkKey != NULL) {
|
||
DmCloseKey(networkKey);
|
||
}
|
||
|
||
return(status);
|
||
|
||
} // NmpGetNetworkDefinition
|
||
|
||
DWORD
|
||
NmpEnumNetworkDefinitions(
|
||
OUT PNM_NETWORK_ENUM * NetworkEnum
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Reads information about defined cluster networks from the cluster
|
||
database. and builds an enumeration structure to hold the information.
|
||
|
||
Arguments:
|
||
|
||
NetworkEnum - A pointer to the variable into which to place a pointer to
|
||
the allocated network enumeration.
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if the routine succeeds.
|
||
A Win32 error code otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD status;
|
||
PNM_NETWORK_ENUM networkEnum = NULL;
|
||
PNM_NETWORK_INFO networkInfo;
|
||
WCHAR networkId[CS_NETWORK_ID_LENGTH + 1];
|
||
DWORD i;
|
||
DWORD valueLength;
|
||
DWORD numNetworks;
|
||
DWORD ignored;
|
||
FILETIME fileTime;
|
||
|
||
|
||
*NetworkEnum = NULL;
|
||
|
||
//
|
||
// First count the number of networks.
|
||
//
|
||
status = DmQueryInfoKey(
|
||
DmNetworksKey,
|
||
&numNetworks,
|
||
&ignored, // MaxSubKeyLen
|
||
&ignored, // Values
|
||
&ignored, // MaxValueNameLen
|
||
&ignored, // MaxValueLen
|
||
&ignored, // lpcbSecurityDescriptor
|
||
&fileTime
|
||
);
|
||
|
||
if (status != ERROR_SUCCESS) {
|
||
ClNetPrint(LOG_CRITICAL,
|
||
"[NM] Failed to query Networks key information, status %1!u!\n",
|
||
status
|
||
);
|
||
return(status);
|
||
}
|
||
|
||
if (numNetworks == 0) {
|
||
valueLength = sizeof(NM_NETWORK_ENUM);
|
||
|
||
}
|
||
else {
|
||
valueLength = sizeof(NM_NETWORK_ENUM) +
|
||
(sizeof(NM_NETWORK_INFO) * (numNetworks-1));
|
||
}
|
||
|
||
valueLength = sizeof(NM_NETWORK_ENUM) +
|
||
(sizeof(NM_NETWORK_INFO) * (numNetworks-1));
|
||
|
||
networkEnum = MIDL_user_allocate(valueLength);
|
||
|
||
if (networkEnum == NULL) {
|
||
ClNetPrint(LOG_CRITICAL, "[NM] Failed to allocate memory.\n");
|
||
return(ERROR_NOT_ENOUGH_MEMORY);
|
||
}
|
||
|
||
ZeroMemory(networkEnum, valueLength);
|
||
|
||
for (i=0; i < numNetworks; i++) {
|
||
networkInfo = &(networkEnum->NetworkList[i]);
|
||
|
||
valueLength = sizeof(networkId);
|
||
|
||
status = DmEnumKey(
|
||
DmNetworksKey,
|
||
i,
|
||
&(networkId[0]),
|
||
&valueLength,
|
||
NULL
|
||
);
|
||
|
||
if (status != ERROR_SUCCESS) {
|
||
ClNetPrint(LOG_CRITICAL,
|
||
"[NM] Failed to enumerate network key, status %1!u!\n",
|
||
status
|
||
);
|
||
goto error_exit;
|
||
}
|
||
|
||
status = NmpGetNetworkDefinition(networkId, networkInfo);
|
||
|
||
if (status != ERROR_SUCCESS) {
|
||
goto error_exit;
|
||
}
|
||
|
||
networkEnum->NetworkCount++;
|
||
}
|
||
|
||
*NetworkEnum = networkEnum;
|
||
|
||
return(ERROR_SUCCESS);
|
||
|
||
|
||
error_exit:
|
||
|
||
if (networkEnum != NULL) {
|
||
ClNetFreeNetworkEnum(networkEnum);
|
||
}
|
||
|
||
return(status);
|
||
}
|
||
|
||
DWORD
|
||
ReadRegData(
|
||
IN PCLNET_CONFIG_LISTS Lists
|
||
)
|
||
|
||
/*++
|
||
|
||
Read the cluster registry data and bulid up an input list
|
||
similar to what happens in the cluster service.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD status;
|
||
PNM_NETWORK_ENUM * networkEnum;
|
||
PNM_INTERFACE_ENUM * interfaceEnum;
|
||
LPWSTR localNodeId;
|
||
|
||
status = DmpOpenKeys(MAXIMUM_ALLOWED);
|
||
if (status != ERROR_SUCCESS) {
|
||
CL_UNEXPECTED_ERROR( status );
|
||
return(status);
|
||
}
|
||
|
||
status = ClNetConvertEnumsToConfigList(networkEnum,
|
||
interfaceEnum,
|
||
localNodeId,
|
||
&Lists->InputConfigList);
|
||
|
||
return status;
|
||
}
|
||
#endif
|
||
|
||
int _cdecl
|
||
main(
|
||
int argc,
|
||
char** argv
|
||
)
|
||
{
|
||
DWORD status;
|
||
DWORD i;
|
||
WSADATA wsaData;
|
||
WORD versionRequested;
|
||
int err;
|
||
SOCKET s;
|
||
DWORD bytesReturned;
|
||
DWORD matchedNetworkCount;
|
||
DWORD newNetworkCount;
|
||
|
||
|
||
ClNetInitialize(
|
||
ClNetPrint,
|
||
ClNetLogEvent,
|
||
ClNetLogEvent1,
|
||
ClNetLogEvent2,
|
||
ClNetLogEvent3
|
||
);
|
||
|
||
ClNetInitializeConfigLists(&ConfigLists);
|
||
|
||
// ReadRegData( &ConfigLists );
|
||
|
||
versionRequested = MAKEWORD(2,0);
|
||
|
||
err = WSAStartup(versionRequested, &wsaData);
|
||
|
||
if (err != 0) {
|
||
status = WSAGetLastError();
|
||
printf("wsastartup failed, %u\n", status);
|
||
return(1);
|
||
}
|
||
|
||
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||
|
||
if (s == INVALID_SOCKET) {
|
||
status = WSAGetLastError();
|
||
printf("socket failed, %u\n", status);
|
||
return(1);
|
||
}
|
||
|
||
//
|
||
// Init COM
|
||
//
|
||
|
||
status = CoInitializeEx( NULL, COINIT_DISABLE_OLE1DDE | COINIT_MULTITHREADED );
|
||
if ( !SUCCEEDED( status )) {
|
||
printf("Couldn't init COM %08X\n", status );
|
||
return 1;
|
||
}
|
||
|
||
for (i=0; ; i++) {
|
||
printf("\nIteration #%u\n\n", i);
|
||
|
||
status = ClNetConfigureNetworks(
|
||
NodeId,
|
||
NodeName,
|
||
L"4303",
|
||
TRUE,
|
||
&ConfigLists,
|
||
&matchedNetworkCount,
|
||
&newNetworkCount
|
||
);
|
||
|
||
if (status != ERROR_SUCCESS) {
|
||
printf("Config failed, status %u\n", status);
|
||
return(1);
|
||
}
|
||
|
||
printf("Config succeeded - matched Networks = %u, new Networks = %u\n\n",
|
||
matchedNetworkCount, newNetworkCount);
|
||
|
||
PrintResults();
|
||
|
||
ClNetFreeConfigList(&ConfigLists.RenamedInterfaceList);
|
||
ClNetFreeConfigList(&ConfigLists.DeletedInterfaceList);
|
||
|
||
ConsolidateLists(
|
||
&ConfigLists.InputConfigList,
|
||
&ConfigLists.UpdatedInterfaceList
|
||
);
|
||
ConsolidateLists(
|
||
&ConfigLists.InputConfigList,
|
||
&ConfigLists.CreatedInterfaceList
|
||
);
|
||
ConsolidateLists(
|
||
&ConfigLists.InputConfigList,
|
||
&ConfigLists.CreatedNetworkList
|
||
);
|
||
|
||
printf("Waiting for PnP event\n");
|
||
|
||
err = WSAIoctl(
|
||
s,
|
||
SIO_ADDRESS_LIST_CHANGE,
|
||
NULL,
|
||
0,
|
||
NULL,
|
||
0,
|
||
&bytesReturned,
|
||
NULL,
|
||
NULL
|
||
);
|
||
|
||
|
||
if (err != 0) {
|
||
status = WSAGetLastError();
|
||
printf("wsastartup failed, %u\n", status);
|
||
return(1);
|
||
}
|
||
|
||
printf("PnP notification received\n");
|
||
}
|
||
|
||
CoUninitialize();
|
||
return(0);
|
||
}
|
||
|
||
|
||
|