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.

461 lines
13 KiB

  1. #include <iostream.h>
  2. #include <assert.h>
  3. #include <windows.h>
  4. #include "types.h"
  5. #include "array.hxx"
  6. extern bool g_fWriteToStdOut;
  7. //
  8. //
  9. //
  10. bool
  11. CompareBuffer(char* pBuff1, char* pBuff2, unsigned long nLen)
  12. {
  13. for ( unsigned long i=0; i<nLen; i++ )
  14. if (pBuff1[i] != pBuff2[i])
  15. return false;
  16. return true;
  17. }
  18. bool
  19. CompareBufferNoCase( char* pBuff1, char* pBuff2, unsigned long nLen)
  20. {
  21. // or ing with 0x20 always gives the lower case for ASCII characters.
  22. // this way we can compare case insensitive.
  23. for ( unsigned long i=0; i<nLen; i++ )
  24. if ( (pBuff1[i]|0x20) != (pBuff2[i]|0x20) )
  25. return false;
  26. return true;
  27. }
  28. //
  29. //
  30. //
  31. void
  32. WriteLine(HANDLE file, char* pBuff, int nLen)
  33. {
  34. DWORD dwSize;
  35. char szBuff[2] = {0x0d, 0x0a};
  36. if (-1 == nLen)
  37. {
  38. nLen = lstrlen( pBuff );
  39. }
  40. WriteFile(file, pBuff, nLen, &dwSize, NULL);
  41. WriteFile(file, &szBuff, 2, &dwSize, NULL);
  42. }
  43. //
  44. //
  45. //
  46. unsigned long
  47. FindEndOfLine( char* pBuff )
  48. {
  49. char* pWalk = pBuff;
  50. while ( *pWalk != 0x0d )
  51. pWalk++;
  52. return ((unsigned long)(pWalk-pBuff));
  53. }
  54. //
  55. //
  56. //
  57. bool
  58. GetLine(HANDLE file, char** ppTarget)
  59. {
  60. //buffer
  61. char* pchBuff;
  62. unsigned long ulBuffIdx;
  63. unsigned long ulBuffSize = SZ;
  64. // Read variables
  65. DWORD dwRead=0;
  66. BOOL bRes;
  67. //allocate the initial buffer
  68. pchBuff = new char[ulBuffSize];
  69. //if we are currently positioned at wherever the previous
  70. //operation left us, skip the carriage returns and
  71. //get to the real data.
  72. pchBuff[0] = 0x0d;
  73. while (( pchBuff[0] == 0x0d ) || ( pchBuff[0] == 0x0a ))
  74. {
  75. bRes = ReadFile( (HANDLE)file, pchBuff, 1, &dwRead, NULL);
  76. if ( !bRes || !dwRead )
  77. return false;
  78. }
  79. //get the buffer until you reach the terminating character.
  80. //the first character of the buffer is filled. ulBuffIdx always points
  81. //to the char. to be read.
  82. ulBuffIdx = 1;
  83. BOOL fContinue = true;
  84. while( fContinue )
  85. {
  86. bRes = ReadFile( (HANDLE)file, &pchBuff[ulBuffIdx], 1, &dwRead, NULL);
  87. if ( !bRes || !dwRead )
  88. return false;
  89. //was this the terminating character?
  90. if ( pchBuff[ulBuffIdx] == 0x0A )
  91. {
  92. fContinue = false;
  93. }
  94. ulBuffIdx++; //always point to the character to be read.
  95. //did we reach the end of the buffer? If so, enlarge buffer
  96. if ( 0 == (ulBuffIdx % SZ) )
  97. {
  98. //allocate new memory chunk
  99. char* pTmp = new char[ulBuffSize+SZ];
  100. //copy data
  101. memcpy( pTmp, pchBuff, ulBuffSize);
  102. //release old memory
  103. delete [] pchBuff;
  104. //make the new chunk the current one
  105. pchBuff = pTmp;
  106. ulBuffSize += SZ;
  107. }
  108. }
  109. pchBuff[ulBuffIdx-2] = 0;
  110. //if there is a receiving pointer and it is
  111. //initialized to NULL properly
  112. if ((ppTarget) && (*ppTarget==NULL))
  113. {
  114. *ppTarget = pchBuff;
  115. }
  116. else
  117. {
  118. //since there are no valid receivers of the buffer,
  119. //we can delete it.
  120. delete [] pchBuff;
  121. }
  122. return true;
  123. }
  124. //----------------------------------------------------------------------------
  125. // Function : GetBlockType
  126. // Description : Get a block of memory that is the first line
  127. // of a block, and determine the block type, by
  128. // checking the first characters on the line
  129. // Parameters :
  130. // char* : pointer to the buf. that contains the line
  131. //
  132. // Returns : Returns the type of the block ( enumeration BLOCK_TYPE)
  133. //----------------------------------------------------------------------------
  134. BLOCK_TYPE
  135. GetBlockType( char* pchData, char* pchTerm )
  136. {
  137. assert( pchData );
  138. assert( pchTerm );
  139. switch (*pchData)
  140. {
  141. case 'd':
  142. *pchTerm = '}'; //end of block
  143. return BLK_DISPINT;
  144. break;
  145. case 'i':
  146. *pchTerm = '}'; //end of block
  147. return BLK_INTERFACE;
  148. break;
  149. case 'c':
  150. *pchTerm = '}'; //end of block
  151. return BLK_COCLASS;
  152. break;
  153. case 't':
  154. *pchTerm = ';'; //end of type definition
  155. return BLK_TYPEDEF;
  156. break;
  157. case '[':
  158. *pchTerm = ']'; //end of attribute
  159. return BLK_ATTR;
  160. break;
  161. default:
  162. *pchTerm = 0x0a; //end of line
  163. return BLK_NONE;
  164. break;
  165. }
  166. }
  167. //
  168. //
  169. //
  170. bool
  171. GetBlock(HANDLE file, INDEX* pIdx, char** ppTarget = NULL, unsigned long* pulBlockBase = NULL )
  172. {
  173. char * pchBuff; //buffer
  174. unsigned long ulBuffIdx; //walking pointer
  175. unsigned long ulBuffBase; //end of the last memory chunk.
  176. unsigned long ulBlockBase; //beginning of the actual block,
  177. //after the funny characters are skipped
  178. unsigned long ulBuffSize = SZ+1; // the extra character is for the NULL termination.
  179. unsigned long ulLines = 0;
  180. BOOL fContinue = TRUE;
  181. //read variables
  182. DWORD dwRead=0;
  183. BOOL bRes;
  184. char chTerm;
  185. assert(pIdx);
  186. if ( ppTarget )
  187. *ppTarget = NULL; //reset the pointer to be returned.
  188. //allocate the initial buffer
  189. pchBuff = new char[ulBuffSize];
  190. ulBuffBase = ulBuffIdx = ulBlockBase = 0;
  191. //we are currently positioned at wherever the previous
  192. //operation left us. learn where we are and start to read.
  193. pIdx->ulStartPos = SetFilePointer( (HANDLE)file, 0, NULL, FILE_CURRENT);
  194. while( fContinue )
  195. {
  196. //read a block from the file.
  197. bRes = ReadFile( (HANDLE)file, &pchBuff[ulBuffIdx], SZ, &dwRead, NULL);
  198. //if there was a failure or we had reached the end of the file.
  199. if ( !bRes || !dwRead )
  200. return false;
  201. //skip the possible 0d 0a sequences at the beginning and process the rest of
  202. //the message.
  203. if ( ulBuffIdx== 0 )
  204. {
  205. while((pchBuff[ulBuffIdx] == 0x0D ) ||
  206. ( pchBuff[ulBuffIdx] == 0x0A ) ||
  207. ( pchBuff[ulBuffIdx] == 0x20 ))
  208. {
  209. ulBuffIdx++; //read position in the buffer
  210. ulBlockBase++; //increment the buffer base position.
  211. pIdx->ulStartPos++; //start position in the file.
  212. }
  213. //if we reached the end of file by doing this, return. There is nothing left.
  214. if (dwRead==ulBuffIdx)
  215. return false;
  216. //now we are pointing to the actual data, learn the terminating
  217. //character and terminate this loop.
  218. pIdx->blockType = GetBlockType(&pchBuff[ulBuffIdx], &chTerm);
  219. }
  220. //walk until you reach the terminating character or the end of the read buffer
  221. while ((ulBuffIdx<(ulBuffBase+dwRead)) && (pchBuff[ulBuffIdx] != chTerm))
  222. {
  223. //check for the 0x0A to determine the number of lines
  224. //the linefeed after the chTerm is found is taken care of
  225. //in the spin routine for the empty lines.
  226. if (pchBuff[ulBuffIdx] == 0x0A )
  227. ulLines++;
  228. ulBuffIdx++;
  229. }
  230. //did we reach the end of the buffer or found the chTerm character
  231. if (ulBuffIdx == ulBuffSize - 1)
  232. {
  233. char* pTmp = new char[ulBuffSize+SZ]; //allocate new memory chunk
  234. memcpy( pTmp, pchBuff, ulBuffSize); //copy data
  235. delete [] pchBuff; //release old memory
  236. pchBuff = pTmp; //make the new chunk the current one
  237. ulBuffSize += SZ; //adjust the buffer size
  238. ulBuffBase = ulBuffIdx; //reset the base to the current limit
  239. }
  240. else
  241. {
  242. //we found the terminating character.
  243. ulBuffIdx++; //always point to the character to be read next.
  244. break;
  245. }
  246. }
  247. // Subtract the block base, If there were 0d0a pairs, we incremented both
  248. // ulStartPos and ulBuffIdx, and doubled the effect of the skipping these
  249. // characters. Compensation is provided by -ulBlockBase ...
  250. pIdx->ulEndPos = pIdx->ulStartPos + ulBuffIdx - ulBlockBase;
  251. // If the terminating character was a line break, we don't want it to go
  252. // into the record as a part of this line
  253. if ( chTerm == 0x0a )
  254. {
  255. pIdx->ulEndPos -= 2;
  256. ulBuffIdx -= 2;
  257. }
  258. // Reset the pointer to the end of this block.
  259. SetFilePointer( (HANDLE)file, pIdx->ulEndPos, NULL, FILE_BEGIN);
  260. // Terminate the buffer, since the index always shows the next
  261. // position available, subtract 1 from the index.
  262. pchBuff[ulBuffIdx] = 0;
  263. // If there is a receiving pointer and it is
  264. // initialized to NULL properly
  265. if ((ppTarget) && (*ppTarget==NULL) && (pulBlockBase))
  266. {
  267. *ppTarget = pchBuff;
  268. *pulBlockBase = ulBlockBase;
  269. }
  270. else
  271. {
  272. // Since there are no valid receivers of the buffer,
  273. // we can delete it.
  274. delete [] pchBuff;
  275. }
  276. return true;
  277. }
  278. //
  279. // Compare two attribute blocks. Attribute blocks are placed before interface descriptions
  280. // and coclass descriptions.
  281. // dual --> breaker for both coclass and interface if added/removed
  282. // uuid(...) --> breaker for interfaces of all kinds if the contents of the uuid is changed
  283. //
  284. // Return Value:
  285. // The return value from this function 0 if there are no differences between these two blocks
  286. // otherwise an error code is returned.
  287. long
  288. CompareAttributeBlock( char * pRefBuf,
  289. CAutoArray<ATTRINFO>* pRefList,
  290. char * pCurBuf,
  291. CAutoArray<ATTRINFO>* pCurList)
  292. {
  293. char szDual[] = {"dual"};
  294. char szUuid[] = {"uuid"};
  295. char * pszAttr;
  296. ATTRINFO attrCur, attrRef;
  297. int i, j, k;
  298. long lErr;
  299. // For all of the attributes that are in the reference list, if the attribute is one of
  300. // the attributes that we care about, we will make sure that the current list contains
  301. // the same attribute.
  302. for ( i=0; i < pRefList->Size(); i++ )
  303. {
  304. pRefList->GetAt(i, &attrRef);
  305. if (attrRef.ulAttrLength == 4)
  306. {
  307. pszAttr = szDual;
  308. lErr = CHANGE_DUALATTRREMOVED;
  309. }
  310. else if (attrRef.ulAttrLength == 42)
  311. {
  312. pszAttr = szUuid;
  313. lErr = CHANGE_UUIDHASCHANGED;
  314. }
  315. else
  316. continue;
  317. assert(pszAttr);
  318. // is this attribute one of those that we want to check for?
  319. for (j=0; j<4; j++)
  320. if( pszAttr[j] != pRefBuf[attrRef.ulAttrStart+j])
  321. break;
  322. // We don't want to compare this attribute.
  323. if (j != 4)
  324. continue;
  325. // we care about this attribute. It MUST be in the current attribute block
  326. for (k=0; k < pCurList->Size(); k++)
  327. {
  328. pCurList->GetAt(k, &attrCur);
  329. if ((!attrCur.fUsed) &&
  330. (0 == memcmp( pRefBuf+attrRef.ulAttrStart,
  331. pCurBuf+attrCur.ulAttrStart,
  332. attrRef.ulAttrLength)))
  333. {
  334. // if the attribute is found, then mark the current list so we skip
  335. // over this one next time.
  336. attrCur.fUsed = true;
  337. pCurList->Set(k, attrCur);
  338. // shortcut...
  339. break;
  340. }
  341. }
  342. // if we did not find the same attribute, return the error code that is in lErr
  343. if (k == pCurList->Size())
  344. return lErr;
  345. }
  346. // check for things that are added to the current list,
  347. // but don't exist in the reference list. If something we check for is added, this is a breaker.
  348. for ( i=0; i < pCurList->Size(); i++)
  349. {
  350. pCurList->GetAt(i, &attrCur);
  351. if (!attrCur.fUsed)
  352. {
  353. // only check for "dual" here.
  354. pszAttr = szDual;
  355. for (j=0; j<4; j++)
  356. if( pszAttr[j] != pCurBuf[attrCur.ulAttrStart+j])
  357. break;
  358. if (j==4)
  359. return CHANGE_DUALATTRADDED;
  360. }
  361. }
  362. return 0;
  363. }
  364. void
  365. TokenizeAttributes( char* pBuf, unsigned long nCnt, CAutoArray<ATTRINFO>* pList )
  366. {
  367. unsigned long i,j;
  368. ATTRINFO attrInfo;
  369. attrInfo.ulAttrStart = 0;
  370. // the first attribute is always at 0
  371. for ( i=0, j=0; i<= nCnt; i++, j++ )
  372. {
  373. if ( ( pBuf[i] == ',' ) || (i==nCnt) )
  374. {
  375. attrInfo.ulAttrLength = i- attrInfo.ulAttrStart;
  376. attrInfo.fUsed = false;
  377. pList->Append( attrInfo );
  378. i += 2;
  379. attrInfo.ulAttrStart = i;
  380. }
  381. }
  382. }