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.
1052 lines
25 KiB
1052 lines
25 KiB
#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);
|
|
}
|
|
|
|
|
|
|