Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1538 lines
31 KiB

/*++
Copyright (C) Microsoft Corporation, 1998 - 1999
Module Name:
TclRdCmd
Abstract:
This module provides the implementation for the Tcl command line reader.
Author:
Doug Barlow (dbarlow) 3/14/1998
Environment:
Win32, C++ w/ exceptions, Tcl
Notes:
?Notes?
--*/
// #ifndef WIN32_LEAN_AND_MEAN
// #define WIN32_LEAN_AND_MEAN
// #endif
// #include <windows.h> // All the Windows definitions.
#include <afx.h>
#include <tchar.h>
extern "C"
{
#include "tclHelp.h"
}
#include "tclRdCmd.h" // Our definitions
//
//==============================================================================
//
// CTclCommand
//
/*++
CONSTRUCTOR:
These are the constructors for a CTclCommand object.
Arguments:
Per the standard Tcl command calling sequence, the parameters are:
interp - The Tcl interpreter against which to report errors.
argc - The number of command line arguments
argv - The vector of command line arguments
Return Value:
None
Author:
Doug Barlow (dbarlow) 3/14/1998
--*/
CTclCommand::CTclCommand(
void)
{
Constructor();
}
CTclCommand::CTclCommand(
Tcl_Interp *interp,
int argc,
char *argv[])
{
Constructor();
Initialize(interp, argc, argv);
}
/*++
Constructor:
This is a constructor helper routine. All constructors call this routine
first to be sure internal properties are initialized.
Arguments:
None
Return Value:
None
Author:
Doug Barlow (dbarlow) 3/14/1998
--*/
void
CTclCommand::Constructor(
void)
{
m_fErrorDeclared = FALSE;
m_pInterp = NULL;
m_dwArgCount = 0;
m_dwArgIndex = 0;
m_rgszArgs = NULL;
}
/*++
DESTRUCTOR:
This is the destructor for the object. It cleans up any outstanding
resources.
Author:
Doug Barlow (dbarlow) 3/14/1998
--*/
CTclCommand::~CTclCommand()
{
}
/*++
Initialize:
This method initializes the object with the standard Tcl command parameters.
Arguments:
Per the standard Tcl command calling sequence, the parameters are:
interp - The Tcl interpreter against which to report errors.
argc - The number of command line arguments
argv - The vector of command line arguments
Return Value:
None
Throws:
Errors are thrown as DWORD status codes.
Author:
Doug Barlow (dbarlow) 3/14/1998
--*/
void
CTclCommand::Initialize(
Tcl_Interp *interp,
int argc,
char *argv[])
{
if (NULL != m_pInterp)
throw (DWORD)ERROR_ALREADY_INITIALIZED;
m_pInterp = interp;
m_dwArgCount = (DWORD)argc;
m_rgszArgs = argv;
m_dwArgIndex = 1;
}
/*++
SetError:
These routines establish an error message for the command, if one doesn't
exist already.
Arguments:
dwError supplies an error code who's message should be reported.
szMessage supplies a text string to be reported.
szMsg<n> supplies a list of text strings to be reported. The last
parameter must be NULL to terminate the list.
Return Value:
None
Author:
Doug Barlow (dbarlow) 3/14/1998
--*/
void
CTclCommand::SetError(
DWORD dwError)
{
SetError(ErrorString(dwError), (LPCTSTR)NULL);
}
void
CTclCommand::SetError(
LPCTSTR szMessage,
DWORD dwError)
{
SetError(szMessage, ErrorString(dwError), NULL);
}
void
CTclCommand::SetError(
LPCTSTR szMsg1,
...)
{
va_list vaArgs;
LPCTSTR szMsg;
va_start(vaArgs, szMsg1);
szMsg = szMsg1;
if (!m_fErrorDeclared)
{
Tcl_ResetResult(m_pInterp);
while (NULL != szMsg)
{
Tcl_AppendResult(m_pInterp, szMsg, NULL);
szMsg = va_arg(vaArgs, LPCTSTR);
}
m_fErrorDeclared = TRUE;
}
va_end(vaArgs);
}
/*++
TclError:
This routine is called to note that Tcl has already filled in the error
reason, and we should just pass it along.
Arguments:
None
Return Value:
TCL_ERROR (suitable for throwing)
Author:
Doug Barlow (dbarlow) 3/14/1998
--*/
DWORD
CTclCommand::TclError(
void)
{
m_fErrorDeclared = TRUE;
return TCL_ERROR;
}
/*++
Keyword:
This method converts a list of keywords into an integer identifying the
keyword. The list of keywords must be NULL-terminated (the last parameter
must be NULL).
Arguments:
szKeyword - supplies one or more keywords to be translated into an integer.
The last keyword must be NULL to terminate the list.
Return Value:
0 - None of the keywords matched the next input argument.
-1 - More than one of the keywords matched the next input argument.
n > 0 - Keyword 'n' (counting from one) matched the next input argument.
Author:
Doug Barlow (dbarlow) 3/14/1998
--*/
LONG
CTclCommand::Keyword(
IN LPCTSTR szKeyword, ...)
{
va_list vaArgs;
LPCTSTR szKey;
CString szArg;
DWORD dwLength;
DWORD dwReturn = 0;
DWORD dwCount = 0;
PeekArgument(szArg);
dwLength = szArg.GetLength();
if (0 == dwLength)
return 0; // Empty strings don't match anything.
va_start(vaArgs, szKeyword);
szKey = szKeyword;
while (NULL != szKey)
{
dwCount += 1;
if (0 == _tcsncicmp(szArg, szKey, dwLength))
{
if (0 != dwReturn)
{
dwReturn = -1;
break;
}
dwReturn = dwCount;
}
szKey = va_arg(vaArgs, LPCTSTR);
}
va_end(vaArgs);
if (0 < dwReturn)
NextArgument();
return dwReturn;
}
/*++
GetArgument:
This method obtains the specified argument in the command.
Arguments:
szToken receives the specified argument of the command.
Return Value:
None
Throws:
TCL_ERROR - if there aren't enough arguments on the command line,
preprepping the error string.
Author:
Doug Barlow (dbarlow) 3/14/1998
--*/
void
CTclCommand::GetArgument(
DWORD dwArgId,
CString &szToken)
{
if (dwArgId >= m_dwArgCount)
{
CString szCommand;
GetArgument(0, szCommand);
SetError(
TEXT("Insufficient parameters to the '"),
szCommand,
TEXT("' command."),
NULL);
throw (DWORD)TCL_ERROR;
}
szToken = m_rgszArgs[dwArgId];
}
/*++
PeekArgument:
This method obtains the next argument in the command without moving on to
the next argument.
Arguments:
szToken receives the next argument of the command.
Return Value:
None
Throws:
TCL_ERROR - if there are no more arguments on the command line, preprepping
the error string.
Author:
Doug Barlow (dbarlow) 3/14/1998
--*/
void
CTclCommand::PeekArgument(
CString &szToken)
{
GetArgument(m_dwArgIndex, szToken);
}
/*++
NextArgument:
This method moves forward to the next argument.
Arguments:
szToken receives the next argument of the command.
Return Value:
None
Throws:
TCL_ERROR - if there are no more arguments on the command line, preprepping
the error string.
Author:
Doug Barlow (dbarlow) 3/14/1998
--*/
void
CTclCommand::NextArgument(
void)
{
m_dwArgIndex += 1;
}
void
CTclCommand::NextArgument(
CString &szToken)
{
PeekArgument(szToken);
NextArgument();
}
/*++
IsMoreArguments:
This method obtains whether or not there are additional parameters to be
processed. It returns TRUE while parameters remain, and returns FALSE if
none remain. A minimum number of parameters may be specified, in which case
it returns whether or not there are at least that number of parameters
remaining.
Arguments:
dwCount - If supplied, this provides a way to ask if 'dwCount' parameters
remain.
Return Value:
TRUE - At least dwCount parameters remain to be processed
FALSE - less that dwCount parameters remain to be processed.
Throws:
None
Author:
Doug Barlow (dbarlow) 3/14/1998
--*/
BOOL
CTclCommand::IsMoreArguments(
DWORD dwCount)
const
{
return m_dwArgIndex + dwCount <= m_dwArgCount;
}
/*++
NoMoreArguments:
This method asserts that there are no more arguments in the command line. If there are,
a BadSyntax error is thrown.
Arguments:
None
Return Value:
None
Throws:
TCL_ERROR as a DWORD if more arguments remain on the command line
Author:
Doug Barlow (dbarlow) 3/14/1998
--*/
void
CTclCommand::NoMoreArguments(
void)
{
if (m_dwArgIndex < m_dwArgCount)
throw BadSyntax();
}
/*++
BadSyntax:
This method declares a syntax error. It does not throw an error, but
returns a DWORD suitable for throwing.
Arguments:
szParam - Supplies the syntactic offender string, or NULL.
Return Value:
A DWORD error code suitable for throwing.
Throws:
None
Author:
Doug Barlow (dbarlow) 3/14/1998
--*/
DWORD
CTclCommand::BadSyntax(
LPCTSTR szOffender)
{
DWORD dwIndex;
if (NULL == szOffender)
szOffender = m_rgszArgs[m_dwArgIndex];
Tcl_ResetResult(m_pInterp);
Tcl_AppendResult(
m_pInterp,
"Invalid option '",
szOffender,
"' to the '",
NULL);
for (dwIndex = 0; dwIndex < m_dwArgIndex; dwIndex += 1)
Tcl_AppendResult(m_pInterp, m_rgszArgs[dwIndex], " ", NULL);
Tcl_AppendResult(m_pInterp, "...' command.", NULL);
m_fErrorDeclared = TRUE;
return TCL_ERROR;
}
/*++
Value:
This method extracts a LONG value from the argument list.
Arguments:
lDefault supplies the default value.
Return Value:
The value extracted.
Throws:
If no default value is suppled and the next parameter is not an integer,
TCL_ERROR is thrown as a DWORD.
Author:
Doug Barlow (dbarlow) 3/14/1998
--*/
LONG
CTclCommand::Value(
LONG lDefault)
{
LONG lReturn;
CString szValue;
PeekArgument(szValue);
if (TCL_OK == Tcl_ExprLong(m_pInterp, SZ(szValue), &lReturn))
NextArgument();
else
{
Tcl_ResetResult(m_pInterp);
lReturn = lDefault;
}
return lReturn;
}
LONG
CTclCommand::Value(
void)
{
LONG lReturn;
CString szValue;
PeekArgument(szValue);
if (TCL_OK != Tcl_ExprLong(m_pInterp, SZ(szValue), &lReturn))
throw (DWORD)TCL_ERROR;
NextArgument();
return lReturn;
}
/*++
MapValue:
This method converts text into a value, given a ValueMap structure. The
class member automatically extracts the keyword.
Arguments:
rgvmMap supplies the value map array. The last element's string value
must be NULL.
szString supplies the value to be parsed.
fValueOk supplies a flag indicating whether or not an integral value may be
supplied instead of a symbolic token.
Return Value:
The value resulting from the map.
Throws:
If no default value is suppled and the next parameter is not an integer,
TCL_ERROR is thrown as a DWORD.
Author:
Doug Barlow (dbarlow) 3/14/1998
--*/
LONG
CTclCommand::MapValue(
const ValueMap *rgvmMap,
BOOL fValueOk)
{
CString szValue;
LONG lReturn;
PeekArgument(szValue);
lReturn = MapValue(rgvmMap, szValue, fValueOk);
NextArgument();
return lReturn;
}
LONG
CTclCommand::MapValue(
const ValueMap *rgvmMap,
CString &szValue,
BOOL fValueOk)
{
LONG lReturn;
LONG lMap = -1;
DWORD dwIndex, dwLength;
if (fValueOk && (TCL_OK != Tcl_ExprLong(m_pInterp, SZ(szValue), &lReturn)))
{
Tcl_ResetResult(m_pInterp);
dwLength = szValue.GetLength();
if (0 == dwLength)
throw BadSyntax();
for (dwIndex = 0; NULL != rgvmMap[dwIndex].szValue; dwIndex += 1)
{
if (0 == _tcsncicmp(
szValue,
rgvmMap[dwIndex].szValue,
dwLength))
{
if (-1 != lMap)
throw BadSyntax();
lMap = (LONG)dwIndex;
if (0 == rgvmMap[dwIndex].szValue[dwLength])
break;
}
}
if (-1 == lMap)
throw BadSyntax(szValue);
lReturn = rgvmMap[lMap].lValue;
}
return lReturn;
}
/*++
MapFlags:
This method converts a text list into a single value, given a ValueMap
structure. The list is taken as an array of flags. The corresponding
values are OR'ed together to obtain the return value.
The class member automatically extracts the keyword.
Arguments:
rgvmMap supplies the value map array. The last element's string value
must be NULL.
fValueOk supplies a flag indicating whether or not an integral value may be
supplied instead of a symbolic token.
Return Value:
The value resulting from the map.
Throws:
If no default value is suppled and the next parameter is not an integer,
TCL_ERROR is thrown as a DWORD.
Author:
Doug Barlow (dbarlow) 3/14/1998
--*/
DWORD
CTclCommand::MapFlags(
const ValueMap *rgvmMap,
BOOL fValueOk)
{
CArgArray rgFlags(*this);
CString szFlags;
CString szFlag;
DWORD dwFlags = 0;
DWORD dwIndex = 0;
NextArgument(szFlags);
rgFlags.LoadList(szFlags);
for (dwIndex = rgFlags.Count(); dwIndex > 0;)
{
rgFlags.Fetch(--dwIndex, szFlag);
dwFlags |= MapValue(rgvmMap, szFlag);
}
return dwFlags;
}
/*++
OutputStyle:
This method parses the common binary data output flags and prepares to
properly render it on output.
Arguments:
outData supplies the CRenderableData object with information on how to
render its internal binary data.
Return Value:
None
Throws:
Errors are thrown as exceptions
Author:
Doug Barlow (dbarlow) 5/5/1998
--*/
void
CTclCommand::OutputStyle(
CRenderableData &outData)
{
outData.SetDisplayType(CRenderableData::Undefined);
if (IsMoreArguments())
{
switch (Keyword(TEXT("/OUTPUT"), TEXT("-OUTPUT"),
TEXT("/HEXIDECIMAL"), TEXT("-HEXIDECIMAL"),
TEXT("/TEXT"), TEXT("-TEXT"),
TEXT("/ANSI"), TEXT("-ANSI"),
TEXT("/UNICODE"), TEXT("-UNICODE"),
TEXT("/FILE"), TEXT("-FILE"),
NULL))
{
case 1: // /OUTPUT
case 2: // -OUTPUT
switch (Keyword(TEXT("HEXIDECIMAL"), TEXT("TEXT"),
TEXT("ANSI"), TEXT("UNICODE"),
TEXT("FILE"), NULL))
{
case 1: // HEX
outData.SetDisplayType(CRenderableData::Hexidecimal);
break;
case 2: // TEXT
outData.SetDisplayType(CRenderableData::Text);
break;
case 3: // ANSI
outData.SetDisplayType(CRenderableData::Ansi);
break;
case 4: // UNICODE
outData.SetDisplayType(CRenderableData::Unicode);
break;
case 5: // FILE
outData.SetDisplayType(CRenderableData::File);
NextArgument(outData.m_szFile);
break;
default:
throw BadSyntax();
}
break;
case 3: // /HEX
case 4: // -HEX
outData.SetDisplayType(CRenderableData::Hexidecimal);
break;
case 5: // /TEXT
case 6: // -TEXT
outData.SetDisplayType(CRenderableData::Text);
break;
case 7: // /ANSI
case 8: // -ANSI
outData.SetDisplayType(CRenderableData::Ansi);
break;
case 9: // /UNICODE
case 10: // -UNICODE
outData.SetDisplayType(CRenderableData::Unicode);
break;
case 11: // /FILE <name>
case 12: // -FILE <name>
outData.SetDisplayType(CRenderableData::File);
NextArgument(outData.m_szFile);
break;
default:
; // No action
}
}
}
/*++
InputStyle:
This method parses the common binary data input flags and prepares to
properly interpret input data.
Arguments:
inData supplies the CRenderableData object with information on how to
interpret binary data.
Return Value:
None
Throws:
Errors are thrown as exceptions
Author:
Doug Barlow (dbarlow) 5/5/1998
--*/
void
CTclCommand::InputStyle(
CRenderableData &inData)
{
inData.SetDisplayType(CRenderableData::Undefined);
switch (Keyword(TEXT("/INPUT"), TEXT("-INPUT"),
TEXT("/HEXIDECIMAL"), TEXT("-HEXIDECIMAL"),
TEXT("/TEXT"), TEXT("-TEXT"),
TEXT("/ANSI"), TEXT("-ANSI"),
TEXT("/UNICODE"), TEXT("-UNICODE"),
TEXT("/FILE"), TEXT("-FILE"),
NULL))
{
case 1: // /INPUT
case 2: // -INPUT
switch (Keyword(TEXT("HEXIDECIMAL"), TEXT("TEXT"),
TEXT("ANSI"), TEXT("UNICODE"),
TEXT("FILE"), NULL))
{
case 1: // HEX
inData.SetDisplayType(CRenderableData::Hexidecimal);
break;
case 2: // TEXT
inData.SetDisplayType(CRenderableData::Text);
break;
case 3: // ANSI
inData.SetDisplayType(CRenderableData::Ansi);
break;
case 4: // UNICODE
inData.SetDisplayType(CRenderableData::Unicode);
break;
case 5: // FILE
inData.SetDisplayType(CRenderableData::File);
break;
default:
throw BadSyntax();
}
break;
case 3: // /HEX
case 4: // -HEX
inData.SetDisplayType(CRenderableData::Hexidecimal);
break;
case 5: // /TEXT
case 6: // -TEXT
inData.SetDisplayType(CRenderableData::Text);
break;
case 7: // /ANSI
case 8: // -ANSI
inData.SetDisplayType(CRenderableData::Ansi);
break;
case 9: // /UNICODE
case 10: // -UNICODE
inData.SetDisplayType(CRenderableData::Unicode);
break;
case 11: // /FILE <name>
case 12: // -FILE <name>
inData.SetDisplayType(CRenderableData::File);
break;
default:
; // No action
}
}
/*++
IOStyle:
This method parses the common binary data input and output flags, and
prepares to properly interpret and render data.
Arguments:
outData supplies the CRenderableData object with information on how to
render its internal binary data.
Return Value:
None
Throws:
Errors are thrown as exceptions
Author:
Doug Barlow (dbarlow) 5/5/1998
--*/
void
CTclCommand::IOStyle(
CRenderableData &inData,
CRenderableData &outData)
{
BOOL fInput, fOutput;
outData.SetDisplayType(CRenderableData::Undefined);
inData.SetDisplayType(CRenderableData::Undefined);
fInput = fOutput = FALSE;
do
{
switch (Keyword(TEXT("/OUTPUT"), TEXT("-OUTPUT"),
TEXT("/INPUT"), TEXT("-INPUT"),
NULL))
{
case 1: // /OUTPUT
case 2: // -OUTPUT
if (fOutput)
throw BadSyntax();
switch (Keyword(TEXT("HEXIDECIMAL"), TEXT("TEXT"),
TEXT("ANSI"), TEXT("UNICODE"),
TEXT("FILE"), NULL))
{
case 1: // HEX
outData.SetDisplayType(CRenderableData::Hexidecimal);
break;
case 2: // TEXT
outData.SetDisplayType(CRenderableData::Text);
break;
case 3: // ANSI
outData.SetDisplayType(CRenderableData::Ansi);
break;
case 4: // UNICODE
outData.SetDisplayType(CRenderableData::Unicode);
break;
case 5: // FILE
outData.SetDisplayType(CRenderableData::File);
NextArgument(outData.m_szFile);
break;
default:
throw BadSyntax();
}
fOutput = TRUE;
break;
case 3: // /INPUT
case 4: // -INPUT
if (fInput)
throw BadSyntax();
switch (Keyword(TEXT("HEXIDECIMAL"), TEXT("TEXT"),
TEXT("ANSI"), TEXT("UNICODE"),
TEXT("FILE"), NULL))
{
case 1: // HEX
inData.SetDisplayType(CRenderableData::Hexidecimal);
break;
case 2: // TEXT
inData.SetDisplayType(CRenderableData::Text);
break;
case 3: // ANSI
inData.SetDisplayType(CRenderableData::Ansi);
break;
case 4: // UNICODE
inData.SetDisplayType(CRenderableData::Unicode);
break;
case 5: // FILE
inData.SetDisplayType(CRenderableData::File);
break;
default:
throw BadSyntax();
}
fInput = TRUE;
break;
default:
fInput = fOutput = TRUE;
}
} while (!fInput || !fOutput);
}
/*++
Render:
This method renders data from a CRenderableData object into the Tcl output
buffer.
Arguments:
outData supplies the CRenderableData object with information on how to
render its internal binary data.
Return Value:
None
Throws:
Errors are thrown as exceptions
Author:
Doug Barlow (dbarlow) 5/6/1998
--*/
void
CTclCommand::Render(
CRenderableData &outData)
{
try
{
Tcl_AppendResult(*this, outData.RenderData(), NULL);
}
catch (DWORD dwError)
{
SetError(
TEXT("Failed to render output data: "),
dwError);
throw (DWORD)TCL_ERROR;
}
}
/*++
ReadData:
This method reads input data into a CRenderableData object from the Tcl
input stream.
Arguments:
inData supplies the CRenderableData object with information on how to
read the next parameter into its internal binary data.
Return Value:
None
Throws:
Errors are thrown as exceptions
Author:
Doug Barlow (dbarlow) 5/14/1998
--*/
void
CTclCommand::ReadData(
CRenderableData &inData)
{
CString szValue;
try
{
PeekArgument(szValue);
inData.LoadData(szValue);
NextArgument();
}
catch (...)
{
throw BadSyntax();
}
}
//
//==============================================================================
//
// CRenderableData
//
/*++
CONSTRUCTOR:
This is the constructor for a CRenderableData object.
Arguments:
None
Return Value:
None
Author:
Doug Barlow (dbarlow) 5/5/1998
--*/
CRenderableData::CRenderableData(
void)
: m_bfData(),
m_szString(),
m_szFile()
{
m_dwType = Undefined;
}
/*++
DESTRUCTOR:
This is the destructor for a CRenderableData object.
Arguments:
None
Return Value:
None
Author:
Doug Barlow (dbarlow) 5/5/1998
--*/
CRenderableData::~CRenderableData()
{
}
/*++
LoadData:
This method loads data into the style buffer. There are two forms, loading
from a string, and direct binary loading.
Arguments:
szData supplies the data to be loaded, in it's string format.
dwType supplies the type of string data being loaded.
Return Value:
None
Throws:
Errors are thrown as DWORD status codes.
Author:
Doug Barlow (dbarlow) 5/5/1998
--*/
void
CRenderableData::LoadData(
LPCTSTR szData,
DisplayType dwType)
{
if (Undefined == dwType)
dwType = m_dwType;
switch (dwType)
{
case Text:
m_bfData.Set((LPCBYTE)szData, (lstrlen(szData) + 1) * sizeof(TCHAR));
break;
case Ansi:
case Unicode:
throw (DWORD)SCARD_F_INTERNAL_ERROR;
break;
case Undefined: // Default output
case Hexidecimal:
{
DWORD dwHex, dwLength, dwIndex;
BYTE bHex;
m_bfData.Reset();
dwLength = lstrlen(szData);
if (dwLength != _tcsspn(szData, TEXT("0123456789ABCDEFabcdef")))
throw (DWORD)SCARD_E_INVALID_VALUE;
m_bfData.Resize(dwLength / 2);
for (dwIndex = 0; dwIndex < dwLength; dwIndex += 2)
{
_stscanf(&szData[dwIndex], TEXT(" %2lx"), &dwHex);
bHex = (BYTE)dwHex;
*m_bfData.Access(dwIndex / 2) = bHex;
}
break;
}
case File:
{
HANDLE hFile = INVALID_HANDLE_VALUE;
BOOL fSts;
DWORD dwLen;
try
{
hFile = CreateFile(
szData,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE == hFile)
throw GetLastError();
m_bfData.Presize(GetFileSize(hFile, NULL));
fSts = ReadFile(
hFile,
m_bfData.Access(),
m_bfData.Space(),
&dwLen,
NULL);
if (!fSts)
throw GetLastError();
m_bfData.Resize(dwLen, TRUE);
fSts = CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
if (!fSts)
throw GetLastError();
}
catch (...)
{
if (INVALID_HANDLE_VALUE != hFile)
{
fSts = CloseHandle(hFile);
ASSERT(fSts);
}
throw;
}
break;
}
default:
throw (DWORD)SCARD_F_INTERNAL_ERROR;
}
}
/*++
RenderData:
This method converts the raw binary data stored in the stype to the
provided display type.
Arguments:
dwType supplies the type of string data to be returned.
Return Value:
The rendered string
Throws:
Errors are thrown as DWORD status codes
Author:
Doug Barlow (dbarlow) 5/5/1998
--*/
LPCTSTR
CRenderableData::RenderData(
DisplayType dwType)
{
if (Undefined == dwType)
dwType = m_dwType;
switch (dwType)
{
case Text:
m_bfData.Append((LPBYTE)TEXT("\000"), sizeof(TCHAR));
m_szString = (LPCTSTR)m_bfData.Access();
break;
case Ansi:
m_bfData.Append((LPBYTE)"\000", sizeof(CHAR));
m_szString = (LPCSTR)m_bfData.Access();
break;
case Unicode:
m_bfData.Append((LPBYTE)L"\000", sizeof(WCHAR));
m_szString = (LPCWSTR)m_bfData.Access();
break;
case Undefined: // Default output
case Hexidecimal:
{
DWORD dwIndex;
DWORD dwLength = m_bfData.Length();
CBuffer bfString((dwLength * 2 + 1) * sizeof(TCHAR));
for (dwIndex = 0; dwIndex < dwLength; dwIndex += 1)
wsprintf(
(LPTSTR)bfString.Access(dwIndex * 2 * sizeof(TCHAR)),
TEXT("%02x"),
m_bfData[dwIndex]);
*(LPTSTR)bfString.Access(dwLength * 2 * sizeof(TCHAR)) = TEXT('\000');
m_szString = (LPCTSTR)bfString.Access();
break;
}
case File:
{
HANDLE hFile = INVALID_HANDLE_VALUE;
BOOL fSts;
DWORD dwLen;
m_szString.Empty();
try
{
if (m_szFile.IsEmpty())
throw (DWORD)ERROR_INVALID_NAME;
hFile = CreateFile(
m_szFile,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE == hFile)
throw GetLastError();
fSts = WriteFile(
hFile,
m_bfData.Access(),
m_bfData.Length(),
&dwLen,
NULL);
if (!fSts)
throw GetLastError();
ASSERT(dwLen == m_bfData.Length());
fSts = CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
if (!fSts)
throw GetLastError();
}
catch (...)
{
if (INVALID_HANDLE_VALUE != hFile)
{
fSts = CloseHandle(hFile);
ASSERT(fSts);
}
throw;
}
break;
}
default:
throw (DWORD)SCARD_F_INTERNAL_ERROR;
}
return m_szString;
}
//
//==============================================================================
//
// CArgArray
//
/*++
CONSTRUCTOR:
This method is the default constructor for a CArgArray.
Arguments:
None
Author:
Doug Barlow (dbarlow) 5/14/1998
--*/
CArgArray::CArgArray(
CTclCommand &tclCmd)
: m_rgszElements()
{
m_pTclCmd = &tclCmd;
m_pszMemory = NULL;
m_dwElements = 0;
}
/*++
DESTRUCTOR:
This is the destructor method for the CArgArray.
Remarks:
The string elements are automatically freed.
Author:
Doug Barlow (dbarlow) 5/14/1998
--*/
CArgArray::~CArgArray()
{
if (NULL != m_pszMemory)
ckfree((LPSTR)m_pszMemory);
}
/*++
LoadList:
Load a potential list of arguments into the argument list, so that they may
be accessed individually.
Arguments:
szList supplies the Tcl Text string that contains the individual arguments.
Return Value:
None
Throws:
Errors are thrown as DWORD exceptions.
Author:
Doug Barlow (dbarlow) 5/14/1998
--*/
void
CArgArray::LoadList(
LPCSTR szList)
{
int nElements;
DWORD dwIndex;
Tcl_SplitList(*m_pTclCmd, (LPSTR)szList, &nElements, &m_pszMemory);
m_dwElements = (DWORD)nElements;
for (dwIndex = 0; dwIndex < m_dwElements; dwIndex += 1)
m_rgszElements.Add(m_pszMemory[dwIndex]);
}