//-------------------------------------------------------------------------- // // Copyright (C) 1999, Microsoft Corporation // // File: misc.cxx // //-------------------------------------------------------------------------- #define UNICODE 1 extern "C" { #include #include #include #include #include #include #include #include #include #include #include #include #include #include } #include #include "struct.hxx" #include "flush.hxx" #include "misc.hxx" #include "messages.h" #include #include #include "dfspathname.hxx" #include "resapi.h" #define MAX_BUF_SIZE 10000 WCHAR MsgBuf[MAX_BUF_SIZE]; CHAR AnsiBuf[MAX_BUF_SIZE*3]; WCHAR wszRootShare[MAX_PATH+1] = { 0 }; #define WINLOGON_FOLDER L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon" #define SFCVALUE L"SFCDisable" #define ARRAYLEN(x) (sizeof(x) / sizeof((x)[0])) DWORD DfspGetLinkName( LPWSTR pwszDfsRoot, LPWSTR *ppwszLinkName); DWORD AtoHex( LPWSTR pwszHexValue, PDWORD pdwErr) { DWORD dwHexValue = 0; DWORD DiscardResult; // if (fSwDebug == TRUE) // MyPrintf(L"AtoHex(%ws)\r\n", pwszHexValue); if (pwszHexValue == NULL) { *pdwErr = ERROR_INVALID_PARAMETER; goto AllDone; } if (pwszHexValue[0] == L'0' && (pwszHexValue[1] == L'x' || pwszHexValue[1] == L'X')) pwszHexValue = &pwszHexValue[2]; DiscardResult = swscanf(pwszHexValue, L"%x", &dwHexValue); AllDone: // if (fSwDebug == TRUE) // MyPrintf(L"AtoHex returning 0x%x (dwErr=0x%x)\r\n", dwHexValue, *pdwErr); return dwHexValue; } DWORD AtoDec( LPWSTR pwszDecValue, PDWORD pdwErr) { DWORD dwDecValue = 0; DWORD DiscardResult; // if (fSwDebug == TRUE) // MyPrintf(L"AtoDec(%ws)\r\n", pwszDecValue); if (pwszDecValue == NULL) { *pdwErr = ERROR_INVALID_PARAMETER; goto AllDone; } DiscardResult = swscanf(pwszDecValue, L"%d", &dwDecValue); AllDone: // if (fSwDebug == TRUE) // MyPrintf(L"AtoDec returning 0x%x (dwErr=0x%x)\r\n", dwDecValue, *pdwErr); return dwDecValue; } DFSSTATUS IsClusterNode( LPWSTR pNodeName, PBOOLEAN pIsCluster ) { DFSSTATUS Status = ERROR_SUCCESS; DWORD ClusterState; *pIsCluster = FALSE; Status = GetNodeClusterState( pNodeName, &ClusterState ); if (Status == ERROR_SUCCESS) { if ( (ClusterStateRunning == ClusterState) || (ClusterStateNotRunning == ClusterState) ) { *pIsCluster = TRUE; } } return Status; } #if 0 // We might enable this code in a more cluster friendly // dfsutil version. // typedef struct _DFSUTIL_CLUSTER_CONTEXT { PUNICODE_STRING pShareName; BOOLEAN bIsClustered; } DFSUTIL_CLUSTER_CONTEXT; DWORD DfsUtilClusterCallBackFunction( HRESOURCE hSelf, HRESOURCE hResource, PVOID Context) { UNREFERENCED_PARAMETER( hSelf ); HKEY HKey = NULL; HKEY HParamKey = NULL; DFSUTIL_CLUSTER_CONTEXT *pContext = (DFSUTIL_CLUSTER_CONTEXT *)Context; DWORD Status = ERROR_SUCCESS; DWORD Value = 0; pContext->bIsClustered = FALSE; HKey = GetClusterResourceKey(hResource, KEY_READ); if (HKey != NULL) { Status = ClusterRegOpenKey( HKey, L"Parameters", KEY_READ, &HParamKey ); ClusterRegCloseKey( HKey ); if (ERROR_SUCCESS == Status) { LPWSTR ResShareName = NULL; UNICODE_STRING VsName; ResShareName = ResUtilGetSzValue( HParamKey, L"ShareName" ); Status = DfsRtlInitUnicodeStringEx(&VsName, ResShareName); if(Status == ERROR_SUCCESS) { if (pContext->pShareName->Length == VsName.Length) { Status = ResUtilGetDwordValue(HParamKey, L"IsDfsRoot", &Value, 0); if ((ERROR_SUCCESS == Status) && (Value == 1)) { if (_wcsnicmp(pContext->pShareName->Buffer, VsName.Buffer, VsName.Length) == 0) { pContext->bIsClustered = TRUE; } } } } ClusterRegCloseKey( HParamKey ); } } return Status; } DWORD IsClusterRoot( LPWSTR pNodeName, PUNICODE_STRING pShareName, PBOOLEAN pIsClustered ) { DWORD Status; DFSUTIL_CLUSTER_CONTEXT Context; UNREFERENCED_PARAMETER(pNodeName); Context.pShareName = pShareName; Context.bIsClustered = FALSE; Status = ResUtilEnumResources(NULL, L"File Share", DfsUtilClusterCallBackFunction, (PVOID)&Context ); if (Status == ERROR_SUCCESS) { *pIsClustered = Context.bIsClustered; } return Status; } #endif DWORD CmdAddRoot( BOOLEAN DomainDfs, LPWSTR pwszServerName, LPWSTR pwszShareName, LPWSTR pwszRootName, LPWSTR pwszComment) { DWORD dwErr = ERROR_SUCCESS; BOOLEAN bIsClustered = FALSE; DebugInformation((L"CmdAddRoot (%ws,%ws)\r\n", pwszServerName, pwszShareName)); if (DomainDfs == FALSE) { // see if the server is a clustered node. dwErr = IsClusterNode( pwszServerName, &bIsClustered ); if (dwErr == ERROR_SUCCESS && bIsClustered) { DebugInformation((L"Node %ws is in a cluster\r\n", pwszServerName)); } if (!bIsClustered) { DebugInformation((L"<%ws, %ws> is not clustered. Calling NetDfsAddStdRoot\r\n", pwszServerName, pwszShareName)); dwErr = NetDfsAddStdRoot( pwszServerName, pwszShareName, pwszComment, 0);; } else { MyPrintf(L"Node %ws belongs to a cluster environment. This command is not supported.\r\n", pwszServerName); dwErr = ERROR_NOT_SUPPORTED; } } else { dwErr = NetDfsAddFtRoot( pwszServerName, pwszShareName, pwszRootName, pwszComment, 0); } DebugInformation((L"CmdAddRoot returning %d\r\n", dwErr)); if (dwErr == ERROR_SUCCESS) CommandSucceeded = TRUE; return dwErr; } DWORD CmdRemRoot( BOOLEAN DomDfs, LPWSTR pwszServerName, LPWSTR pwszShareName, LPWSTR pwszRootName) { DWORD dwErr = ERROR_SUCCESS; BOOLEAN bIsClustered = FALSE; DebugInformation((L"CmdRemRoot: Server %ws, Physical Share %ws, Logical Share %ws)\r\n", pwszServerName, pwszShareName, pwszRootName)); if (DomDfs == FALSE) { // see if the server is a clustered node. dwErr = IsClusterNode( pwszServerName, &bIsClustered ); if (dwErr == ERROR_SUCCESS && bIsClustered) { DebugInformation((L"Node %ws is in a cluster.\r\n", pwszServerName)); } if (!bIsClustered) { DebugInformation((L"<%ws, %ws> is not clustered. Calling NetDfsRemoveStdRoot\r\n", pwszServerName, pwszShareName)); dwErr = NetDfsRemoveStdRoot( pwszServerName, pwszShareName, 0); } else { MyPrintf(L"Node %ws belongs to a cluster environment. This command is not supported.\r\n",pwszServerName); dwErr = ERROR_NOT_SUPPORTED; } } else { dwErr = NetDfsRemoveFtRoot( pwszServerName, pwszShareName, pwszRootName, 0); } DebugInformation((L"CmdRemRoot returning %d\r\n", dwErr)); if (dwErr == ERROR_SUCCESS) CommandSucceeded = TRUE; return dwErr; } VOID MyFormatMessageText( HRESULT dwMsgId, PWSTR pszBuffer, DWORD dwBufferSize, va_list *parglist) { DWORD dwReturn = FormatMessage( (dwMsgId >= MSG_FIRST_MESSAGE) ? FORMAT_MESSAGE_FROM_HMODULE : FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwMsgId, LANG_USER_DEFAULT, pszBuffer, dwBufferSize, parglist); if (dwReturn == 0 && fSwDebug) MyPrintf(L"Formatmessage failed 0x%x\r\n", GetLastError()); } VOID ErrorMessage( IN HRESULT hr, ...) { ULONG cch; va_list arglist; HRESULT HResult; size_t CharacterCount; va_start(arglist, hr); MyFormatMessageText(hr, MsgBuf, ARRAYLEN(MsgBuf), &arglist); HResult = StringCchLength( MsgBuf, MAX_BUF_SIZE, &CharacterCount ); if (SUCCEEDED(HResult)) { cch = WideCharToMultiByte(CP_OEMCP, 0, MsgBuf, CharacterCount, AnsiBuf, MAX_BUF_SIZE*3, NULL, NULL); WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), AnsiBuf, cch, &cch, NULL); } va_end(arglist); } VOID DfsVPrintToFile( HANDLE FileHandle, PWCHAR format, va_list va) { ULONG cch; HRESULT HResult; size_t CharacterCount; HResult = StringCchVPrintf( MsgBuf, MAX_BUF_SIZE, format, va ); if (SUCCEEDED(HResult)) { HResult = StringCchLength( MsgBuf, MAX_BUF_SIZE, &CharacterCount ); } if (SUCCEEDED(HResult)) { cch = WideCharToMultiByte(CP_OEMCP, 0, MsgBuf, CharacterCount, AnsiBuf, MAX_BUF_SIZE*3, NULL, NULL); WriteFile(FileHandle, AnsiBuf, cch, &cch, NULL); } return; } VOID DfsVPrintWideToFile( HANDLE FileHandle, PWCHAR format, va_list va) { ULONG cch; HRESULT HResult; size_t CharacterCount; HResult = StringCchVPrintf( MsgBuf, MAX_BUF_SIZE, format, va ); if (SUCCEEDED(HResult)) { HResult = StringCchLength( MsgBuf, MAX_BUF_SIZE, &CharacterCount ); } if (SUCCEEDED(HResult)) { //cch = WideCharToMultiByte(CP_OEMCP, 0, // MsgBuf, CharacterCount, // AnsiBuf, MAX_BUF_SIZE*3, // NULL, NULL); // WriteFile(FileHandle, AnsiBuf, cch, &cch, NULL); WriteFile(FileHandle, MsgBuf, CharacterCount*sizeof(WCHAR), &cch, NULL); } return; } VOID DfsPrintToFile( HANDLE FileHandle, BOOLEAN ScriptOut, PWCHAR format, ...) { va_list va; va_start(va, format); if (ScriptOut) { DfsVPrintWideToFile( FileHandle, format, va); } else { DfsVPrintToFile( FileHandle, format, va); } va_end(va); return; } VOID MyPrintf( PWCHAR format, ...) { va_list va; va_start(va, format); DfsVPrintToFile( GetStdHandle(STD_OUTPUT_HANDLE), format, va); va_end(va); return; } VOID ShowVerboseInformation( PWCHAR format, ...) { va_list va; extern HANDLE ShowHandle; va_start(va, format); DfsVPrintToFile( ShowHandle, format, va); va_end(va); return; } VOID ShowDebugInformation( PWCHAR format, ...) { va_list va; extern HANDLE DebugHandle; va_start(va, format); DfsVPrintToFile( DebugHandle, format, va); va_end(va); return; } DFSSTATUS SetInfoReSynchronize( LPWSTR ServerName, LPWSTR ShareName) { DfsPathName RootTarget; DFS_INFO_101 Info101; DFSSTATUS Status; // // First create a UNC path name to the root target. // Status = RootTarget.SetPathName( ServerName, ShareName ); if (Status != ERROR_SUCCESS) { DebugInformation((L"DfsUtil: Error 0x%x in creating RootTarget<%wS, %wS>\n", Status, ServerName, ShareName)); ErrorMessage(Status); return Status; } DebugInformation((L"DfsUtil: ReSynchronize notification to root target %wS\n", RootTarget.GetPathString())); // // Ask the dfs service to synchronize. It is important that we don't // use direct mode operations (ie. DFS_SET_INFO macro) here. These are the root targets. // Info101.State = DFS_VOLUME_STATE_RESYNCHRONIZE; Status = NetDfsSetInfo( RootTarget.GetPathString(), NULL, NULL, 101, (LPBYTE)&Info101 ); // // It is entirely fine to get an error from W2K servers. Still, we'll defer that decision to the // to the caller and return the real error. // if (Status != ERROR_SUCCESS) { DebugInformation((L"DfsUtil: Error 0x%x hit in attempting to contact root target %wS\n", Status, RootTarget.GetPathString())); } return Status; } // // Just take out the tuple from the replicalist // in the AD directly. This doesn't involve any attempts to // contact that replica server other than a feeble attempt to // send a RESYNCHRONIZE message to it. We fully expect that // the typically scenario will be one of a dead replica server. // DWORD CmdUnmapRootReplica( LPWSTR DomainDfsPath, LPWSTR ReplicaServerName, LPWSTR ReplicaShareName ) { DfsPathName DfsPathName; DFSSTATUS Status; Status = DfsPathName.CreatePathName( DomainDfsPath ); if (Status == ERROR_SUCCESS) { PUNICODE_STRING pRemaining = DfsPathName.GetRemainingCountedString(); if (pRemaining->Length != 0) { Status = ERROR_INVALID_PARAMETER; } if (Status == ERROR_SUCCESS) { Status = NetDfsRemoveFtRootForced( DfsPathName.GetServerString(), ReplicaServerName, ReplicaShareName, DfsPathName.GetShareString(), 0 ); } } return Status; } DWORD CmdClean( LPWSTR HostServerName, LPWSTR RootShareName ) { DWORD Status; DebugInformation((L"DfsUtil: Contacting registry of %wS to remove %wS\n", HostServerName, RootShareName)); Status = DfsClean( HostServerName, RootShareName ); if (Status != ERROR_SUCCESS) { DebugInformation((L"DfsUtil: Specified registry entry was not found.\n")); } return Status; } DWORD CreateDfsFile( LPWSTR pFileString, PHANDLE pFileHandle ) { HANDLE FileHandle; DWORD Status = ERROR_SUCCESS; FileHandle = CreateFile( pFileString, GENERIC_ALL, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if (FileHandle == INVALID_HANDLE_VALUE) { Status = GetLastError(); } else { *pFileHandle = FileHandle; } return Status; }