diff -urN mac-3.99-u4-b5/ChangeLog.shntool mac-3.99-u4-b5-s4/ChangeLog.shntool
--- mac-3.99-u4-b5/ChangeLog.shntool	1969-12-31 19:00:00.000000000 -0500
+++ mac-3.99-u4-b5-s4/ChangeLog.shntool	2008-03-12 11:32:44.000000000 -0400
@@ -0,0 +1,16 @@
+version 3.99-u4-b5-s4
+  + include error reason with error code in mac.exe
+  + automatically recalculate quick verify checksum when compressing, if
+    necessary (e.g. piped encoding with foobar2000, or truncated WAVE file)
+    
+version 3.99-u4-b5-s3
+  + reenabled quick-verification of APE files (via new '-q' option)
+
+version 3.99-u4-b5-s2
+  + show above version in mac.exe help screen (sN = shntool revision N)
+  + added support for encoding WAVE data of unknown length (all files/pipes
+    are now treated as unknown length; this forces mac.exe to write a seek
+    table of maximum size regardless of input file size, adding ~30kb/file)
+
+version 3.99-u4-b5-s1
+  + added support for pipe encoding/decoding
diff -urN mac-3.99-u4-b5/src/Console/Console.cpp mac-3.99-u4-b5-s4/src/Console/Console.cpp
--- mac-3.99-u4-b5/src/Console/Console.cpp	2006-06-01 05:00:55.000000000 -0400
+++ mac-3.99-u4-b5-s4/src/Console/Console.cpp	2008-03-12 11:50:48.000000000 -0400
@@ -22,6 +22,21 @@
 // global variables
 TICK_COUNT_TYPE g_nInitialTickCount = 0;
 
+#ifdef SHNTOOL
+BOOL bQuickVerify = FALSE;
+
+typedef struct
+{
+    int nErrorNum;
+    char *sErrorString;
+} _ErrorDesc;
+
+_ErrorDesc ErrorList[][2] = {
+  ERROR_EXPLANATION
+  NULL
+};
+#endif
+
 /***************************************************************************************
 Displays the proper usage for MAC.exe
 ***************************************************************************************/
@@ -37,12 +52,18 @@
 	fprintf(pFile, "    Compress (insane): '-c5000'\n");
 	fprintf(pFile, "    Decompress: '-d'\n");
 	fprintf(pFile, "    Verify: '-v'\n");
+#ifdef SHNTOOL
+	fprintf(pFile, "    Quick verify: '-q'\n");
+#endif
 	fprintf(pFile, "    Convert: '-nXXXX'\n\n");
 
 	fprintf(pFile, "Examples:\n");
 	fprintf(pFile, "    Compress: mac.exe \"Metallica - One.wav\" \"Metallica - One.ape\" -c2000\n");
 	fprintf(pFile, "    Decompress: mac.exe \"Metallica - One.ape\" \"Metallica - One.wav\" -d\n");
 	fprintf(pFile, "    Verify: mac.exe \"Metallica - One.ape\" -v\n");
+#ifdef SHNTOOL
+	fprintf(pFile, "    Quick verify: mac.exe \"Metallica - One.ape\" -q\n");
+#endif
 	fprintf(pFile, "    (note: int filenames must be put inside of quotations)\n");
 }
 
@@ -65,6 +86,22 @@
 		dProgress * 100, dRemaining, dElapsed);
 }
 
+#ifdef SHNTOOL
+char *ErrorToString(int nErrNo)
+{
+    int i = 0;
+
+    while (ErrorList[i])
+    {
+        if (ErrorList[i]->nErrorNum == nErrNo)
+            return ErrorList[i]->sErrorString;
+        i++;
+    }
+
+    return "unknown error";
+}
+#endif
+
 /***************************************************************************************
 Main (the main function)
 ***************************************************************************************/
@@ -104,7 +141,11 @@
 	char cMode[256];
 	strcpy(cMode, argv[2]);
 
+#ifdef SHNTOOL
+	if (_strnicmp(cMode, "-v", 2) != 0 && _strnicmp(cMode, "-q", 2) != 0)
+#else
 	if (_strnicmp(cMode, "-v", 2) != 0)
+#endif
 	{
 		// verify is the only mode that doesn't use at least the third argument
 		if (argc < 4) 
@@ -124,7 +165,19 @@
 	else if (_strnicmp(cMode, "-d", 2) == 0)
 		nMode = DECOMPRESS_MODE;
 	else if (_strnicmp(cMode, "-v", 2) == 0)
+#ifdef SHNTOOL
+    {
+		nMode = VERIFY_MODE;
+        bQuickVerify = FALSE;
+    }
+	else if (_strnicmp(cMode, "-q", 2) == 0)
+    {
+		nMode = VERIFY_MODE;
+        bQuickVerify = TRUE;
+    }
+#else
 		nMode = VERIFY_MODE;
+#endif
 	else if (_strnicmp(cMode, "-n", 2) == 0)
 		nMode = CONVERT_MODE;
 
@@ -173,7 +226,11 @@
 	else if (nMode == VERIFY_MODE) 
 	{
 		fprintf(stderr, "Verifying...\n");
+#ifdef SHNTOOL
+		nRetVal = VerifyFileW(spInputFilename, &nPercentageDone, ProgressCallback, &nKillFlag, bQuickVerify);
+#else
 		nRetVal = VerifyFileW(spInputFilename, &nPercentageDone, ProgressCallback, &nKillFlag);
+#endif
 	}	
 	else if (nMode == CONVERT_MODE) 
 	{
@@ -184,7 +241,11 @@
 	if (nRetVal == ERROR_SUCCESS) 
 		fprintf(stderr, "\nSuccess...\n");
 	else 
+#ifdef SHNTOOL
+		fprintf(stderr, "\nError: %i (%s)\n", nRetVal, ErrorToString(nRetVal));
+#else
 		fprintf(stderr, "\nError: %i\n", nRetVal);
+#endif
 
 	return nRetVal;
 }
diff -urN mac-3.99-u4-b5/src/MACLib/APECompress.cpp mac-3.99-u4-b5-s4/src/MACLib/APECompress.cpp
--- mac-3.99-u4-b5/src/MACLib/APECompress.cpp	2006-06-01 05:00:58.000000000 -0400
+++ mac-3.99-u4-b5-s4/src/MACLib/APECompress.cpp	2008-03-12 11:26:59.000000000 -0400
@@ -132,10 +132,18 @@
     return ERROR_SUCCESS;
 } 
 
+#ifdef SHNTOOL
+int CAPECompress::Finish(unsigned char * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes, const void * pHeaderData, int nHeaderBytes)
+#else
 int CAPECompress::Finish(unsigned char * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes)
+#endif
 {
     RETURN_ON_ERROR(ProcessBuffer(TRUE))
+#ifdef SHNTOOL
+    return m_spAPECompressCreate->Finish(pTerminatingData, nTerminatingBytes, nWAVTerminatingBytes, pHeaderData, nHeaderBytes);
+#else
     return m_spAPECompressCreate->Finish(pTerminatingData, nTerminatingBytes, nWAVTerminatingBytes);
+#endif
 }
 
 int CAPECompress::Kill()
@@ -224,10 +232,20 @@
         // get data
         int nBlocksAdded = 0;
         int nRetVal = pInputSource->GetData(pBuffer, nBlocksToAdd, &nBlocksAdded);
+
+#ifdef SHNTOOL
+        nBytesRead = (nBlocksAdded * m_wfeInput.nBlockAlign);
+        if (nRetVal != 0)
+        {
+            UnlockBuffer(nBytesRead, TRUE);
+            return ERROR_IO_READ;
+        }
+#else
         if (nRetVal != 0)
             return ERROR_IO_READ;
         else
             nBytesRead = (nBlocksAdded * m_wfeInput.nBlockAlign);
+#endif
         
         // store the bytes read
         if (pBytesAdded)
@@ -243,4 +261,3 @@
     
     return ERROR_SUCCESS;
 }
-
diff -urN mac-3.99-u4-b5/src/MACLib/APECompress.h mac-3.99-u4-b5-s4/src/MACLib/APECompress.h
--- mac-3.99-u4-b5/src/MACLib/APECompress.h	2006-06-01 05:00:57.000000000 -0400
+++ mac-3.99-u4-b5-s4/src/MACLib/APECompress.h	2008-03-12 11:26:32.000000000 -0400
@@ -32,7 +32,11 @@
     int AddDataFromInputSource(CInputSource * pInputSource, int nMaxBytes = -1, int * pBytesAdded = NULL);
     
     // finish / kill
+#ifdef SHNTOOL
+    int Finish(unsigned char * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes, const void * pHeaderData, int nHeaderBytes);
+#else
     int Finish(unsigned char * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes);
+#endif
     int Kill();
     
 private:
diff -urN mac-3.99-u4-b5/src/MACLib/APECompressCreate.cpp mac-3.99-u4-b5-s4/src/MACLib/APECompressCreate.cpp
--- mac-3.99-u4-b5/src/MACLib/APECompressCreate.cpp	2006-06-01 05:00:57.000000000 -0400
+++ mac-3.99-u4-b5-s4/src/MACLib/APECompressCreate.cpp	2008-03-12 11:25:54.000000000 -0400
@@ -91,14 +91,23 @@
     return nRetVal;
 }
 
+#ifdef SHNTOOL
+int CAPECompressCreate::Finish(const void * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes, const void * pHeaderData, int nHeaderBytes)
+#else
 int CAPECompressCreate::Finish(const void * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes)
+#endif
 {
     // clear the bit array
     RETURN_ON_ERROR(m_spAPECompressCore->GetBitArray()->OutputBitArray(TRUE));
     
     // finalize the file
+#ifdef SHNTOOL
+    RETURN_ON_ERROR(FinalizeFile(m_spIO, m_nFrameIndex, m_nLastFrameBlocks, 
+        pTerminatingData, nTerminatingBytes, nWAVTerminatingBytes, m_spAPECompressCore->GetPeakLevel(), pHeaderData, nHeaderBytes));
+#else
     RETURN_ON_ERROR(FinalizeFile(m_spIO, m_nFrameIndex, m_nLastFrameBlocks, 
         pTerminatingData, nTerminatingBytes, nWAVTerminatingBytes, m_spAPECompressCore->GetPeakLevel()));
+#endif
     
     return ERROR_SUCCESS;
 }
@@ -167,8 +176,22 @@
     return ERROR_SUCCESS;
 }
 
+#ifdef SHNTOOL
+void ULONG_TO_UCHAR_LE(unsigned char * buf,unsigned long num)
+/* converts an unsigned long to 4 bytes stored in little-endian format */
+{
+  buf[0] = (unsigned char)(num);
+  buf[1] = (unsigned char)(num >> 8);
+  buf[2] = (unsigned char)(num >> 16);
+  buf[3] = (unsigned char)(num >> 24);
+}
+#endif
 
+#ifdef SHNTOOL
+int CAPECompressCreate::FinalizeFile(CIO * pIO, int nNumberOfFrames, int nFinalFrameBlocks, const void * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes, int nPeakLevel, const void * pHeaderData, int nHeaderBytes)
+#else
 int CAPECompressCreate::FinalizeFile(CIO * pIO, int nNumberOfFrames, int nFinalFrameBlocks, const void * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes, int nPeakLevel)
+#endif
 {
     // store the tail position
     int nTailPosition = pIO->GetPosition();
@@ -203,7 +226,7 @@
     // update the header
     APEHeader.nFinalFrameBlocks = nFinalFrameBlocks;
     APEHeader.nTotalFrames = nNumberOfFrames;
-    
+
     // update the descriptor
     APEDescriptor.nAPEFrameDataBytes = nTailPosition - (APEDescriptor.nDescriptorBytes + APEDescriptor.nHeaderBytes + APEDescriptor.nSeekTableBytes + APEDescriptor.nHeaderDataBytes);
     APEDescriptor.nAPEFrameDataBytesHigh = 0;
@@ -239,6 +262,54 @@
 	m_spSeekTable[i] = swap_int32(m_spSeekTable[i]);
     }
 #endif
-    
+
+#ifdef SHNTOOL
+    char *p;
+    int i;
+    uint32 nDataSize;
+    bool bHasWaveHeader = ((pHeaderData != NULL) && (nHeaderBytes > 0) && (nHeaderBytes != CREATE_WAV_HEADER_ON_DECOMPRESSION));
+
+    // rewrite the WAVE header with known, correct values
+    if (bHasWaveHeader)
+    {
+        CSmartPtr<unsigned char> spOldHeader;
+        spOldHeader.Assign(new unsigned char [nHeaderBytes], TRUE);
+        memcpy(spOldHeader,pHeaderData,nHeaderBytes);
+
+        nDataSize = (((nNumberOfFrames - 1) * m_nSamplesPerFrame + nFinalFrameBlocks) * m_wfeInput.nBlockAlign);
+        for (i = 0; i < nHeaderBytes; i++)
+        {
+            if ((p = strstr((const char *)pHeaderData+i,"RIFF"))) {
+                ULONG_TO_UCHAR_LE((unsigned char *)p+4,nDataSize + nHeaderBytes - 8);
+                break;
+            }
+        }
+        for (i = 0; i < nHeaderBytes; i++)
+        {
+            if ((p = strstr((const char *)pHeaderData+i,"data"))) {
+                ULONG_TO_UCHAR_LE((unsigned char *)p+4,nDataSize);
+                break;
+            }
+        }
+
+        if (pIO->Write((void *) pHeaderData, nHeaderBytes, &nBytesWritten) != 0) { return ERROR_IO_WRITE; }
+
+        if (memcmp(spOldHeader,pHeaderData,nHeaderBytes))
+        {
+            swap_ape_descriptor(&APEDescriptor);
+
+            GetChecksum(pIO,&APEDescriptor,0,APEDescriptor.cFileMD5);
+
+            swap_ape_descriptor(&APEDescriptor);
+
+            if (pIO->Seek(0, FILE_BEGIN) != ERROR_SUCCESS) { return ERROR_IO_WRITE; }
+
+            if (pIO->Write(&APEDescriptor, sizeof(APEDescriptor), &nBytesWritten) != 0) { return ERROR_IO_WRITE; }
+        }
+
+        spOldHeader.Delete();
+    }
+#endif
+
     return ERROR_SUCCESS;
 }
diff -urN mac-3.99-u4-b5/src/MACLib/APECompressCreate.h mac-3.99-u4-b5-s4/src/MACLib/APECompressCreate.h
--- mac-3.99-u4-b5/src/MACLib/APECompressCreate.h	2006-06-01 05:00:58.000000000 -0400
+++ mac-3.99-u4-b5-s4/src/MACLib/APECompressCreate.h	2008-03-12 11:24:53.000000000 -0400
@@ -12,7 +12,11 @@
     ~CAPECompressCreate();
     
     int InitializeFile(CIO * pIO, const WAVEFORMATEX * pwfeInput, int nMaxFrames, int nCompressionLevel, const void * pHeaderData, int nHeaderBytes);
+#ifdef SHNTOOL
+    int FinalizeFile(CIO * pIO, int nNumberOfFrames, int nFinalFrameBlocks, const void * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes, int nPeakLevel, const void * pHeaderData, int nHeaderBytes);
+#else
     int FinalizeFile(CIO * pIO, int nNumberOfFrames, int nFinalFrameBlocks, const void * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes, int nPeakLevel);
+#endif
     
     int SetSeekByte(int nFrame, int nByteOffset);
 
@@ -21,7 +25,11 @@
     int GetFullFrameBytes();
     int EncodeFrame(const void * pInputData, int nInputBytes);
 
+#ifdef SHNTOOL
+    int Finish(const void * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes, const void * pHeaderData, int nHeaderBytes);
+#else
     int Finish(const void * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes);
+#endif
     
 
 private:
diff -urN mac-3.99-u4-b5/src/MACLib/APESimple.cpp mac-3.99-u4-b5-s4/src/MACLib/APESimple.cpp
--- mac-3.99-u4-b5/src/MACLib/APESimple.cpp	2006-06-01 05:00:58.000000000 -0400
+++ mac-3.99-u4-b5-s4/src/MACLib/APESimple.cpp	2008-03-12 11:28:10.000000000 -0400
@@ -44,18 +44,29 @@
 int __stdcall VerifyFile(const str_ansi * pInputFilename, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag, BOOL bQuickVerifyIfPossible)
 {
     CSmartPtr<str_utf16> spInputFile(GetUTF16FromANSI(pInputFilename), TRUE);
+#ifdef SHNTOOL
+    return VerifyFileW(spInputFile, pPercentageDone, ProgressCallback, pKillFlag, bQuickVerifyIfPossible);
+#else
     return VerifyFileW(spInputFile, pPercentageDone, ProgressCallback, pKillFlag, FALSE);
+#endif
 }
 
 /*****************************************************************************************
 Compress file
 *****************************************************************************************/
+#ifdef SHNTOOL
 int __stdcall CompressFileW(const str_utf16 * pInputFilename, const str_utf16 * pOutputFilename, int nCompressionLevel, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag)
+#else
+int __stdcall CompressFileW(const str_utf16 * pInputFilename, const str_utf16 * pOutputFilename, int nCompressionLevel, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag)
+#endif
 {
     // declare the variables
     int nFunctionRetVal = ERROR_SUCCESS;
     WAVEFORMATEX WaveFormatEx;
     CSmartPtr<CMACProgressHelper> spMACProgressHelper;
+#ifdef SHNTOOL
+    CSmartPtr<unsigned char> spHeader;
+#endif
     CSmartPtr<unsigned char> spBuffer;
     CSmartPtr<IAPECompress> spAPECompress;
     
@@ -78,13 +89,20 @@
         int nAudioBytes = nAudioBlocks * WaveFormatEx.nBlockAlign;
 
         // start the encoder
+#ifdef SHNTOOL
+        if (nHeaderBytes > 0) spHeader.Assign(new unsigned char [nHeaderBytes], TRUE);
+        THROW_ON_ERROR(spInputSource->GetHeaderData(spHeader.GetPtr()))
+        THROW_ON_ERROR(spAPECompress->Start(pOutputFilename, &WaveFormatEx, nAudioBytes,
+            nCompressionLevel, spHeader.GetPtr(), nHeaderBytes));
+#else
         if (nHeaderBytes > 0) spBuffer.Assign(new unsigned char [nHeaderBytes], TRUE);
         THROW_ON_ERROR(spInputSource->GetHeaderData(spBuffer.GetPtr()))
         THROW_ON_ERROR(spAPECompress->Start(pOutputFilename, &WaveFormatEx, nAudioBytes,
             nCompressionLevel, spBuffer.GetPtr(), nHeaderBytes));
     
         spBuffer.Delete();
-
+#endif
+    
         // set-up the progress
         spMACProgressHelper.Assign(new CMACProgressHelper(nAudioBytes, pPercentageDone, ProgressCallback, pKillFlag));
 
@@ -94,9 +112,30 @@
         while (nBytesLeft > 0)
         {
             int nBytesAdded = 0;
+#ifdef SHNTOOL
+            nRetVal = spAPECompress->AddDataFromInputSource(spInputSource.GetPtr(), nBytesLeft, &nBytesAdded);
+            switch (nRetVal) {
+                case 0:
+                    if (nBytesAdded == 0)
+                    {
+                        nBytesLeft = 0;
+                        nTerminatingBytes = 0;
+                    }
+                    nBytesLeft -= nBytesAdded;
+                    break;
+                case ERROR_IO_READ:
+                    nBytesLeft = 0;
+                    nTerminatingBytes = 0;
+                    break;
+                default:
+                    throw(nRetVal);
+                    break;
+            }
+#else
             THROW_ON_ERROR(spAPECompress->AddDataFromInputSource(spInputSource.GetPtr(), nBytesLeft, &nBytesAdded))
 
             nBytesLeft -= nBytesAdded;
+#endif
 
             // update the progress
             spMACProgressHelper->UpdateProgress(nAudioBytes - nBytesLeft);
@@ -109,7 +148,11 @@
         // finalize the file
         if (nTerminatingBytes > 0) spBuffer.Assign(new unsigned char [nTerminatingBytes], TRUE);
         THROW_ON_ERROR(spInputSource->GetTerminatingData(spBuffer.GetPtr()));
+#ifdef SHNTOOL
+        THROW_ON_ERROR(spAPECompress->Finish(spBuffer.GetPtr(), nTerminatingBytes, nTerminatingBytes, spHeader.GetPtr(), nHeaderBytes))
+#else
         THROW_ON_ERROR(spAPECompress->Finish(spBuffer.GetPtr(), nTerminatingBytes, nTerminatingBytes))
+#endif
 
         // update the progress to 100%
         spMACProgressHelper->UpdateProgressComplete();
@@ -131,6 +174,42 @@
     return nFunctionRetVal;
 }
 
+int __stdcall GetChecksum(CIO * pIO, APE_DESCRIPTOR * spAPEDescriptor, int nJunkHeaderBytes, unsigned char * cChecksum)
+{
+    unsigned int nBytesRead = 0;
+    CMD5Helper MD5Helper;
+
+    int nHead = nJunkHeaderBytes + spAPEDescriptor->nDescriptorBytes;
+    int nStart = nHead + spAPEDescriptor->nHeaderBytes + spAPEDescriptor->nSeekTableBytes;
+
+    pIO->Seek(nHead, FILE_BEGIN);
+    int nHeadBytes = nStart - nHead;
+    CSmartPtr<unsigned char> spHeadBuffer(new unsigned char [nHeadBytes], TRUE);
+    if ((pIO->Read(spHeadBuffer, nHeadBytes, &nBytesRead) != ERROR_SUCCESS) || (nHeadBytes != int(nBytesRead)))
+        return ERROR_IO_READ;
+    
+    int nBytesLeft = spAPEDescriptor->nHeaderDataBytes + spAPEDescriptor->nAPEFrameDataBytes + spAPEDescriptor->nTerminatingDataBytes;
+    CSmartPtr<unsigned char> spBuffer(new unsigned char [16384], TRUE);
+    nBytesRead = 1;
+    while ((nBytesLeft > 0) && (nBytesRead > 0))
+    {
+        int nBytesToRead = min(16384, nBytesLeft);
+        if (pIO->Read(spBuffer, nBytesToRead, &nBytesRead) != ERROR_SUCCESS)
+            return ERROR_IO_READ;
+
+        MD5Helper.AddData(spBuffer, nBytesRead);
+        nBytesLeft -= nBytesRead;
+    }
+
+    if (nBytesLeft != 0)
+        return ERROR_IO_READ;
+
+    MD5Helper.AddData(spHeadBuffer, nHeadBytes);
+
+    MD5Helper.GetResult(cChecksum);
+
+    return ERROR_SUCCESS;
+}
 
 /*****************************************************************************************
 Verify file
@@ -173,53 +252,25 @@
     {
         // variable declares
         int nFunctionRetVal = ERROR_SUCCESS;
-        unsigned int nBytesRead = 0;
         CSmartPtr<IAPEDecompress> spAPEDecompress;
 
         // run the quick verify
         try
         {
+            unsigned char cResult[16];
+
             spAPEDecompress.Assign(CreateIAPEDecompress(pInputFilename, &nFunctionRetVal));
             if (spAPEDecompress == NULL || nFunctionRetVal != ERROR_SUCCESS) throw(nFunctionRetVal);
 
-            CMD5Helper MD5Helper;
-            
-            CIO * pIO = GET_IO(spAPEDecompress);
             APE_FILE_INFO * pInfo = (APE_FILE_INFO *) spAPEDecompress->GetInfo(APE_INTERNAL_INFO);
-
             if ((pInfo->nVersion < 3980) || (pInfo->spAPEDescriptor == NULL))
-                throw(ERROR_UPSUPPORTED_FILE_VERSION);
-
-            int nHead = pInfo->nJunkHeaderBytes + pInfo->spAPEDescriptor->nDescriptorBytes;
-            int nStart = nHead + pInfo->spAPEDescriptor->nHeaderBytes + pInfo->spAPEDescriptor->nSeekTableBytes;
-
-            pIO->Seek(nHead, FILE_BEGIN);
-            int nHeadBytes = nStart - nHead;
-            CSmartPtr<unsigned char> spHeadBuffer(new unsigned char [nHeadBytes], TRUE);
-            if ((pIO->Read(spHeadBuffer, nHeadBytes, &nBytesRead) != ERROR_SUCCESS) || (nHeadBytes != int(nBytesRead)))
-                throw(ERROR_IO_READ);
-            
-            int nBytesLeft = pInfo->spAPEDescriptor->nHeaderDataBytes + pInfo->spAPEDescriptor->nAPEFrameDataBytes + pInfo->spAPEDescriptor->nTerminatingDataBytes;
-            CSmartPtr<unsigned char> spBuffer(new unsigned char [16384], TRUE);
-            nBytesRead = 1;
-            while ((nBytesLeft > 0) && (nBytesRead > 0))
-            {
-                int nBytesToRead = min(16384, nBytesLeft);
-                if (pIO->Read(spBuffer, nBytesToRead, &nBytesRead) != ERROR_SUCCESS)
-                    throw(ERROR_IO_READ);
+                return ERROR_UPSUPPORTED_FILE_VERSION;
 
-                MD5Helper.AddData(spBuffer, nBytesRead);
-                nBytesLeft -= nBytesRead;
-            }
+            CIO * pIO = GET_IO(spAPEDecompress);
 
-            if (nBytesLeft != 0)
+            if (GetChecksum(pIO,pInfo->spAPEDescriptor,pInfo->nJunkHeaderBytes,cResult) != ERROR_SUCCESS)
                 throw(ERROR_IO_READ);
 
-            MD5Helper.AddData(spHeadBuffer, nHeadBytes);
-
-            unsigned char cResult[16];
-            MD5Helper.GetResult(cResult);
-
             if (memcmp(cResult, pInfo->spAPEDescriptor->cFileMD5, 16) != 0)
                 nFunctionRetVal = ERROR_INVALID_CHECKSUM;
 
@@ -401,11 +452,19 @@
                     THROW_ON_ERROR(GET_IO(spAPEDecompress)->Read(&spTempBuffer[spAPEDecompress->GetInfo(APE_INFO_WAV_TERMINATING_BYTES)], nTagBytes, &nBytesRead))
                 }
 
+#ifdef SHNTOOL
+                THROW_ON_ERROR(spAPECompress->Finish(spTempBuffer, nTerminatingBytes, spAPEDecompress->GetInfo(APE_INFO_WAV_TERMINATING_BYTES), 0, 0));
+#else
                 THROW_ON_ERROR(spAPECompress->Finish(spTempBuffer, nTerminatingBytes, spAPEDecompress->GetInfo(APE_INFO_WAV_TERMINATING_BYTES)));
+#endif
             }
             else 
             {
+#ifdef SHNTOOL
+                THROW_ON_ERROR(spAPECompress->Finish(NULL, 0, 0, 0, 0));
+#else
                 THROW_ON_ERROR(spAPECompress->Finish(NULL, 0, 0));
+#endif
             }
         }
 
diff -urN mac-3.99-u4-b5/src/MACLib/MACLib.h mac-3.99-u4-b5-s4/src/MACLib/MACLib.h
--- mac-3.99-u4-b5/src/MACLib/MACLib.h	2006-06-01 05:00:58.000000000 -0400
+++ mac-3.99-u4-b5-s4/src/MACLib/MACLib.h	2008-03-12 11:24:18.000000000 -0400
@@ -394,7 +394,11 @@
     //        the number of bytes of the terminating data buffer that should be appended to a decoded
     //        WAV file (it's basically nTerminatingBytes - the bytes that make up the tag)
     //////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef SHNTOOL
+    virtual int Finish(unsigned char * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes, const void * pHeaderData, int nHeaderBytes) = 0;
+#else
     virtual int Finish(unsigned char * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes) = 0;
+#endif
 
     //////////////////////////////////////////////////////////////////////////////////////////////
     // Kill(...) - stops encoding and deletes the output file
@@ -436,11 +440,20 @@
     DLLEXPORT int __stdcall DecompressFile(const str_ansi * pInputFilename, const str_ansi * pOutputFilename, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag);
     DLLEXPORT int __stdcall ConvertFile(const str_ansi * pInputFilename, const str_ansi * pOutputFilename, int nCompressionLevel, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag);
     DLLEXPORT int __stdcall VerifyFile(const str_ansi * pInputFilename, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag); 
+    DLLEXPORT int __stdcall GetChecksum(CIO * pIO, APE_DESCRIPTOR * spAPEDescriptor, int nJunkHeaderBytes, unsigned char * cChecksum);
 
+#ifdef SHNTOOL
+    DLLEXPORT int __stdcall CompressFileW(const str_utf16 * pInputFilename, const str_utf16 * pOutputFilename, int nCompressionLevel = COMPRESSION_LEVEL_NORMAL, int * pPercentageDone = NULL, APE_PROGRESS_CALLBACK ProgressCallback = 0, int * pKillFlag = NULL);
+#else
     DLLEXPORT int __stdcall CompressFileW(const str_utf16 * pInputFilename, const str_utf16 * pOutputFilename, int nCompressionLevel = COMPRESSION_LEVEL_NORMAL, int * pPercentageDone = NULL, APE_PROGRESS_CALLBACK ProgressCallback = 0, int * pKillFlag = NULL);
+#endif
     DLLEXPORT int __stdcall DecompressFileW(const str_utf16 * pInputFilename, const str_utf16 * pOutputFilename, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag);
     DLLEXPORT int __stdcall ConvertFileW(const str_utf16 * pInputFilename, const str_utf16 * pOutputFilename, int nCompressionLevel, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag);
-    DLLEXPORT int __stdcall VerifyFileW(const str_utf16 * pInputFilename, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag, BOOL bQuickVerifyIfPossible = FALSE); 
+#ifdef SHNTOOL
+    DLLEXPORT int __stdcall VerifyFileW(const str_utf16 * pInputFilename, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag, BOOL bQuickVerifyIfPossible = TRUE);
+#else
+    DLLEXPORT int __stdcall VerifyFileW(const str_utf16 * pInputFilename, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag, BOOL bQuickVerifyIfPossible = FALSE);
+#endif
 
     // helper functions
     DLLEXPORT int __stdcall FillWaveFormatEx(WAVEFORMATEX * pWaveFormatEx, int nSampleRate = 44100, int nBitsPerSample = 16, int nChannels = 2);
diff -urN mac-3.99-u4-b5/src/MACLib/WAVInputSource.cpp mac-3.99-u4-b5-s4/src/MACLib/WAVInputSource.cpp
--- mac-3.99-u4-b5/src/MACLib/WAVInputSource.cpp	2006-06-01 05:00:57.000000000 -0400
+++ mac-3.99-u4-b5-s4/src/MACLib/WAVInputSource.cpp	2008-03-12 02:13:26.000000000 -0400
@@ -31,9 +31,25 @@
     uint32 nChunkBytes;  // the bytes of the chunk  
 };
 
+#ifdef SHNTOOL
+unsigned long UCHAR_TO_ULONG_LE(unsigned char * buf)
+/* converts 4 bytes stored in little-endian format to an unsigned long */
+{
+	return (unsigned long)((buf[3] << 24) + (buf[2] << 16) + (buf[1] << 8) + buf[0]);
+}
+ 
+unsigned short UCHAR_TO_USHORT_LE(unsigned char * buf)
+/* converts 2 bytes stored in little-endian format to an unsigned short */
+{
+	return (unsigned short)((buf[1] << 8) + buf[0]);
+}
+#endif
 
 CInputSource * CreateInputSource(const wchar_t * pSourceName, WAVEFORMATEX * pwfeSource, int * pTotalBlocks, int * pHeaderBytes, int * pTerminatingBytes, int * pErrorCode)
 { 
+#ifdef SHNTOOL
+	return new CWAVInputSource(pSourceName, pwfeSource, pTotalBlocks, pHeaderBytes, pTerminatingBytes, pErrorCode);
+#else
     // error check the parameters
     if ((pSourceName == NULL) || (wcslen(pSourceName) == 0))
     {
@@ -57,6 +73,7 @@
         if (pErrorCode) *pErrorCode = ERROR_INVALID_INPUT_FILE;
         return NULL;
     }
+#endif
 }
 
 CWAVInputSource::CWAVInputSource(CIO * pIO, WAVEFORMATEX * pwfeSource, int * pTotalBlocks, int * pHeaderBytes, int * pTerminatingBytes, int * pErrorCode)
@@ -139,6 +156,101 @@
 
 int CWAVInputSource::AnalyzeSource()
 {
+#ifdef SHNTOOL
+	unsigned char *p = m_sFullHeader, *priff = NULL;
+
+	// seek to the beginning (just in case)
+	m_spIO->Seek(0, FILE_BEGIN);
+
+	// get the file size
+	m_nFileBytes = m_spIO->GetSize();
+
+	// get the RIFF header
+	RETURN_ON_ERROR(ReadSafe(m_spIO, p, sizeof(RIFF_HEADER)))
+
+	// make sure the RIFF header is valid
+	if (!(p[0] == 'R' && p[1] == 'I' && p[2] == 'F' && p[3] == 'F'))
+		return ERROR_INVALID_INPUT_FILE;
+	p += sizeof(RIFF_HEADER);
+
+	// read the data type header
+	RETURN_ON_ERROR(ReadSafe(m_spIO, p, sizeof(DATA_TYPE_ID_HEADER)))
+
+	// make sure it's the right data type
+	if (!(p[0] == 'W' && p[1] == 'A' && p[2] == 'V' && p[3] == 'E'))
+		return ERROR_INVALID_INPUT_FILE;
+	p += sizeof(DATA_TYPE_ID_HEADER);
+
+	// find the 'fmt ' chunk
+	RETURN_ON_ERROR(ReadSafe(m_spIO, p, sizeof(RIFF_CHUNK_HEADER)))
+
+	while (!(p[0] == 'f' && p[1] == 'm' && p[2] == 't' && p[3] == ' ')) 
+	{
+		p += sizeof(RIFF_CHUNK_HEADER);
+
+		// move the file pointer to the end of this chunk
+		RETURN_ON_ERROR(ReadSafe(m_spIO, p, UCHAR_TO_ULONG_LE(p+4)))
+		p += UCHAR_TO_ULONG_LE(p+4);
+
+		// check again for the data chunk
+		RETURN_ON_ERROR(ReadSafe(m_spIO, p, sizeof(RIFF_CHUNK_HEADER)))
+    }
+
+	priff = p+4;
+	p += sizeof(RIFF_CHUNK_HEADER);
+
+	// read the format info
+	RETURN_ON_ERROR(ReadSafe(m_spIO, p, sizeof(WAV_FORMAT_HEADER)))
+
+	// error check the header to see if we support it
+	if (UCHAR_TO_USHORT_LE(p) != 1)
+		return ERROR_INVALID_INPUT_FILE;
+
+	// copy the format information to the WAVEFORMATEX passed in
+	FillWaveFormatEx(&m_wfeSource, UCHAR_TO_ULONG_LE(p+4), UCHAR_TO_USHORT_LE(p+14), UCHAR_TO_USHORT_LE(p+2));
+
+	p += sizeof(WAV_FORMAT_HEADER);
+
+	// skip over any extra data in the header
+	int nWAVFormatHeaderExtra = UCHAR_TO_ULONG_LE(priff) - sizeof(WAV_FORMAT_HEADER);
+	if (nWAVFormatHeaderExtra < 0)
+		return ERROR_INVALID_INPUT_FILE;
+	else {
+		RETURN_ON_ERROR(ReadSafe(m_spIO, p, nWAVFormatHeaderExtra))
+		p += nWAVFormatHeaderExtra;
+	}
+
+	// find the data chunk
+	RETURN_ON_ERROR(ReadSafe(m_spIO, p, sizeof(RIFF_CHUNK_HEADER)))
+
+	while (!(p[0] == 'd' && p[1] == 'a' && p[2] == 't' && p[3] == 'a')) 
+	{
+		p += sizeof(RIFF_CHUNK_HEADER);
+
+		// move the file pointer to the end of this chunk
+		RETURN_ON_ERROR(ReadSafe(m_spIO, p, UCHAR_TO_ULONG_LE(p+4)))
+		p += UCHAR_TO_ULONG_LE(p+4);
+
+		// check again for the data chunk
+		RETURN_ON_ERROR(ReadSafe(m_spIO, p, sizeof(RIFF_CHUNK_HEADER))) 
+	}
+
+	// we're at the data block
+	m_nDataBytes = UCHAR_TO_ULONG_LE(p+4);
+	if (m_nDataBytes < 0)
+		m_nDataBytes = m_nFileBytes - m_nHeaderBytes;
+
+	p += sizeof(RIFF_CHUNK_HEADER);
+
+	m_nHeaderBytes = p - m_sFullHeader;
+
+	// make sure the data bytes is a whole number of blocks
+	if ((m_nDataBytes % m_wfeSource.nBlockAlign) != 0)
+		return ERROR_INVALID_INPUT_FILE;
+
+	// calculate the terminating byts
+	m_nTerminatingBytes = 0;
+#else
     // seek to the beginning (just in case)
     m_spIO->Seek(0, FILE_BEGIN);
     
@@ -222,9 +334,10 @@
 
     // calculate the terminating byts
     m_nTerminatingBytes = m_nFileBytes - m_nDataBytes - m_nHeaderBytes;
-    
-    // we made it this far, everything must be cool
-    return ERROR_SUCCESS;
+#endif
+
+	// we made it this far, everything must be cool
+	return ERROR_SUCCESS;
 }
 
 int CWAVInputSource::GetData(unsigned char * pBuffer, int nBlocks, int * pBlocksRetrieved)
@@ -234,16 +347,35 @@
     int nBytes = (m_wfeSource.nBlockAlign * nBlocks);
     unsigned int nBytesRead = 0;
 
+#ifdef SHNTOOL
+    int nRetVal = m_spIO->Read(pBuffer, nBytes, &nBytesRead);
+#else
     if (m_spIO->Read(pBuffer, nBytes, &nBytesRead) != ERROR_SUCCESS)
         return ERROR_IO_READ;
+#endif
 
     if (pBlocksRetrieved) *pBlocksRetrieved = (nBytesRead / m_wfeSource.nBlockAlign);
 
+#ifdef SHNTOOL
+    if (nRetVal != ERROR_SUCCESS)
+        return ERROR_IO_READ;
+#endif
+
     return ERROR_SUCCESS;
 }
 
 int CWAVInputSource::GetHeaderData(unsigned char * pBuffer)
 {
+#ifdef SHNTOOL
+	int i;
+
+	if (!m_bIsValid) return ERROR_UNDEFINED;
+
+	for (i=0;i<m_nHeaderBytes;i++)
+		*(pBuffer + i) = *(m_sFullHeader + i);
+
+	return ERROR_SUCCESS;
+#else
     if (!m_bIsValid) return ERROR_UNDEFINED;
 
     int nRetVal = ERROR_SUCCESS;
@@ -266,6 +398,7 @@
     }
 
     return nRetVal;
+#endif
 }
 
 int CWAVInputSource::GetTerminatingData(unsigned char * pBuffer)
diff -urN mac-3.99-u4-b5/src/MACLib/WAVInputSource.h mac-3.99-u4-b5-s4/src/MACLib/WAVInputSource.h
--- mac-3.99-u4-b5/src/MACLib/WAVInputSource.h	2006-06-01 05:00:58.000000000 -0400
+++ mac-3.99-u4-b5-s4/src/MACLib/WAVInputSource.h	2008-03-12 02:05:21.000000000 -0400
@@ -3,6 +3,10 @@
 
 #include "IO.h"
 
+#ifdef SHNTOOL
+#define FULL_HEADER_SIZE 32768
+#endif
+
 /*************************************************************************************
 CInputSource - base input format class (allows multiple format support)
 *************************************************************************************/
@@ -54,6 +58,9 @@
     int m_nTerminatingBytes;
     int m_nFileBytes;
     BOOL m_bIsValid;
+#ifdef SHNTOOL
+    unsigned char m_sFullHeader[FULL_HEADER_SIZE];
+#endif
 };
 
 /*************************************************************************************
diff -urN mac-3.99-u4-b5/src/Shared/All.h mac-3.99-u4-b5-s4/src/Shared/All.h
--- mac-3.99-u4-b5/src/Shared/All.h	2006-06-01 05:00:56.000000000 -0400
+++ mac-3.99-u4-b5-s4/src/Shared/All.h	2008-03-12 02:05:36.000000000 -0400
@@ -110,7 +110,11 @@
 #define MAC_NAME                                        _T("Monkey's Audio 3.99")
 #define PLUGIN_NAME                                     "Monkey's Audio Player v3.99"
 #define MJ_PLUGIN_NAME                                  _T("APE Plugin (v3.99)")
+#ifdef SHNTOOL
+#define CONSOLE_NAME                                    "-- Monkey's Audio Console Front End (v 3.99-u4-b5-s4) (c) Matthew T. Ashland --\n"
+#else
 #define CONSOLE_NAME                                    "--- Monkey's Audio Console Front End (v 3.99) (c) Matthew T. Ashland ---\n"
+#endif
 #define PLUGIN_ABOUT                                    _T("Monkey's Audio Player v3.99\nCopyrighted (c) 2000-2004 by Matthew T. Ashland")
 #define MAC_DLL_INTERFACE_VERSION_NUMBER                1000
 
diff -urN mac-3.99-u4-b5/src/Shared/GlobalFunctions.cpp mac-3.99-u4-b5-s4/src/Shared/GlobalFunctions.cpp
--- mac-3.99-u4-b5/src/Shared/GlobalFunctions.cpp	2006-06-01 05:00:56.000000000 -0400
+++ mac-3.99-u4-b5-s4/src/Shared/GlobalFunctions.cpp	2008-03-12 02:07:22.000000000 -0400
@@ -66,7 +66,11 @@
 
 BOOL FileExists(wchar_t * pFilename)
 {    
+#ifdef SHNTOOL
+    if (0 == wcscmp(pFilename, L"-"))
+#else
     if (0 == wcscmp(pFilename, L"-")  ||  0 == wcscmp(pFilename, L"/dev/stdin"))
+#endif
         return TRUE;
 
 #ifdef _WIN32
diff -urN mac-3.99-u4-b5/src/Shared/StdLibFileIO.cpp mac-3.99-u4-b5-s4/src/Shared/StdLibFileIO.cpp
--- mac-3.99-u4-b5/src/Shared/StdLibFileIO.cpp	2006-06-01 05:00:56.000000000 -0400
+++ mac-3.99-u4-b5-s4/src/Shared/StdLibFileIO.cpp	2008-03-12 02:09:26.000000000 -0400
@@ -126,6 +126,13 @@
 
     char * wpName = GetANSIFromUTF16(pName);
 
+#ifdef SHNTOOL
+    if (0 == wcscmp(pName, L"-")) 
+    {
+        m_pFile = SETBINARY_IN(stdin);
+        m_bReadOnly = TRUE;                                                     // ReadOnly
+    }
+#else
     if (0 == wcscmp(pName, L"-") || 0 == wcscmp(pName, L"/dev/stdin")) 
     {
         m_pFile = SETBINARY_IN(stdin);
@@ -136,6 +143,7 @@
         m_pFile = SETBINARY_OUT(stdout);
         m_bReadOnly = FALSE;                                                    // WriteOnly
     }
+#endif
     else 
     {
         m_pFile = fopen(wpName, "r+b");
@@ -225,11 +233,19 @@
 {
     Close();
 
+#ifdef SHNTOOL
+    if (0 == wcscmp (pName, L"-")) 
+    {
+        m_pFile = SETBINARY_OUT(stdout);
+        m_bReadOnly = FALSE;                            // WriteOnly
+    }
+#else
     if (0 == wcscmp (pName, L"-") || 0 == wcscmp (pName, L"/dev/stdout")) 
     {
         m_pFile = SETBINARY_OUT(stdout);
         m_bReadOnly = FALSE;                            // WriteOnly
     }
+#endif
     else 
     {
 	char * wpName = GetANSIFromUTF16(pName);
diff -urN mac-3.99-u4-b5/src/Shared/WinFileIO.cpp mac-3.99-u4-b5-s4/src/Shared/WinFileIO.cpp
--- mac-3.99-u4-b5/src/Shared/WinFileIO.cpp	2006-06-01 05:00:56.000000000 -0400
+++ mac-3.99-u4-b5-s4/src/Shared/WinFileIO.cpp	2008-03-12 11:47:35.000000000 -0400
@@ -28,23 +28,36 @@
         CSmartPtr<char> spName(GetANSIFromUTF16(pName), TRUE);
     #endif
 
-    m_hFile = ::CreateFile(spName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-    if (m_hFile == INVALID_HANDLE_VALUE) 
-    {
-        m_hFile = ::CreateFile(spName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-        if (m_hFile == INVALID_HANDLE_VALUE) 
-        {
-            return -1;
-        }
-        else 
-        {
-            m_bReadOnly = TRUE;
-        }
-    }
-    else
-    {
-        m_bReadOnly = FALSE;
+#ifdef SHNTOOL
+	if ( 0 == wcscmp (pName, L"-") )
+	{
+		m_hFile = GetStdHandle (STD_INPUT_HANDLE);
+		m_bReadOnly = TRUE;
+		// ReadOnly
+	}
+	else
+	{
+#endif
+		m_hFile = ::CreateFile(spName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+		if (m_hFile == INVALID_HANDLE_VALUE)
+		{
+			m_hFile = ::CreateFile(spName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+			if (m_hFile == INVALID_HANDLE_VALUE)
+			{
+				return -1;
+			}
+			else
+			{
+				m_bReadOnly = TRUE;
+			}
+		}
+		else
+		{
+			m_bReadOnly = FALSE;
+		}
+#ifdef SHNTOOL
     }
+#endif
     
     wcscpy(m_cFileName, pName);
 
@@ -136,10 +149,23 @@
         CSmartPtr<char> spName(GetANSIFromUTF16(pName), TRUE);
     #endif
 
-    m_hFile = CreateFile(spName, GENERIC_WRITE | GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
-    if (m_hFile == INVALID_HANDLE_VALUE) { return -1; }
+#ifdef SHNTOOL
+	if ( 0 == wcscmp (pName, L"-") )
+	{
+		m_hFile = GetStdHandle (STD_OUTPUT_HANDLE);
+		m_bReadOnly = FALSE;
+		// ReadOnly
+	}
+	else
+	{
+#endif
+        m_hFile = CreateFile(spName, GENERIC_WRITE | GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+        if (m_hFile == INVALID_HANDLE_VALUE) { return -1; }
 
-    m_bReadOnly = FALSE;
+        m_bReadOnly = FALSE;
+#ifdef SHNTOOL
+    }
+#endif
     
     wcscpy(m_cFileName, pName);
 
