|
|
/*++
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]); }
|