#include #include #include #include "types.h" #include "array.hxx" extern bool g_fWriteToStdOut; // // // bool CompareBuffer(char* pBuff1, char* pBuff2, unsigned long nLen) { for ( unsigned long i=0; iulStartPos = SetFilePointer( (HANDLE)file, 0, NULL, FILE_CURRENT); while( fContinue ) { //read a block from the file. bRes = ReadFile( (HANDLE)file, &pchBuff[ulBuffIdx], SZ, &dwRead, NULL); //if there was a failure or we had reached the end of the file. if ( !bRes || !dwRead ) return false; //skip the possible 0d 0a sequences at the beginning and process the rest of //the message. if ( ulBuffIdx== 0 ) { while((pchBuff[ulBuffIdx] == 0x0D ) || ( pchBuff[ulBuffIdx] == 0x0A ) || ( pchBuff[ulBuffIdx] == 0x20 )) { ulBuffIdx++; //read position in the buffer ulBlockBase++; //increment the buffer base position. pIdx->ulStartPos++; //start position in the file. } //if we reached the end of file by doing this, return. There is nothing left. if (dwRead==ulBuffIdx) return false; //now we are pointing to the actual data, learn the terminating //character and terminate this loop. pIdx->blockType = GetBlockType(&pchBuff[ulBuffIdx], &chTerm); } //walk until you reach the terminating character or the end of the read buffer while ((ulBuffIdx<(ulBuffBase+dwRead)) && (pchBuff[ulBuffIdx] != chTerm)) { //check for the 0x0A to determine the number of lines //the linefeed after the chTerm is found is taken care of //in the spin routine for the empty lines. if (pchBuff[ulBuffIdx] == 0x0A ) ulLines++; ulBuffIdx++; } //did we reach the end of the buffer or found the chTerm character if (ulBuffIdx == ulBuffSize - 1) { char* pTmp = new char[ulBuffSize+SZ]; //allocate new memory chunk memcpy( pTmp, pchBuff, ulBuffSize); //copy data delete [] pchBuff; //release old memory pchBuff = pTmp; //make the new chunk the current one ulBuffSize += SZ; //adjust the buffer size ulBuffBase = ulBuffIdx; //reset the base to the current limit } else { //we found the terminating character. ulBuffIdx++; //always point to the character to be read next. break; } } // Subtract the block base, If there were 0d0a pairs, we incremented both // ulStartPos and ulBuffIdx, and doubled the effect of the skipping these // characters. Compensation is provided by -ulBlockBase ... pIdx->ulEndPos = pIdx->ulStartPos + ulBuffIdx - ulBlockBase; // If the terminating character was a line break, we don't want it to go // into the record as a part of this line if ( chTerm == 0x0a ) { pIdx->ulEndPos -= 2; ulBuffIdx -= 2; } // Reset the pointer to the end of this block. SetFilePointer( (HANDLE)file, pIdx->ulEndPos, NULL, FILE_BEGIN); // Terminate the buffer, since the index always shows the next // position available, subtract 1 from the index. pchBuff[ulBuffIdx] = 0; // If there is a receiving pointer and it is // initialized to NULL properly if ((ppTarget) && (*ppTarget==NULL) && (pulBlockBase)) { *ppTarget = pchBuff; *pulBlockBase = ulBlockBase; } else { // Since there are no valid receivers of the buffer, // we can delete it. delete [] pchBuff; } return true; } // // Compare two attribute blocks. Attribute blocks are placed before interface descriptions // and coclass descriptions. // dual --> breaker for both coclass and interface if added/removed // uuid(...) --> breaker for interfaces of all kinds if the contents of the uuid is changed // // Return Value: // The return value from this function 0 if there are no differences between these two blocks // otherwise an error code is returned. long CompareAttributeBlock( char * pRefBuf, CAutoArray* pRefList, char * pCurBuf, CAutoArray* pCurList) { char szDual[] = {"dual"}; char szUuid[] = {"uuid"}; char * pszAttr; ATTRINFO attrCur, attrRef; int i, j, k; long lErr; // For all of the attributes that are in the reference list, if the attribute is one of // the attributes that we care about, we will make sure that the current list contains // the same attribute. for ( i=0; i < pRefList->Size(); i++ ) { pRefList->GetAt(i, &attrRef); if (attrRef.ulAttrLength == 4) { pszAttr = szDual; lErr = CHANGE_DUALATTRREMOVED; } else if (attrRef.ulAttrLength == 42) { pszAttr = szUuid; lErr = CHANGE_UUIDHASCHANGED; } else continue; assert(pszAttr); // is this attribute one of those that we want to check for? for (j=0; j<4; j++) if( pszAttr[j] != pRefBuf[attrRef.ulAttrStart+j]) break; // We don't want to compare this attribute. if (j != 4) continue; // we care about this attribute. It MUST be in the current attribute block for (k=0; k < pCurList->Size(); k++) { pCurList->GetAt(k, &attrCur); if ((!attrCur.fUsed) && (0 == memcmp( pRefBuf+attrRef.ulAttrStart, pCurBuf+attrCur.ulAttrStart, attrRef.ulAttrLength))) { // if the attribute is found, then mark the current list so we skip // over this one next time. attrCur.fUsed = true; pCurList->Set(k, attrCur); // shortcut... break; } } // if we did not find the same attribute, return the error code that is in lErr if (k == pCurList->Size()) return lErr; } // check for things that are added to the current list, // but don't exist in the reference list. If something we check for is added, this is a breaker. for ( i=0; i < pCurList->Size(); i++) { pCurList->GetAt(i, &attrCur); if (!attrCur.fUsed) { // only check for "dual" here. pszAttr = szDual; for (j=0; j<4; j++) if( pszAttr[j] != pCurBuf[attrCur.ulAttrStart+j]) break; if (j==4) return CHANGE_DUALATTRADDED; } } return 0; } void TokenizeAttributes( char* pBuf, unsigned long nCnt, CAutoArray* pList ) { unsigned long i,j; ATTRINFO attrInfo; attrInfo.ulAttrStart = 0; // the first attribute is always at 0 for ( i=0, j=0; i<= nCnt; i++, j++ ) { if ( ( pBuf[i] == ',' ) || (i==nCnt) ) { attrInfo.ulAttrLength = i- attrInfo.ulAttrStart; attrInfo.fUsed = false; pList->Append( attrInfo ); i += 2; attrInfo.ulAttrStart = i; } } }