Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

945 lines
21 KiB

#define STRICT
#include <windows.h>
#include <windowsx.h>
#include <tspi.h>
#ifndef WIN32
#include <memory.h>
#endif
#include "logger.h"
#include "debug.h"
#ifndef TCHAR
#define TCHAR char
#endif
#if ! defined(TEXT)
#define TEXT(string) string
#endif
#ifndef LPCWSTR
#define LPCWSTR LPCSTR
#endif
extern BOOL gfTerminateNow;
DWORD gdwTotalBlocks;
DWORD gdwID = 0;
CHUNK gChunks[MAXCHUNKS];
typedef struct tagLOGSTRUCT
{
int iSize;
struct tagLOGSTRUCT* pNext;
} LOGSTRUCT, * PLOGSTRUCT;
#ifdef WIN32
PLOGSTRUCT gpBegin = NULL, gpEnd = NULL;
CRITICAL_SECTION gcsLogging;
CRITICAL_SECTION gcsID;
#endif
#ifdef WIN32
HANDLE ghLogFile = NULL;
#else
HFILE ghLogFile = NULL;
#endif
#ifndef MAX_PATH
#define MAX_PATH 260
#endif
#ifndef WIN32
char gszFileName[MAX_PATH];
#endif
BOOL InitLogging();
void WriteData();
BOOL CopyIDToList(int iCount, LPVOID pBuffer);
//***************************************************************************
//***************************************************************************
//***************************************************************************
#ifdef WIN32
DWORD WINAPI LoggingThread( LPVOID pThreadParm )
{
DBGOUT((3, "Entering LoggingThread"));
while ( !gfTerminateNow )
{
if (NULL != gpBegin)
{
WriteData();
}
Sleep(0);
}
DBGOUT((3, "Closing File Handle"));
CloseHandle(ghLogFile);
DBGOUT((3, "Exiting thread"));
ExitThread(0);
return 0;
}
#endif //WIN32
#if 0
#ifdef WIN32
void CopyData(LPVOID pBuffer, int iCount)
{
PLOGSTRUCT pNew;
// if we have a lot of stuff to write, hold up here and
// wait until we've written a bunch
if (gdwTotalBlocks > MAXCHUNKS)
{
while (gdwTotalBlocks > MINCHUNKS)
{
Sleep(0);
}
}
pNew = (PLOGSTRUCT)GlobalAlloc(GPTR, iCount+sizeof(LOGSTRUCT));
pNew->pNext = NULL;
pNew->iSize = iCount;
memcpy(pNew+1, pBuffer, iCount);
EnterCriticalSection(&gcsLogging);
if (gpBegin == NULL)
{
gpBegin = pNew;
}
else
{
gpEnd->pNext = pNew;
}
gpEnd = pNew;
LeaveCriticalSection(&gcsLogging);
gdwTotalBlocks++;
}
#else
void CopyData(LPVOID pBuffer, int iCount)
{
OFSTRUCT ofstruct;
ofstruct.cBytes = sizeof(ofstruct);
ghLogFile = OpenFile(gszFileName,
&ofstruct,
OF_READWRITE);
if (ghLogFile == HFILE_ERROR)
{
DBGOUT((3,"OpenFile failed"));
return;
}
_llseek(ghLogFile,
0,
2);
if (_lwrite(ghLogFile,
pBuffer,
iCount) == HFILE_ERROR)
{
char szbuf[128];
wsprintf(szbuf, "icount %d", iCount);
MessageBox(NULL, szbuf, NULL, MB_OK);
MessageBox(NULL, "writefile error", NULL, MB_OK);
}
_lclose(ghLogFile);
}
#endif
#endif // 0
#ifdef WIN32
void WriteData()
{
PLOGSTRUCT pHold;
DWORD dwNumBytes;
while (gpBegin != NULL)
{
WriteFile(ghLogFile,
(LPCVOID)(gpBegin+1),
gpBegin->iSize,
&dwNumBytes,
NULL);
if (dwNumBytes != (DWORD)(gpBegin->iSize))
{
//bugbug do something
}
EnterCriticalSection(&gcsLogging);
pHold = gpBegin;
gpBegin = gpBegin->pNext;
LeaveCriticalSection(&gcsLogging);
GlobalFree(pHold);
gdwTotalBlocks--;
}
}
#endif
#define SZFILEBASE "rep"
#define SZFILEEXT ".log"
#define SZREPEATERKEY "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Repeater"
#define SZLOGFILE "LogFileDirectory"
#define SZREPEATER "Repeater"
#define SZTELEPHONINI "telephon.ini"
BOOL InitLogging()
{
TCHAR szFileName[MAX_PATH];
TCHAR szFilePath[MAX_PATH];
int i = 0;
#ifdef WIN32
HKEY hRepeaterKey;
DWORD dwSize;
#else
OFSTRUCT ofstruct;
#endif
DBGOUT((3, "Entering InitLogging"));
#ifdef WIN32
RegOpenKeyEx(HKEY_LOCAL_MACHINE,
SZREPEATERKEY,
0,
KEY_ALL_ACCESS,
&hRepeaterKey);
dwSize = MAX_PATH;
RegQueryValueEx(hRepeaterKey,
SZLOGFILE,
NULL,
NULL,
szFilePath,
&dwSize);
RegCloseKey(hRepeaterKey);
#else
GetPrivateProfileString(SZREPEATER,
SZLOGFILE,
"",
szFilePath,
MAX_PATH,
SZTELEPHONINI);
#endif
gdwTotalBlocks = 0;
while (TRUE)
{
#ifdef WIN32
HANDLE hFile;
WIN32_FIND_DATA FindData;
wsprintf(szFileName,
"%s%s%d%s",
szFilePath,
SZFILEBASE,
i,
SZFILEEXT);
/*
ghLogFile = CreateFile(szFileName,
GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (ghLogFile == INVALID_HANDLE_VALUE)
{
break;
}
CloseHandle(ghLogFile);*/
hFile = FindFirstFile(szFileName,
&FindData);
if (hFile == INVALID_HANDLE_VALUE)
{
break;
}
FindClose(hFile);
// CloseHandle(hFile);
#else
ofstruct.cBytes = sizeof(ofstruct);
ghLogFile = OpenFile(szFileName,
&ofstruct,
OF_EXIST);
if (ghLogFile == HFILE_ERROR)
{
break;
}
_lclose(ghLogFile);
#endif
i++;
}
#ifdef WIN32
DBGOUT((3, "log file name is %s", szFileName));
ghLogFile = CreateFile(szFileName,
GENERIC_WRITE,
FILE_SHARE_READ, //0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (ghLogFile == INVALID_HANDLE_VALUE)
{
DBGOUT((3, "InitLogging failed CreateFile"));
return FALSE;
}
#else
lstrcpy(gszFileName, szFileName);
ofstruct.cBytes = sizeof(ofstruct);
ghLogFile = OpenFile(gszFileName,
&ofstruct,
OF_CREATE);
_lclose(ghLogFile);
/*
ofstruct.cBytes = sizeof(ofstruct);
DBGOUT((3, szFileName));
ghLogFile = OpenFile(szFileName,
&ofstruct,
OF_CREATE | OF_READWRITE);
if (ghLogFile == HFILE_ERROR)
{
DBGOUT((3, "InitLogging failed OpenFile"));
return FALSE;
}*/
#endif
#ifdef WIN32
InitializeCriticalSection(&gcsLogging);
InitializeCriticalSection(&gcsID);
gpBegin = NULL;
gpEnd = NULL;
#endif
DBGOUT((3, "Exiting InitLogging"));
return TRUE;
}
void WritePreHeader(DWORD dwID, DWORD dwType)
{
return;
/*
PREHEADER PreHeader;
PreHeader.dwKey = DWPREKEY;
PreHeader.dwTime = GetTickCount();
PreHeader.dwType = dwType;
CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
*/
}
void WriteStruct(DWORD dwID,
DWORD dwSize,
LPVOID lpBuf)
{
STRUCTHEADER StructHeader;
if (!lpBuf)
{
return;
}
StructHeader.dwKey = DWSTRCKEY;
StructHeader.dwSize = dwSize;
StructHeader.dwID = (DWORD)lpBuf;
CopyData(dwID, (LPVOID)&StructHeader, sizeof(StructHeader));
CopyData(dwID, lpBuf, (int)dwSize);
}
void WritePostStruct(DWORD dwID,
LONG lResult)
{
POSTSTRUCT PostStruct;
PostStruct.dwKey = DWPOSTKEY;
PostStruct.dwTime = GetTickCount();
PostStruct.lReturn = lResult;
CopyData(dwID, (LPVOID)&PostStruct, sizeof(PostStruct));
}
void WriteLineMsgStruct(DWORD dwID,
HTAPILINE htLine,
HTAPICALL htCall,
DWORD dwMsg,
DWORD dw1,
DWORD dw2,
DWORD dw3)
{
LINEMSGSTRUCT LineMsgStruct;
PREHEADER PreHeader;
PreHeader.dwKey = DWPREKEY;
PreHeader.dwTime = GetTickCount();
PreHeader.dwType = LINEMSG;
CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
LineMsgStruct.dwMsg = dwMsg;
LineMsgStruct.htLine = htLine;
LineMsgStruct.htCall = htCall;
LineMsgStruct.dw1 = dw1;
LineMsgStruct.dw2 = dw2;
LineMsgStruct.dw3 = dw3;
CopyData(dwID, (LPVOID)&LineMsgStruct, sizeof(LineMsgStruct));
}
void WritePhoneMsgStruct(DWORD dwID,
HTAPIPHONE htPhone,
DWORD dwMsg,
DWORD dw1,
DWORD dw2,
DWORD dw3)
{
PHONEMSGSTRUCT PhoneMsgStruct;
PREHEADER PreHeader;
PreHeader.dwKey = DWPREKEY;
PreHeader.dwTime = GetTickCount();
PreHeader.dwType = PHONEMSG;
CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
PhoneMsgStruct.dwMsg = dwMsg;
PhoneMsgStruct.htPhone = htPhone;
PhoneMsgStruct.dw1 = dw1;
PhoneMsgStruct.dw2 = dw2;
PhoneMsgStruct.dw3 = dw3;
CopyData(dwID, (LPVOID)&PhoneMsgStruct, sizeof(PhoneMsgStruct));
}
void WriteAsyncStruct(DWORD dwID,
DWORD dwRequestID,
LONG lResult)
{
ASYNCSTRUCT AsyncStruct;
PREHEADER PreHeader;
PreHeader.dwKey = DWPREKEY;
PreHeader.dwTime = GetTickCount();
PreHeader.dwType = ASYNCMSG;
CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
AsyncStruct.dwRequestID = dwRequestID;
AsyncStruct.lResult = lResult;
CopyData(dwID, (LPVOID)&AsyncStruct, sizeof(AsyncStruct));
}
void WriteLogStruct1(DWORD dwID,
DWORD dwSPFUNC,
DWORD dwParam1)
{
LOGSPFUNC1 LogStruct;
PREHEADER PreHeader;
PreHeader.dwKey = DWPREKEY;
PreHeader.dwTime = GetTickCount();
PreHeader.dwType = SPFUNC1;
CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
LogStruct.dwSPFUNC = dwSPFUNC;
LogStruct.dwParam1 = dwParam1;
CopyData(dwID, (LPVOID)&LogStruct, sizeof(LogStruct));
}
void WriteLogStruct2(DWORD dwID,
DWORD dwSPFUNC,
DWORD dwParam1,
DWORD dwParam2)
{
LOGSPFUNC2 LogStruct;
PREHEADER PreHeader;
PreHeader.dwKey = DWPREKEY;
PreHeader.dwTime = GetTickCount();
PreHeader.dwType = SPFUNC2;
CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
LogStruct.dwSPFUNC = dwSPFUNC;
LogStruct.dwParam1 = dwParam1;
LogStruct.dwParam2 = dwParam2;
CopyData(dwID, (LPVOID)&LogStruct, sizeof(LogStruct));
}
void WriteLogStruct3(DWORD dwID,
DWORD dwSPFUNC,
DWORD dwParam1,
DWORD dwParam2,
DWORD dwParam3)
{
LOGSPFUNC3 LogStruct;
PREHEADER PreHeader;
PreHeader.dwKey = DWPREKEY;
PreHeader.dwTime = GetTickCount();
PreHeader.dwType = SPFUNC3;
CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
LogStruct.dwSPFUNC = dwSPFUNC;
LogStruct.dwParam1 = dwParam1;
LogStruct.dwParam2 = dwParam2;
LogStruct.dwParam3 = dwParam3;
CopyData(dwID, (LPVOID)&LogStruct, sizeof(LogStruct));
}
void WriteLogStruct4(DWORD dwID,
DWORD dwSPFUNC,
DWORD dwParam1,
DWORD dwParam2,
DWORD dwParam3,
DWORD dwParam4)
{
LOGSPFUNC4 LogStruct;
PREHEADER PreHeader;
PreHeader.dwKey = DWPREKEY;
PreHeader.dwTime = GetTickCount();
PreHeader.dwType = SPFUNC4;
CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
LogStruct.dwSPFUNC = dwSPFUNC;
LogStruct.dwParam1 = dwParam1;
LogStruct.dwParam2 = dwParam2;
LogStruct.dwParam3 = dwParam3;
LogStruct.dwParam4 = dwParam4;
CopyData(dwID, (LPVOID)&LogStruct, sizeof(LogStruct));
}
void WriteLogStruct5(DWORD dwID,
DWORD dwSPFUNC,
DWORD dwParam1,
DWORD dwParam2,
DWORD dwParam3,
DWORD dwParam4,
DWORD dwParam5)
{
LOGSPFUNC5 LogStruct;
PREHEADER PreHeader;
PreHeader.dwKey = DWPREKEY;
PreHeader.dwTime = GetTickCount();
PreHeader.dwType = SPFUNC5;
CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
LogStruct.dwSPFUNC = dwSPFUNC;
LogStruct.dwParam1 = dwParam1;
LogStruct.dwParam2 = dwParam2;
LogStruct.dwParam3 = dwParam3;
LogStruct.dwParam4 = dwParam4;
LogStruct.dwParam5 = dwParam5;
CopyData(dwID, (LPVOID)&LogStruct, sizeof(LogStruct));
}
void WriteLogStruct6(DWORD dwID,
DWORD dwSPFUNC,
DWORD dwParam1,
DWORD dwParam2,
DWORD dwParam3,
DWORD dwParam4,
DWORD dwParam5,
DWORD dwParam6)
{
LOGSPFUNC6 LogStruct;
PREHEADER PreHeader;
PreHeader.dwKey = DWPREKEY;
PreHeader.dwTime = GetTickCount();
PreHeader.dwType = SPFUNC6;
CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
LogStruct.dwSPFUNC = dwSPFUNC;
LogStruct.dwParam1 = dwParam1;
LogStruct.dwParam2 = dwParam2;
LogStruct.dwParam3 = dwParam3;
LogStruct.dwParam4 = dwParam4;
LogStruct.dwParam5 = dwParam5;
LogStruct.dwParam6 = dwParam6;
CopyData(dwID, (LPVOID)&LogStruct, sizeof(LogStruct));
}
void WriteLogStruct7(DWORD dwID,
DWORD dwSPFUNC,
DWORD dwParam1,
DWORD dwParam2,
DWORD dwParam3,
DWORD dwParam4,
DWORD dwParam5,
DWORD dwParam6,
DWORD dwParam7)
{
LOGSPFUNC7 LogStruct;
PREHEADER PreHeader;
PreHeader.dwKey = DWPREKEY;
PreHeader.dwTime = GetTickCount();
PreHeader.dwType = SPFUNC7;
CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
LogStruct.dwSPFUNC = dwSPFUNC;
LogStruct.dwParam1 = dwParam1;
LogStruct.dwParam2 = dwParam2;
LogStruct.dwParam3 = dwParam3;
LogStruct.dwParam4 = dwParam4;
LogStruct.dwParam5 = dwParam5;
LogStruct.dwParam6 = dwParam6;
LogStruct.dwParam7 = dwParam7;
CopyData(dwID, (LPVOID)&LogStruct, sizeof(LogStruct));
}
void WriteLogStruct8(DWORD dwID,
DWORD dwSPFUNC,
DWORD dwParam1,
DWORD dwParam2,
DWORD dwParam3,
DWORD dwParam4,
DWORD dwParam5,
DWORD dwParam6,
DWORD dwParam7,
DWORD dwParam8)
{
LOGSPFUNC8 LogStruct;
PREHEADER PreHeader;
PreHeader.dwKey = DWPREKEY;
PreHeader.dwTime = GetTickCount();
PreHeader.dwType = SPFUNC8;
CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
LogStruct.dwSPFUNC = dwSPFUNC;
LogStruct.dwParam1 = dwParam1;
LogStruct.dwParam2 = dwParam2;
LogStruct.dwParam3 = dwParam3;
LogStruct.dwParam4 = dwParam4;
LogStruct.dwParam5 = dwParam5;
LogStruct.dwParam6 = dwParam6;
LogStruct.dwParam7 = dwParam7;
LogStruct.dwParam8 = dwParam8;
CopyData(dwID, (LPVOID)&LogStruct, sizeof(LogStruct));
}
void WriteLogStruct9(DWORD dwID,
DWORD dwSPFUNC,
DWORD dwParam1,
DWORD dwParam2,
DWORD dwParam3,
DWORD dwParam4,
DWORD dwParam5,
DWORD dwParam6,
DWORD dwParam7,
DWORD dwParam8,
DWORD dwParam9)
{
LOGSPFUNC9 LogStruct;
PREHEADER PreHeader;
PreHeader.dwKey = DWPREKEY;
PreHeader.dwTime = GetTickCount();
PreHeader.dwType = SPFUNC9;
CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
LogStruct.dwSPFUNC = dwSPFUNC;
LogStruct.dwParam1 = dwParam1;
LogStruct.dwParam2 = dwParam2;
LogStruct.dwParam3 = dwParam3;
LogStruct.dwParam4 = dwParam4;
LogStruct.dwParam5 = dwParam5;
LogStruct.dwParam6 = dwParam6;
LogStruct.dwParam7 = dwParam7;
LogStruct.dwParam8 = dwParam8;
LogStruct.dwParam9 = dwParam9;
CopyData(dwID, (LPVOID)&LogStruct, sizeof(LogStruct));
}
void WriteLogStruct12(DWORD dwID,
DWORD dwSPFUNC,
DWORD dwParam1,
DWORD dwParam2,
DWORD dwParam3,
DWORD dwParam4,
DWORD dwParam5,
DWORD dwParam6,
DWORD dwParam7,
DWORD dwParam8,
DWORD dwParam9,
DWORD dwParam10,
DWORD dwParam11,
DWORD dwParam12)
{
LOGSPFUNC12 LogStruct;
PREHEADER PreHeader;
PreHeader.dwKey = DWPREKEY;
PreHeader.dwTime = GetTickCount();
PreHeader.dwType = SPFUNC12;
CopyData(dwID, (LPVOID)&PreHeader, sizeof(PreHeader));
LogStruct.dwSPFUNC = dwSPFUNC;
LogStruct.dwParam1 = dwParam1;
LogStruct.dwParam2 = dwParam2;
LogStruct.dwParam3 = dwParam3;
LogStruct.dwParam4 = dwParam4;
LogStruct.dwParam5 = dwParam5;
LogStruct.dwParam6 = dwParam6;
LogStruct.dwParam7 = dwParam7;
LogStruct.dwParam8 = dwParam8;
LogStruct.dwParam9 = dwParam9;
LogStruct.dwParam10 = dwParam10;
LogStruct.dwParam11 = dwParam11;
LogStruct.dwParam12 = dwParam12;
CopyData(dwID, (LPVOID)&LogStruct, sizeof(LogStruct));
}
void CopyData(DWORD dwID, LPVOID lpBuf, int dwSize)
{
memcpy((LPBYTE)gChunks[dwID].pBuffer + gChunks[dwID].iStart,
lpBuf,
dwSize);
gChunks[dwID].iStart += dwSize;
}
BOOL GetChunkID(LPDWORD lpdwID)
{
#ifdef WIN32
EnterCriticalSection(&gcsID);
#endif
while (TRUE)
{
while (gdwID < MAXCHUNKS)
{
if (!gChunks[gdwID].bInUse)
{
goto gotid;
}
gdwID++;
}
gdwID = 0;
#ifdef WIN32
Sleep(0);
#endif
}
gotid:
*lpdwID = gdwID;
gChunks[gdwID].bInUse = TRUE;
#ifdef WIN32
LeaveCriticalSection(&gcsID);
#endif
return TRUE;
}
BOOL ReleaseID(DWORD dwID)
{
CopyIDToList(gChunks[dwID].iStart,
gChunks[dwID].pBuffer);
#ifdef WIN32
GlobalFree(gChunks[dwID].pBuffer);
#else
GlobalFreePtr(gChunks[dwID].pBuffer);
#endif
gChunks[dwID].iStart = 0;
gChunks[dwID].pBuffer = NULL;
gChunks[dwID].bInUse = FALSE;
return TRUE;
}
#ifdef WIN32
BOOL CopyIDToList(int iCount, LPVOID pBuffer)
{
PLOGSTRUCT pNew;
// if we have a lot of stuff to write, hold up here and
// wait until we've written a bunch
if (gdwTotalBlocks > MAXCHUNKS)
{
while (gdwTotalBlocks > MINCHUNKS)
{
Sleep(0);
}
}
pNew = (PLOGSTRUCT)GlobalAlloc(GPTR, iCount+sizeof(LOGSTRUCT));
pNew->pNext = NULL;
pNew->iSize = iCount;
memcpy(pNew+1, pBuffer, iCount);
EnterCriticalSection(&gcsLogging);
if (gpBegin == NULL)
{
gpBegin = pNew;
}
else
{
gpEnd->pNext = pNew;
}
gpEnd = pNew;
LeaveCriticalSection(&gcsLogging);
gdwTotalBlocks++;
return TRUE;
}
#else
BOOL CopyIDToList(int iCount, LPVOID pBuffer)
{
OFSTRUCT ofstruct;
ofstruct.cBytes = sizeof(ofstruct);
ghLogFile = OpenFile(gszFileName,
&ofstruct,
OF_READWRITE);
if (ghLogFile == HFILE_ERROR)
{
DBGOUT((3,"OpenFile failed"));
return FALSE;
}
_llseek(ghLogFile,
0,
2);
if (_lwrite(ghLogFile,
pBuffer,
iCount) == HFILE_ERROR)
{
DBGOUT((3, "_lwrite failed"));
}
_lclose(ghLogFile);
return TRUE;
}
#endif
BOOL AllocChunk(DWORD dwID, DWORD dwSize)
{
LPVOID pbuf;
// ok, i messed up and forgot to alloc for structheader.
// so i'll just add the size of 4 struct headers to each
// alloc. what a hack - o - rama
dwSize += 4*sizeof(STRUCTHEADER);
#ifdef WIN32
pbuf = (LPVOID)GlobalAlloc(GPTR, dwSize);
#else
pbuf = (LPVOID)GlobalAllocPtr(GPTR, dwSize);
#endif
if (!pbuf)
{
gChunks[dwID].pBuffer = NULL;
return FALSE;
}
#ifdef WIN32
memset(pbuf, 0, dwSize);
#else
memset(pbuf, 0, (int)dwSize);
#endif
gChunks[dwID].pBuffer = pbuf;
gChunks[dwID].bInUse = TRUE;
gChunks[dwID].iStart = 0;
return TRUE;
}