windows-nt/Source/XPSP1/NT/base/fs/dfs/ui/dfscmd/myutil.cxx
2020-09-26 16:20:57 +08:00

732 lines
17 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1994.
//
// File: myutil.cxx
//
// Contents: Helper APIs for Sharing Tool
//
// History: 6-Jun-93 WilliamW Created
//
//----------------------------------------------------------------------------
#include "headers.hxx"
#pragma hdrstop
////////////////////////////////////////////////////////////////////////////
//+-------------------------------------------------------------------------
//
// Member: MyGetLastComponent, public
//
// Synopsis: Parse a string to a (prefix, last-component) pair. Any
// trailing text after L'.' will be ignored
//
// History: 07-May-93 WilliamW Created
//
// Notes: pszPrefix and pszLastComponent should be pre-allocated
//
//--------------------------------------------------------------------------
VOID
MyGetLastComponent(
IN PWSTR pszStr,
OUT PWSTR pszPrefix,
OUT PWSTR pszLastComponent
)
{
PWSTR pszTmp = NULL;
PWSTR pszTmpLast = NULL;
//
// Manufacture the prefix part by replacing L'\\' with L'\0'
//
wcscpy(pszPrefix, pszStr);
pszTmp = wcsrchr(pszPrefix, L'\\');
if (pszTmp != NULL)
{
*pszTmp = L'\0';
//
// Extract the last component. The L'.' part will be replaced
// by a L'\0'
//
pszTmpLast = pszTmp + 1;
pszTmp = wcsrchr(pszTmpLast, L'.');
if (pszTmp != NULL)
{
//
// Replace with a L'\0' character
//
*pszTmp = L'\0';
}
wcscpy(pszLastComponent, pszTmpLast);
}
else
{
*pszPrefix = L'\0';
wcscpy(pszLastComponent, pszStr);
}
}
//+-------------------------------------------------------------------------
//
// Member: MyFindLastComponent, public
//
// Synopsis: Parse a string to find the last component. This is different
// from MyGetLastComponent as it doesn't copy any data, but just
// looks for the last backslash and points one after it.
//
// History: 21-Nov-94 BruceFo
//
//--------------------------------------------------------------------------
PWSTR
MyFindLastComponent(
IN const WCHAR* pszStr
)
{
PWSTR pszTmp = wcsrchr(pszStr, L'\\');
if (pszTmp != NULL)
{
return pszTmp + 1;
}
else
{
return (PWSTR)pszStr; // cast away const
}
}
//+-------------------------------------------------------------------------
//
// Member: MyGetNextComponent(), public
//
// Synopsis: Parse a string to a (next-components, remaing-components)
// pair. Any
//
// History: 07-May-93 WilliamW Created
//
// Notes: pszNextComponent and pszRemaining should be pre-allocated.
//
//--------------------------------------------------------------------------
VOID
MyGetNextComponent(
IN PWSTR pszStr,
OUT PWSTR pszNextComponent,
OUT PWSTR pszRemaining
)
{
PWSTR pszTmp = NULL;
if (*pszStr == L'\0')
{
*pszNextComponent = *pszRemaining = L'\0';
return;
}
#if DBG == 1
if (*pszStr == L'\\')
{
appDebugOut((DEB_IERROR,
"WARNING: MyGetNextComponent takes a relative path as its first argument\n"));
}
#endif // DBG == 1
//
// Manufacture the next component part by replacing L'\\' with L'\0'
//
pszTmp = wcschr(pszStr, L'\\');
if (pszTmp != NULL)
{
ULONG cchNextComponent = (ULONG)(pszTmp - pszStr);
wcsncpy(pszNextComponent, pszStr, cchNextComponent);
pszNextComponent[cchNextComponent] = L'\0';
//
// Handle the remaining component.
//
wcscpy(pszRemaining, pszTmp + 1);
}
else
{
//
// No remaining part, this is the last component
//
*pszRemaining = L'\0';
wcscpy(pszNextComponent, pszStr);
}
}
//+-------------------------------------------------------------------------
//
// Method: MyStrStr
//
// Synopsis: A case insensitive version of wcsstr (i.e. strstr)
//
//--------------------------------------------------------------------------
PWSTR
MyStrStr(
IN PWSTR pszInStr,
IN PWSTR pszInSubStr
)
{
if ( pszInStr == NULL
|| pszInSubStr == NULL
|| *pszInStr == L'\0'
|| *pszInSubStr == L'\0')
{
return NULL;
}
INT iSubStrLen = wcslen(pszInSubStr);
INT iStrLen = wcslen(pszInStr);
PWSTR pszHeadInStr = pszInStr;
PWSTR pszTailInStr = pszInStr + iSubStrLen;
PWSTR pszEndInStr = pszInStr + iStrLen;
while (pszTailInStr <= pszEndInStr)
{
if (0 != _wcsnicmp(pszHeadInStr, pszInSubStr, iSubStrLen))
{
return pszHeadInStr;
}
pszHeadInStr++;
pszTailInStr++;
}
return NULL;
}
//+-------------------------------------------------------------------------
//
// Method: MyFindPostfix
//
// Synopsis: Match the prefix with the string. If the string doesn't have
// the prefix, return a pointer to the string itself. If it does,
// then check to see if the character after the prefix is a
// backslash. If it is, return a pointer to the character
// following the backslash. Otherwise, return a pointer to the
// character immediately after the prefix.
//
// Examples:
// string prefix return
// \foo\bar\baz \bad \foo\bar\baz
// \foo\bar\baz \foo\bar baz
// \foo\bar\baz \f oo\bar\baz
//
//--------------------------------------------------------------------------
PWSTR
MyFindPostfix(
IN PWSTR pszString,
IN PWSTR pszPrefix
)
{
UINT cchPrefixLen = wcslen(pszPrefix);
if (0 == _wcsnicmp(pszString, pszPrefix, cchPrefixLen))
{
PWSTR pszReturn = pszString + cchPrefixLen;
if (*pszReturn == L'\\')
{
//
// skip past the leading backslash.
//
++pszReturn;
}
return pszReturn;
}
else
{
// prefix didn't match, return argument string
// appDebugOut((DEB_ITRACE,
// "No postfix of ('%ws', '%ws')\n",
// pszString,
// pszPrefix));
return pszString;
}
}
//+-------------------------------------------------------------------------
//
// Function: MyFormatMessageText
//
// Synopsis: Given a resource IDs, load strings from given instance
// and format the string into a buffer
//
// History: 11-Aug-93 WilliamW Created.
//
//--------------------------------------------------------------------------
VOID
MyFormatMessageText(
IN HRESULT dwMsgId,
IN PWSTR pszBuffer,
IN DWORD dwBufferSize,
IN va_list * parglist
)
{
//
// get message from system or app msg file.
//
DWORD dwReturn = FormatMessage(
(dwMsgId >= MSG_FIRST_MESSAGE)
? FORMAT_MESSAGE_FROM_HMODULE
: FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dwMsgId,
LANG_USER_DEFAULT,
pszBuffer,
dwBufferSize,
parglist);
if (0 == dwReturn) // couldn't find message
{
appDebugOut((DEB_IERROR,
"Formatmessage failed = 0x%08lx\n",
GetLastError()));
WCHAR szText[200];
LoadString(g_hInstance,
(dwMsgId >= MSG_FIRST_MESSAGE)
? IDS_APP_MSG_NOT_FOUND
: IDS_SYS_MSG_NOT_FOUND,
szText,
ARRAYLEN(szText));
wsprintf(pszBuffer,szText,dwMsgId);
}
}
//+-------------------------------------------------------------------------
//
// Function: MyFormatMessage
//
// Synopsis: Given a resource IDs, load strings from given instance
// and format the string into a buffer
//
// History: 11-Aug-93 WilliamW Created.
//
//--------------------------------------------------------------------------
VOID
MyFormatMessage(
IN HRESULT dwMsgId,
IN PWSTR pszBuffer,
IN DWORD dwBufferSize,
...
)
{
va_list arglist;
va_start(arglist, dwBufferSize);
MyFormatMessageText(dwMsgId, pszBuffer, dwBufferSize, &arglist);
va_end(arglist);
}
//+---------------------------------------------------------------------------
//
// Function: NewDup
//
// Synopsis: Duplicate a string using '::new'
//
// Arguments:
//
// Returns:
//
// History: 28-Dec-94 BruceFo Created
//
//----------------------------------------------------------------------------
PWSTR
NewDup(
IN const WCHAR* psz
)
{
if (NULL == psz)
{
return NULL;
}
PWSTR pszRet = new WCHAR[wcslen(psz) + 1];
if (NULL == pszRet)
{
appDebugOut((DEB_ERROR,"OUT OF MEMORY\n"));
return NULL;
}
wcscpy(pszRet, psz);
return pszRet;
}
//+---------------------------------------------------------------------------
//
// Function: wcsistr
//
// Synopsis: Same as wcsstr (find string in string), but case-insensitive
//
// Arguments:
//
// Returns:
//
// History: 2-Feb-95 BruceFo Created
//
//----------------------------------------------------------------------------
wchar_t*
wcsistr(
const wchar_t* string1,
const wchar_t* string2
)
{
if ((NULL == string2) || (NULL == string1))
{
// do whatever wcsstr would do
return wcsstr(string1, string2);
}
wchar_t* s1dup = NewDup(string1);
wchar_t* s2dup = NewDup(string2);
wchar_t* ret = NULL;
if (NULL != s1dup && NULL != s2dup)
{
_wcslwr(s1dup); // lower case everything to make case-insensitive
_wcslwr(s2dup);
ret = wcsstr(s1dup, s2dup);
}
delete[] s1dup;
delete[] s2dup;
return ret;
}
//+---------------------------------------------------------------------------
//
// Function: GetResourceString
//
// Synopsis: Load a resource string, are return a "new"ed copy
//
// Arguments: [dwId] -- a resource string ID
//
// Returns: new memory copy of a string
//
// History: 5-Apr-95 BruceFo Created
//
//----------------------------------------------------------------------------
PWSTR
GetResourceString(
IN DWORD dwId
)
{
WCHAR sz[50];
if (0 == LoadString(g_hInstance, dwId, sz, ARRAYLEN(sz)))
{
return NULL;
}
else
{
return NewDup(sz);
}
}
//+-------------------------------------------------------------------------
//
// Function: IsDfsRoot
//
// Synopsis: Determine if the path passed in is a Dfs root, in form only.
// Namely, does it look like "\\machine-or-domain\share"?
//
// Arguments: none
//
// Returns: nothing
//
// History: 18-Apr-96 BruceFo Created
//
//--------------------------------------------------------------------------
BOOL
IsDfsRoot(
IN LPWSTR pszRoot
)
{
if (NULL != pszRoot
&& pszRoot[0] == L'\\'
&& pszRoot[1] == L'\\'
&& pszRoot[2] != L'\\' // might be null
)
{
LPWSTR pszTmp = wcschr(pszRoot + 2, L'\\');
if (pszTmp != NULL)
{
if (pszTmp[1] != L'\0'
&& pszTmp[1] != L'\\'
)
{
// ok, we've got "\\xxx\y...."
// Now make sure it doesn't have a fourth backslash
pszTmp = wcschr(pszTmp + 2, L'\\');
if (pszTmp == NULL)
{
return TRUE;
}
}
}
}
return FALSE;
}
//+-------------------------------------------------------------------------
//
// Function: IsDfsShare
//
// Synopsis: Determine if the given share on the given server is a Dfs
// share. This actually contacts the machine.
//
// Arguments: none
//
// Returns: nothing
//
// History: 18-Apr-96 BruceFo Created
//
//--------------------------------------------------------------------------
DWORD
IsDfsShare(
IN LPWSTR pszServer,
IN LPWSTR pszShare,
OUT BOOL* pfIsDfs
)
{
PSHARE_INFO_1005 pshi1005;
NET_API_STATUS ret = NetShareGetInfo(pszServer, pszShare, 1005, (LPBYTE*)&pshi1005);
if (NERR_Success == ret)
{
if (pshi1005->shi1005_flags & SHI1005_FLAGS_DFS)
{
*pfIsDfs = TRUE;
}
else
{
appDebugOut((DEB_ITRACE,
"%ws not a Dfs share\n",
pszShare));
}
NetApiBufferFree(pshi1005);
}
else
{
// This could be an access denied.
appDebugOut((DEB_ERROR,
"NetShareGetInfo(NULL, %ws...) failed, 0x%08lx\n",
pszShare,
ret));
}
return ret;
}
//+-------------------------------------------------------------------------
//
// Member: FindDfsRoot, public
//
// Synopsis: Parse a string to find the Dfs root. Returns a pointer to
//
// History: 22-Apr-96 BruceFo
//
//--------------------------------------------------------------------------
BOOL
FindDfsRoot(
IN PWSTR pszDfsPath,
OUT PWSTR pszDfsRoot
)
{
PWSTR pszTmp;
if (NULL != pszDfsPath
&& pszDfsPath[0] == L'\\'
&& pszDfsPath[1] == L'\\'
&& pszDfsPath[2] != L'\\'
&& pszDfsPath[2] != L'\0'
&& (NULL != (pszTmp = wcschr(pszDfsPath + 3, L'\\')))
&& pszTmp[1] != L'\\'
&& pszTmp[1] != L'\0'
)
{
pszTmp = wcschr(pszTmp + 2, L'\\');
if (NULL != pszTmp)
{
// the thing passed in was of the form "\\xxx\yyy\..."
int len = (int)(pszTmp - pszDfsPath);
wcsncpy(pszDfsRoot, pszDfsPath, len);
pszDfsRoot[len] = L'\0';
}
else
{
// the thing passed in was of the form "\\xxx\yyy"
wcscpy(pszDfsRoot, pszDfsPath);
}
appDebugOut((DEB_IERROR,
"Dfs root of %ws is %ws\n",
pszDfsPath, pszDfsRoot));
return TRUE;
}
else
{
return FALSE;
}
}
#define MAX_MESSAGE_BUF 8192
#define MAX_ANSI_MESSAGE_BUF (MAX_MESSAGE_BUF * 3)
WCHAR szMsgBuf[MAX_MESSAGE_BUF];
CHAR szAnsiBuf[MAX_ANSI_MESSAGE_BUF];
VOID
StatusMessage(
IN HRESULT hr,
...
)
{
va_list arglist;
va_start(arglist, hr);
ULONG written;
MyFormatMessageText(hr, szMsgBuf, ARRAYLEN(szMsgBuf), &arglist);
written = WideCharToMultiByte(CP_OEMCP, 0,
szMsgBuf, wcslen(szMsgBuf),
szAnsiBuf, MAX_ANSI_MESSAGE_BUF,
NULL, NULL);
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), szAnsiBuf, written, &written, NULL);
va_end(arglist);
}
VOID
ErrorMessage(
IN HRESULT hr,
...
)
{
va_list arglist;
va_start(arglist, hr);
ULONG written;
MyFormatMessageText(hr, szMsgBuf, ARRAYLEN(szMsgBuf), &arglist);
written = WideCharToMultiByte(CP_OEMCP, 0,
szMsgBuf, wcslen(szMsgBuf),
szAnsiBuf, MAX_ANSI_MESSAGE_BUF,
NULL, NULL);
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), szAnsiBuf, written, &written, NULL);
va_end(arglist);
exit(1);
}
VOID
DfsErrorMessage(
IN NET_API_STATUS status
)
{
ULONG written;
MyFormatMessage(MSG_ERROR, szMsgBuf, ARRAYLEN(szMsgBuf), status);
written = WideCharToMultiByte(CP_OEMCP, 0,
szMsgBuf, wcslen(szMsgBuf),
szAnsiBuf, MAX_ANSI_MESSAGE_BUF,
NULL, NULL);
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), szAnsiBuf, written, &written, NULL);
PWSTR pszDll = L"netmsg.dll";
HINSTANCE hinst = LoadLibrary(pszDll);
if (NULL == hinst)
{
MyFormatMessage(MSG_NO_MESSAGES, szMsgBuf, ARRAYLEN(szMsgBuf), pszDll);
}
else
{
DWORD dwReturn = FormatMessage(
FORMAT_MESSAGE_FROM_HMODULE
| FORMAT_MESSAGE_IGNORE_INSERTS,
hinst,
status,
LANG_USER_DEFAULT,
szMsgBuf,
ARRAYLEN(szMsgBuf),
NULL);
FreeLibrary(hinst);
if (0 == dwReturn) // couldn't find message
{
// try system messages
dwReturn = FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
status,
LANG_USER_DEFAULT,
szMsgBuf,
ARRAYLEN(szMsgBuf),
NULL);
if (0 == dwReturn) // couldn't find message
{
MyFormatMessage(MSG_ERROR_UNKNOWN, szMsgBuf, ARRAYLEN(szMsgBuf));
}
}
}
written = WideCharToMultiByte(CP_OEMCP, 0,
szMsgBuf, wcslen(szMsgBuf),
szAnsiBuf, MAX_ANSI_MESSAGE_BUF,
NULL, NULL);
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), szAnsiBuf, written, &written, NULL);
exit(1);
}
VOID
Usage(
VOID
)
{
ErrorMessage(MSG_USAGE);
}