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.
1126 lines
28 KiB
1126 lines
28 KiB
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include "resource.h"
|
|
#include <tapi.h>
|
|
#include <objbase.h>
|
|
#include <activeds.h>
|
|
#include <lmerr.h>
|
|
|
|
#include "util.h"
|
|
#include "parser.h"
|
|
#include "mmcmgmt.h"
|
|
#include <locale.h>
|
|
#include <winnlsp.h>
|
|
|
|
const TCHAR gszUserDNFmt[] = TEXT("WinNT://%s/%s,user");
|
|
|
|
|
|
// Unicode to Unicode
|
|
void Convert (LPWSTR wszIn, LPWSTR * pwszOut)
|
|
{
|
|
if (NULL == wszIn)
|
|
{
|
|
* pwszOut = NULL;
|
|
return;
|
|
}
|
|
|
|
*pwszOut = new WCHAR [ wcslen (wszIn) + 1 ];
|
|
if (*pwszOut)
|
|
{
|
|
wcscpy (*pwszOut, wszIn);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// Ansi to Unicode
|
|
void Convert (LPSTR szIn, LPWSTR * pwszOut)
|
|
{
|
|
if (NULL == szIn)
|
|
{
|
|
* pwszOut = NULL;
|
|
return;
|
|
}
|
|
|
|
*pwszOut = new WCHAR [ strlen (szIn) + 1 ];
|
|
if (*pwszOut)
|
|
{
|
|
if (0 == MultiByteToWideChar(
|
|
CP_ACP,
|
|
0,
|
|
szIn,
|
|
-1,
|
|
*pwszOut,
|
|
strlen (szIn) + 1
|
|
)
|
|
)
|
|
{
|
|
// the conversion failed
|
|
delete [] *pwszOut;
|
|
*pwszOut = NULL;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void UnicodeToOEM (LPWSTR wszIn, LPSTR *pszOut)
|
|
{
|
|
int iSize;
|
|
|
|
if (NULL == wszIn)
|
|
{
|
|
* pszOut = NULL;
|
|
return;
|
|
}
|
|
|
|
// get the required buffer size
|
|
iSize = WideCharToMultiByte(
|
|
CP_OEMCP,
|
|
0,
|
|
wszIn,
|
|
-1,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
if (0 == iSize)
|
|
{
|
|
*pszOut = NULL;
|
|
}
|
|
else
|
|
{
|
|
*pszOut = new char [ iSize ];
|
|
if (*pszOut)
|
|
{
|
|
if ( 0 == WideCharToMultiByte(
|
|
CP_OEMCP,
|
|
0,
|
|
wszIn,
|
|
-1,
|
|
*pszOut,
|
|
iSize,
|
|
NULL,
|
|
NULL
|
|
)
|
|
)
|
|
{
|
|
// the conversion failed
|
|
delete [] *pszOut;
|
|
*pszOut = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
int MessagePrint(
|
|
LPTSTR szText,
|
|
LPTSTR szTitle
|
|
)
|
|
{
|
|
LPTSTR szOutput = NULL;
|
|
LPWSTR wszOutput = NULL;
|
|
LPSTR szOemOutput = NULL;
|
|
UINT Codepage;
|
|
char achCodepage[12] = ".OCP";
|
|
|
|
// make it one TCHAR string
|
|
szOutput = new TCHAR [ _tcslen(szText) + _tcslen(szTitle) + 3 ];
|
|
|
|
if (!szOutput)
|
|
return -1;
|
|
|
|
_stprintf ( szOutput, _T("%s\n%s\n"), szTitle, szText );
|
|
|
|
// convert the string to unicode
|
|
Convert (szOutput, &wszOutput);
|
|
delete [] szOutput;
|
|
|
|
if (!wszOutput)
|
|
return -1;
|
|
|
|
// set the locale
|
|
if (Codepage = GetConsoleOutputCP()) {
|
|
wsprintfA(achCodepage, ".%u", Codepage);
|
|
setlocale(LC_ALL, achCodepage);
|
|
}
|
|
else
|
|
{
|
|
setlocale (LC_COLLATE, achCodepage );
|
|
setlocale (LC_MONETARY, achCodepage );
|
|
setlocale (LC_NUMERIC, achCodepage );
|
|
setlocale (LC_TIME, achCodepage );
|
|
}
|
|
|
|
SetThreadUILanguage(0);
|
|
|
|
// now print
|
|
wprintf (_T("%s"), wszOutput);
|
|
delete [] wszOutput;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int MessagePrintIds (
|
|
int idsText
|
|
)
|
|
{
|
|
CIds IdsTitle (IDS_PRODUCTNAME);
|
|
CIds IdsText ( idsText );
|
|
|
|
if ( IdsTitle.StringFound () && IdsText.StringFound () )
|
|
{
|
|
return MessagePrint (
|
|
IdsText.GetString (),
|
|
IdsTitle.GetString ()
|
|
);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Report an error resource string with one %s in it
|
|
//
|
|
void ReportSz1 (
|
|
HANDLE hLogFile,
|
|
UINT idsError,
|
|
LPTSTR szParam
|
|
)
|
|
{
|
|
TCHAR szText[256];
|
|
TCHAR szBuf2[128];
|
|
CIds IdsError (idsError);
|
|
CIds IdsTitle (IDS_PRODUCTNAME);
|
|
|
|
if ( IdsError.StringFound () && IdsTitle.StringFound () )
|
|
{
|
|
_tcsncpy (szBuf2, szParam, sizeof(szBuf2) / sizeof(TCHAR));
|
|
szBuf2[sizeof(szBuf2) / sizeof(TCHAR) - 1] = 0;
|
|
wsprintf (szText, IdsError.GetString (), szBuf2);
|
|
if (hLogFile != NULL && hLogFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
char szAnsiBuf[256];
|
|
DWORD dwNumOfBytesWritten;
|
|
|
|
WideCharToMultiByte (
|
|
CP_ACP,
|
|
0,
|
|
szText,
|
|
-1,
|
|
szAnsiBuf,
|
|
sizeof(szAnsiBuf),
|
|
NULL,
|
|
NULL
|
|
);
|
|
lstrcatA (szAnsiBuf, "\n");
|
|
WriteFile (
|
|
hLogFile,
|
|
szAnsiBuf,
|
|
lstrlenA (szAnsiBuf),
|
|
&dwNumOfBytesWritten,
|
|
NULL
|
|
);
|
|
}
|
|
else
|
|
{
|
|
MessagePrint (szText, IdsTitle.GetString ());
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// IsValidDomainUser
|
|
// Check if a domain user like redmond\jonsmith specified in szDomainUser
|
|
// is valid or not. returns S_FALSE if it is invalid, S_OK for valid user.
|
|
//
|
|
// szFullName ---- To return the user's full name
|
|
// cch ---- count of characters pointed to by szFullName
|
|
//
|
|
// if szFullName is NULL or cch is zero, no full name is returned
|
|
//
|
|
|
|
HRESULT IsValidDomainUser (
|
|
LPCTSTR szDomainUser,
|
|
LPTSTR szFullName,
|
|
DWORD cch
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
TCHAR szDN[256];
|
|
TCHAR szDomain[256];
|
|
LPTSTR szSep;
|
|
LPCTSTR szUser;
|
|
DWORD dw;
|
|
|
|
IADsUser * pUser = NULL;
|
|
BSTR bstrFullName = NULL;
|
|
|
|
// Sanity check
|
|
if (szDomainUser == NULL || szDomainUser[0] == 0)
|
|
{
|
|
hr = S_FALSE;
|
|
goto ExitHere;
|
|
}
|
|
|
|
//
|
|
// Construct the user DN as <WINNT://domain/user,user>
|
|
//
|
|
szSep = _tcschr (szDomainUser, TEXT('\\'));
|
|
if (szSep == NULL)
|
|
{
|
|
// No '\' is given, assume a local user ,domain is local computer
|
|
szUser = szDomainUser;
|
|
dw = sizeof(szDomain)/sizeof(TCHAR);
|
|
if (GetComputerName (szDomain, &dw) == 0)
|
|
{
|
|
hr = HRESULT_FROM_WIN32 (GetLastError ());
|
|
goto ExitHere;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// assume invalid domain name if longer than 255
|
|
if (szSep - szDomainUser >= sizeof(szDomain)/sizeof(TCHAR))
|
|
{
|
|
hr = S_FALSE;
|
|
goto ExitHere;
|
|
}
|
|
_tcsncpy (szDomain, szDomainUser, szSep - szDomainUser);
|
|
szDomain[szSep - szDomainUser] = 0;
|
|
szUser = szSep + 1;
|
|
}
|
|
if (_tcslen (gszUserDNFmt) + _tcslen (szDomain) + _tcslen (szUser) >
|
|
sizeof(szDN) / sizeof(TCHAR))
|
|
{
|
|
hr = S_FALSE;
|
|
goto ExitHere;
|
|
}
|
|
wsprintf (szDN, gszUserDNFmt, szDomain, szUser);
|
|
|
|
//
|
|
// Try to bind to the user object
|
|
//
|
|
hr = ADsGetObject (szDN, IID_IADsUser, (void **)&pUser);
|
|
if (FAILED(hr))
|
|
{
|
|
if (hr == E_ADS_INVALID_USER_OBJECT ||
|
|
hr == E_ADS_UNKNOWN_OBJECT ||
|
|
hr == E_ADS_BAD_PATHNAME ||
|
|
HRESULT_CODE(hr) == NERR_UserNotFound)
|
|
{
|
|
hr = S_FALSE; // The user does not exist
|
|
}
|
|
goto ExitHere;
|
|
}
|
|
|
|
//
|
|
// If the user exists, get its full name
|
|
//
|
|
if (cch > 0)
|
|
{
|
|
hr = pUser->get_FullName (&bstrFullName);
|
|
szFullName[0] = 0;
|
|
if (hr == S_OK)
|
|
{
|
|
_tcsncpy (szFullName, bstrFullName, cch);
|
|
szFullName[cch - 1] = 0;
|
|
}
|
|
}
|
|
|
|
ExitHere:
|
|
if (pUser)
|
|
{
|
|
pUser->Release();
|
|
}
|
|
if (bstrFullName)
|
|
{
|
|
SysFreeString (bstrFullName);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
LPTSTR AppendStringAndFree (LPTSTR szOld, LPTSTR szToAppend)
|
|
{
|
|
LPTSTR szNew;
|
|
DWORD dwLen;
|
|
|
|
dwLen = ((szOld == NULL) ? 0 : _tcslen (szOld)) + _tcslen (szToAppend) + 1;
|
|
szNew = new TCHAR[dwLen * sizeof(TCHAR)];
|
|
if (szNew == NULL)
|
|
{
|
|
goto ExitHere;
|
|
}
|
|
|
|
if (szOld)
|
|
{
|
|
_tcscpy (szNew, szOld);
|
|
_tcscat (szNew, szToAppend);
|
|
}
|
|
else
|
|
{
|
|
_tcscpy (szNew, szToAppend);
|
|
}
|
|
|
|
ExitHere:
|
|
if (szOld)
|
|
{
|
|
delete [] szOld;
|
|
}
|
|
return szNew;
|
|
}
|
|
|
|
|
|
void
|
|
TsecCommandLine::ParseCommandLine (LPTSTR szCommand)
|
|
{
|
|
if (szCommand == NULL)
|
|
{
|
|
goto ExitHere;
|
|
}
|
|
|
|
//
|
|
// Skip the first segment which is the executable itself
|
|
//
|
|
if (*szCommand == TEXT('\"'))
|
|
{
|
|
++szCommand;
|
|
while (*szCommand &&
|
|
*szCommand != TEXT('\"'))
|
|
{
|
|
++szCommand;
|
|
}
|
|
if (*szCommand == TEXT('\"'))
|
|
{
|
|
++szCommand;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (
|
|
*szCommand &&
|
|
*szCommand != TEXT(' ') &&
|
|
*szCommand != TEXT('\t') &&
|
|
*szCommand != 0x0a &&
|
|
*szCommand != 0x0d)
|
|
{
|
|
++szCommand;
|
|
}
|
|
}
|
|
|
|
while (*szCommand)
|
|
{
|
|
//
|
|
// Search for / or - as the start of option
|
|
//
|
|
while (*szCommand &&
|
|
*szCommand != TEXT('/') &&
|
|
*szCommand != TEXT('-')
|
|
)
|
|
{
|
|
szCommand++;
|
|
}
|
|
|
|
if (*szCommand == 0)
|
|
{
|
|
break;
|
|
}
|
|
++szCommand;
|
|
|
|
//
|
|
// -h, -H, -? means help
|
|
//
|
|
if (*szCommand == TEXT('h') ||
|
|
*szCommand == TEXT('H') ||
|
|
*szCommand == TEXT('?'))
|
|
{
|
|
++szCommand;
|
|
if (*szCommand == TEXT(' ') ||
|
|
*szCommand == TEXT('\t') ||
|
|
*szCommand == 0x0a ||
|
|
*szCommand == 0x0 ||
|
|
*szCommand == 0x0d)
|
|
{
|
|
m_fShowHelp = TRUE;
|
|
}
|
|
else
|
|
{
|
|
m_fError = TRUE;
|
|
m_fShowHelp = TRUE;
|
|
}
|
|
}
|
|
//
|
|
// -v or -V followed by white space means validating only
|
|
//
|
|
else if (*szCommand == TEXT('v') ||
|
|
*szCommand == TEXT('V'))
|
|
{
|
|
++szCommand;
|
|
if (*szCommand == TEXT(' ') ||
|
|
*szCommand == TEXT('\t') ||
|
|
*szCommand == 0x0a ||
|
|
*szCommand == 0x0 ||
|
|
*szCommand == 0x0d)
|
|
{
|
|
m_fValidateOnly = TRUE;
|
|
}
|
|
else
|
|
{
|
|
m_fError = TRUE;
|
|
m_fShowHelp = TRUE;
|
|
}
|
|
}
|
|
//
|
|
// -u, -U means to validate domain user account
|
|
//
|
|
else if (*szCommand == TEXT('u') ||
|
|
*szCommand == TEXT('U'))
|
|
{
|
|
++szCommand;
|
|
if (*szCommand == TEXT(' ') ||
|
|
*szCommand == TEXT('\t') ||
|
|
*szCommand == 0x0a ||
|
|
*szCommand == 0x0 ||
|
|
*szCommand == 0x0d)
|
|
{
|
|
m_fValidateDU = TRUE;
|
|
}
|
|
else
|
|
{
|
|
m_fError = TRUE;
|
|
m_fShowHelp = TRUE;
|
|
}
|
|
}
|
|
//
|
|
// -d or -D followed by white space means dump current configuration
|
|
//
|
|
else if (*szCommand == TEXT('d') ||
|
|
*szCommand == TEXT('D'))
|
|
{
|
|
++szCommand;
|
|
if (*szCommand == TEXT(' ') ||
|
|
*szCommand == TEXT('\t') ||
|
|
*szCommand == 0x0a ||
|
|
*szCommand == 0x0 ||
|
|
*szCommand == 0x0d)
|
|
{
|
|
m_fDumpConfig = TRUE;
|
|
}
|
|
else
|
|
{
|
|
m_fError = TRUE;
|
|
m_fShowHelp = TRUE;
|
|
}
|
|
}
|
|
//
|
|
// -f is followed by a xml file name
|
|
//
|
|
else if (*szCommand == TEXT('f') ||
|
|
*szCommand == TEXT('F'))
|
|
{
|
|
++szCommand;
|
|
// skip white spaces
|
|
while (*szCommand != 0 && (
|
|
*szCommand == TEXT(' ') ||
|
|
*szCommand == TEXT('\t') ||
|
|
*szCommand == 0x0a ||
|
|
*szCommand == 0x0d))
|
|
{
|
|
++szCommand;
|
|
}
|
|
if (*szCommand == 0)
|
|
{
|
|
// no file name specified for -f, error
|
|
m_fError = TRUE;
|
|
}
|
|
else
|
|
{
|
|
LPTSTR szBeg;
|
|
int cch;
|
|
|
|
szBeg = szCommand;
|
|
cch = 0;
|
|
// A quote means file name might contain space
|
|
// search until the matchint quote of end
|
|
if (*szCommand == TEXT('\"'))
|
|
{
|
|
++szCommand;
|
|
while (*szCommand != 0 &&
|
|
*szCommand != TEXT('\"'))
|
|
{
|
|
++szCommand;
|
|
++cch;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (*szCommand != 0 &&
|
|
*szCommand != TEXT(' ') &&
|
|
*szCommand != TEXT('\t') &&
|
|
*szCommand != TEXT('\r') &&
|
|
*szCommand != TEXT('\n'))
|
|
{
|
|
++szCommand;
|
|
++cch;
|
|
}
|
|
}
|
|
if (cch == 0)
|
|
{
|
|
m_fError = TRUE;
|
|
}
|
|
else
|
|
{
|
|
m_szInFile = new TCHAR[cch+1];
|
|
if (m_szInFile != NULL)
|
|
{
|
|
memcpy (m_szInFile, szBeg, cch * sizeof(TCHAR));
|
|
m_szInFile[cch] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if(*szCommand)
|
|
{
|
|
m_fError = TRUE;
|
|
++szCommand;
|
|
}
|
|
}
|
|
|
|
ExitHere:
|
|
return;
|
|
}
|
|
|
|
int _cdecl wmain( void )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL bUninit = FALSE;
|
|
CXMLParser parser;
|
|
CXMLUser * pCurUser = NULL, *pNextUser;
|
|
CMMCManagement * pMmc = NULL;
|
|
BOOL bNoMerge, bRemove, bPID;
|
|
TCHAR szBufDU[256];
|
|
TCHAR szBufFN[256];
|
|
TCHAR szBufAddr[128];
|
|
DWORD dwPID;
|
|
HWND hwndDump = NULL;
|
|
HANDLE hLogFile = INVALID_HANDLE_VALUE;
|
|
BOOL bRecordedError = FALSE, bValidUser;
|
|
TsecCommandLine cmd (GetCommandLine ());
|
|
|
|
CXMLLine * pCurLine = NULL, * pNextLine;
|
|
|
|
//
|
|
// Create a dump window so that tlist.exe will report a title
|
|
//
|
|
if (LoadString (
|
|
GetModuleHandle(NULL),
|
|
IDS_PRODUCTNAME,
|
|
szBufFN,
|
|
sizeof(szBufFN)/sizeof(TCHAR)))
|
|
{
|
|
hwndDump = CreateWindow (
|
|
TEXT("STATIC"),
|
|
szBufFN,
|
|
0,
|
|
0, 0, 0, 0,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
//
|
|
// Check the command line options
|
|
//
|
|
if (cmd.FError () ||
|
|
cmd.FShowHelp () ||
|
|
!cmd.FDumpConfig () && !cmd.FHasFile () ||
|
|
cmd.FDumpConfig () && cmd.FHasFile () ||
|
|
( cmd.FValidateOnly () || cmd.FValidateUser () ) && !cmd.FHasFile ()
|
|
)
|
|
{
|
|
cmd.PrintUsage();
|
|
goto ExitHere;
|
|
}
|
|
|
|
hr = CoInitializeEx (
|
|
NULL,
|
|
COINIT_MULTITHREADED
|
|
);
|
|
if (FAILED (hr))
|
|
{
|
|
goto ExitHere;
|
|
}
|
|
bUninit = TRUE;
|
|
|
|
//
|
|
// Prepare the MMC component
|
|
//
|
|
pMmc = new CMMCManagement ();
|
|
if (pMmc == NULL)
|
|
{
|
|
hr = TSECERR_NOMEM;
|
|
goto ExitHere;
|
|
}
|
|
hr = pMmc->GetMMCData ();
|
|
if (FAILED(hr))
|
|
{
|
|
goto ExitHere;
|
|
}
|
|
|
|
//
|
|
// Dump the current config if this option was present
|
|
//
|
|
if ( cmd.FDumpConfig() )
|
|
{
|
|
hr = pMmc->DisplayMMCData ();
|
|
goto ExitHere;
|
|
}
|
|
|
|
//
|
|
// Set the XML file name and parse it, report error if any
|
|
//
|
|
|
|
hr = parser.SetXMLFile (cmd.GetInFileName ());
|
|
if (FAILED (hr))
|
|
{
|
|
goto ExitHere;
|
|
}
|
|
|
|
hr = parser.Parse ();
|
|
// Report parsing error if any
|
|
if (hr == TSECERR_INVALFILEFORMAT)
|
|
{
|
|
hr = parser.ReportParsingError ();
|
|
goto ExitHere;
|
|
}
|
|
if (FAILED (hr))
|
|
{
|
|
goto ExitHere;
|
|
}
|
|
|
|
//
|
|
// Create the log file for reporting errors during
|
|
// MMC processing
|
|
//
|
|
hLogFile = CreateFile (
|
|
_T("tsecimp.log"),
|
|
GENERIC_WRITE,
|
|
0,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
if (hLogFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto ExitHere;
|
|
}
|
|
|
|
//
|
|
// Loop through each user and device, based on the user's
|
|
// request, add or remove lines
|
|
//
|
|
hr = parser.GetFirstUser (&pCurUser);
|
|
if (FAILED(hr))
|
|
{
|
|
goto ExitHere;
|
|
}
|
|
while (pCurUser != NULL)
|
|
{
|
|
if (FAILED(hr = pCurUser->GetDomainUser(
|
|
szBufDU, sizeof(szBufDU)/sizeof(TCHAR))) ||
|
|
FAILED(hr = pCurUser->GetFriendlyName(
|
|
szBufFN, sizeof(szBufFN)/sizeof(TCHAR))))
|
|
{
|
|
goto ExitHere;
|
|
}
|
|
|
|
bValidUser = TRUE;
|
|
|
|
if (cmd.FValidateUser())
|
|
{
|
|
hr = IsValidDomainUser(
|
|
szBufDU,
|
|
szBufAddr, // Borrowing szBufAddr for returning full name
|
|
sizeof(szBufAddr) / sizeof(TCHAR)
|
|
);
|
|
if (FAILED(hr))
|
|
{
|
|
goto ExitHere;
|
|
}
|
|
// Not a valid domain user, report it
|
|
if (hr == S_FALSE)
|
|
{
|
|
// domain user <%s> is invalid
|
|
ReportSz1 (hLogFile, IDS_INVALIDUSER, szBufDU);
|
|
bRecordedError = TRUE;
|
|
bValidUser = FALSE;
|
|
}
|
|
if (szBufFN[0] == 0)
|
|
{
|
|
if (szBufAddr[0] != 0)
|
|
{
|
|
// Got a friendly name from DS, use it
|
|
_tcscpy (szBufFN, szBufAddr);
|
|
}
|
|
}
|
|
}
|
|
// Still got no friendly name? use the domain user name
|
|
if (szBufFN[0] == 0)
|
|
{
|
|
_tcscpy (szBufFN, szBufDU);
|
|
}
|
|
|
|
hr = pCurUser->IsNoMerge (&bNoMerge);
|
|
if (FAILED(hr))
|
|
{
|
|
goto ExitHere;
|
|
}
|
|
if (bNoMerge && !cmd.FValidateOnly())
|
|
{
|
|
hr = pMmc->RemoveLinesForUser(szBufDU);
|
|
if (FAILED(hr))
|
|
{
|
|
goto ExitHere;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Loop through each line, add or remove the device
|
|
//
|
|
if (pCurLine)
|
|
{
|
|
delete pCurLine;
|
|
}
|
|
hr = pCurUser->GetFirstLine (&pCurLine);
|
|
if (FAILED(hr))
|
|
{
|
|
goto ExitHere;
|
|
}
|
|
while (pCurLine != NULL)
|
|
{
|
|
if (FAILED(hr = pCurLine->IsRemove(&bRemove)) ||
|
|
FAILED(hr = pCurLine->IsPermanentID(&bPID)))
|
|
{
|
|
goto ExitHere;
|
|
}
|
|
if (bPID)
|
|
{
|
|
hr = pCurLine->GetPermanentID(&dwPID);
|
|
}
|
|
else
|
|
{
|
|
hr = pCurLine->GetAddress(
|
|
szBufAddr,
|
|
sizeof(szBufAddr)/sizeof(TCHAR)
|
|
);
|
|
}
|
|
if (FAILED(hr))
|
|
{
|
|
goto ExitHere;
|
|
}
|
|
|
|
if (!cmd.FValidateOnly() && bValidUser)
|
|
{
|
|
if (bRemove)
|
|
{
|
|
if (bPID)
|
|
{
|
|
hr = pMmc->RemoveLinePIDForUser (
|
|
dwPID,
|
|
szBufDU
|
|
);
|
|
}
|
|
else
|
|
{
|
|
hr = pMmc->RemoveLineAddrForUser (
|
|
szBufAddr,
|
|
szBufDU
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bPID)
|
|
{
|
|
hr = pMmc->AddLinePIDForUser (
|
|
dwPID,
|
|
szBufDU,
|
|
szBufFN
|
|
);
|
|
}
|
|
else
|
|
{
|
|
hr = pMmc->AddLineAddrForUser (
|
|
szBufAddr,
|
|
szBufDU,
|
|
szBufFN
|
|
);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bPID)
|
|
{
|
|
hr = pMmc->IsValidPID (dwPID);
|
|
}
|
|
else
|
|
{
|
|
hr = pMmc->IsValidAddress (szBufAddr);
|
|
}
|
|
}
|
|
|
|
if( hr == S_FALSE || hr == TSECERR_DEVLOCALONLY)
|
|
{
|
|
// An invalid permanent ID or address is given
|
|
// report the error and quit
|
|
TCHAR szText[256];
|
|
CIds IdsTitle (IDS_PRODUCTNAME);
|
|
|
|
if ( IdsTitle.StringFound () )
|
|
{
|
|
szText[0] = 0;
|
|
|
|
if (bPID)
|
|
{
|
|
CIds IdsError (TSECERR_DEVLOCALONLY ? IDS_LOCALONLYPID : IDS_INVALPID);
|
|
|
|
if ( IdsError.StringFound () )
|
|
{
|
|
wsprintf (szText, IdsError.GetString (), dwPID);
|
|
}
|
|
}
|
|
else if (!bPID)
|
|
{
|
|
CIds IdsError (TSECERR_DEVLOCALONLY ? IDS_LOCALONLYADDR : IDS_INVALADDR);
|
|
|
|
if ( IdsError.StringFound () )
|
|
{
|
|
wsprintf (szText, IdsError.GetString (), szBufAddr);
|
|
}
|
|
}
|
|
if (hLogFile != NULL && hLogFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
char szAnsiBuf[256];
|
|
DWORD dwNumOfBytesWritten;
|
|
|
|
WideCharToMultiByte (
|
|
CP_ACP,
|
|
0,
|
|
szText,
|
|
-1,
|
|
szAnsiBuf,
|
|
sizeof(szAnsiBuf),
|
|
NULL,
|
|
NULL
|
|
);
|
|
lstrcatA (szAnsiBuf, "\n");
|
|
WriteFile (
|
|
hLogFile,
|
|
szAnsiBuf,
|
|
lstrlenA (szAnsiBuf),
|
|
&dwNumOfBytesWritten,
|
|
NULL
|
|
);
|
|
}
|
|
else
|
|
{
|
|
MessagePrint (szText, IdsTitle.GetString ());
|
|
}
|
|
}
|
|
bRecordedError = TRUE;
|
|
hr = S_OK;
|
|
}
|
|
else if(FAILED(hr))
|
|
{
|
|
goto ExitHere;
|
|
}
|
|
|
|
hr = pCurLine->GetNextLine (&pNextLine);
|
|
if (FAILED(hr))
|
|
{
|
|
goto ExitHere;
|
|
}
|
|
delete pCurLine;
|
|
pCurLine = pNextLine;
|
|
}
|
|
|
|
hr = pCurUser->GetNextUser (&pNextUser);
|
|
if (FAILED(hr))
|
|
{
|
|
goto ExitHere;
|
|
}
|
|
delete pCurUser;
|
|
pCurUser = pNextUser;
|
|
}
|
|
|
|
// If error happend, we aready exited, reset warnings
|
|
hr = S_OK;
|
|
// We are done if we are asked to do validating only
|
|
if (bRecordedError)
|
|
{
|
|
MessagePrintIds (IDS_HASERROR);
|
|
}
|
|
else if (cmd.FValidateOnly())
|
|
{
|
|
MessagePrintIds (IDS_VALIDSUCCESS);
|
|
}
|
|
else
|
|
{
|
|
MessagePrintIds (IDS_FINSUCCESS);
|
|
}
|
|
|
|
ExitHere:
|
|
|
|
//
|
|
// Report error if any here
|
|
//
|
|
if(FAILED(hr))
|
|
{
|
|
ReportError (NULL, hr);
|
|
}
|
|
|
|
if (hwndDump)
|
|
{
|
|
DestroyWindow (hwndDump);
|
|
}
|
|
|
|
if (hLogFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseHandle (hLogFile);
|
|
}
|
|
|
|
if (pCurLine)
|
|
{
|
|
delete pCurLine;
|
|
}
|
|
if (pCurUser)
|
|
{
|
|
delete pCurUser;
|
|
}
|
|
if (pMmc)
|
|
{
|
|
delete pMmc;
|
|
}
|
|
parser.Release();
|
|
if (bUninit)
|
|
{
|
|
CoUninitialize ();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void ReportError (
|
|
HANDLE hFile,
|
|
HRESULT hr
|
|
)
|
|
{
|
|
TCHAR szTitle[128];
|
|
TCHAR szBuf[512];
|
|
HINSTANCE hModule = GetModuleHandle (NULL);
|
|
|
|
if (LoadString (
|
|
hModule,
|
|
IDS_PRODUCTNAME,
|
|
szTitle,
|
|
sizeof(szTitle)/sizeof(TCHAR)
|
|
) == 0)
|
|
{
|
|
goto ExitHere;
|
|
}
|
|
|
|
// Is this our own error
|
|
if (HRESULT_FACILITY(hr) == FACILITY_TSEC_CODE)
|
|
{
|
|
if (FormatMessage (
|
|
FORMAT_MESSAGE_FROM_HMODULE,
|
|
hModule,
|
|
HRESULT_CODE(hr),
|
|
0,
|
|
szBuf,
|
|
sizeof(szBuf)/sizeof(TCHAR),
|
|
NULL
|
|
) == 0)
|
|
{
|
|
goto ExitHere;
|
|
}
|
|
}
|
|
// Is this TAPI error?
|
|
else if ((hr < 0 && hr > -100) || HRESULT_FACILITY(hr) == 0)
|
|
{
|
|
hModule = LoadLibrary (TEXT("TAPIUI.DLL"));
|
|
if (hModule == NULL)
|
|
{
|
|
goto ExitHere;
|
|
}
|
|
if (FormatMessage (
|
|
FORMAT_MESSAGE_FROM_HMODULE,
|
|
hModule,
|
|
TAPIERROR_FORMATMESSAGE(hr),
|
|
0,
|
|
szBuf,
|
|
sizeof(szBuf)/sizeof(TCHAR),
|
|
NULL
|
|
) == 0)
|
|
{
|
|
FreeLibrary (hModule);
|
|
goto ExitHere;
|
|
}
|
|
FreeLibrary (hModule);
|
|
}
|
|
// Assume system error
|
|
else
|
|
{
|
|
if (FormatMessage (
|
|
FORMAT_MESSAGE_FROM_SYSTEM,
|
|
NULL,
|
|
HRESULT_CODE(hr),
|
|
0,
|
|
szBuf,
|
|
sizeof(szBuf)/sizeof(TCHAR),
|
|
NULL
|
|
) == 0)
|
|
{
|
|
goto ExitHere;
|
|
}
|
|
}
|
|
if (hFile == NULL || hFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
MessagePrint (szBuf, szTitle);
|
|
}
|
|
else
|
|
{
|
|
char szAnsiBuf[1024];
|
|
DWORD dwNumOfBytesWritten;
|
|
|
|
WideCharToMultiByte (
|
|
CP_ACP,
|
|
0,
|
|
szBuf,
|
|
-1,
|
|
szAnsiBuf,
|
|
sizeof(szAnsiBuf),
|
|
NULL,
|
|
NULL
|
|
);
|
|
lstrcatA (szAnsiBuf, "\n");
|
|
WriteFile (
|
|
hFile,
|
|
szAnsiBuf,
|
|
lstrlenA (szAnsiBuf),
|
|
&dwNumOfBytesWritten,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
ExitHere:
|
|
return;
|
|
}
|
|
|