732 lines
17 KiB
C++
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);
|
|
}
|