Source code of Windows XP (NT5)
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.

412 lines
9.8 KiB

  1. /******************************************************\
  2. This file implement the class that will parse an inf
  3. file.
  4. \******************************************************/
  5. #include "inf.h"
  6. #define MAX_INF_STR 8192*2
  7. #define LanguageSection "[LanguagesSupported]"
  8. #define LanguageSection1 "[LanguageID]"
  9. // Constructors and Destructors
  10. CInfFile::CInfFile()
  11. {
  12. m_lBufSize = -1;
  13. m_pfileStart = NULL;
  14. m_pfilePos = NULL;
  15. m_pfileLastPos = NULL;
  16. m_pfileLocalize = NULL;
  17. m_strLang = "0000000000";
  18. }
  19. CInfFile::CInfFile(LPCTSTR strFileName )
  20. {
  21. CFileException fe;
  22. Open(strFileName, CFile::modeRead | CFile::shareDenyWrite, &fe);
  23. }
  24. CInfFile::~CInfFile()
  25. {
  26. if(m_pfileStart)
  27. {
  28. m_file.Close();
  29. delete m_pfileStart;
  30. }
  31. }
  32. //////////////////////////////////////////////////////////////////////////////////////////
  33. // String functions
  34. BOOL CInfFile::ReadString(CString & str, BOOL bLastFilePos)
  35. {
  36. if(m_pfilePos==NULL)
  37. return FALSE;
  38. // search for the next /n in the file
  39. BYTE * pEnd = (BYTE*)memchr(m_pfilePos, '\n', (size_t)(m_lBufSize-(m_pfilePos-m_pfileStart)));
  40. if(!pEnd)
  41. return FALSE;
  42. if(bLastFilePos)
  43. m_pfileLastPos = m_pfilePos;
  44. int istrSize = (int)((pEnd-m_pfilePos) > MAX_INF_STR ? MAX_INF_STR : (pEnd-m_pfilePos));
  45. LPSTR pStr = (LPSTR)str.GetBuffer(istrSize);
  46. memcpy(pStr, m_pfilePos, istrSize-1);
  47. if(*(pEnd-1)=='\r')
  48. *(pStr+istrSize-1) = '\0';
  49. else
  50. *(pStr+istrSize) = '\0';
  51. m_pfilePos = pEnd+1;
  52. str.ReleaseBuffer();
  53. return TRUE;
  54. }
  55. BOOL CInfFile::ReadSectionString(CString & str, BOOL bRecursive)
  56. {
  57. CString strNext;
  58. BYTE * pPos = m_pfilePos;
  59. while(ReadString(strNext, !bRecursive))
  60. {
  61. if(!strNext.IsEmpty())
  62. {
  63. if(!bRecursive)
  64. str = "";
  65. // Check for a section
  66. if(strNext.Find('[')!=-1 && strNext.Find(']')!=-1)
  67. break;
  68. // remove spaces at the end of the string...
  69. strNext.TrimRight();
  70. //
  71. // Check for multiple line. Assume only last char can be a +
  72. //
  73. if(strNext.GetAt(strNext.GetLength()-1)=='+')
  74. {
  75. //
  76. // Remove the +
  77. //
  78. if(!str.IsEmpty())
  79. {
  80. strNext.TrimLeft();
  81. //strNext = strNext.Mid(1);
  82. }
  83. str += strNext.Left(strNext.GetLength()-1);
  84. ReadSectionString(str, TRUE);
  85. }
  86. else
  87. {
  88. if(!str.IsEmpty())
  89. {
  90. strNext.TrimLeft();
  91. }
  92. str += strNext;
  93. }
  94. //
  95. // Make sure the " are balanced with
  96. //
  97. int iPos;
  98. while((iPos = str.Find("\"\""))!=-1)
  99. {
  100. str = str.Left(iPos) + str.Mid(iPos+2);
  101. }
  102. return TRUE;
  103. }
  104. }
  105. m_pfilePos = pPos;
  106. return FALSE;
  107. }
  108. BOOL CInfFile::ReadSectionString(CInfLine & str)
  109. {
  110. CString strLine;
  111. if( !ReadSectionString(strLine) )
  112. return FALSE;
  113. str = strLine;
  114. return TRUE;
  115. }
  116. BOOL CInfFile::ReadTextSection(CString & str)
  117. {
  118. CString strSection;
  119. while(ReadSection(strSection))
  120. {
  121. if(strSection.Find(m_strLang)!=-1)
  122. {
  123. str = strSection;
  124. return TRUE;
  125. }
  126. }
  127. return FALSE;
  128. }
  129. BOOL CInfFile::ReadSection(CString & str)
  130. {
  131. if(m_pfilePos==NULL)
  132. return 0;
  133. BYTE * pOpen;
  134. BYTE * pClose;
  135. BYTE * pEnd;
  136. BOOL bFound = FALSE;
  137. while(!bFound)
  138. {
  139. // search for the next [ in the file
  140. if((pOpen = (BYTE*)memchr(m_pfilePos, '[', (size_t)(m_lBufSize-(m_pfilePos-m_pfileStart))))==NULL)
  141. return 0;
  142. if((pClose = (BYTE*)memchr(pOpen, ']', (size_t)(m_lBufSize-(pOpen-m_pfileStart))))==NULL)
  143. return 0;
  144. if((pEnd = (BYTE*)memchr(pOpen, '\n', (size_t)(m_lBufSize-(pOpen-m_pfileStart))))==NULL)
  145. return 0;
  146. // pClose must be before pEnd
  147. if((pClose>pEnd) || (*(pOpen-1)!='\n') || (*(pClose+1)!='\r'))
  148. m_pfilePos = pEnd+1;
  149. else bFound = TRUE;
  150. }
  151. int istrSize = (int)((pEnd-pOpen) > MAX_INF_STR ? MAX_INF_STR : (pEnd-pOpen));
  152. LPSTR pStr = (LPSTR)str.GetBuffer(istrSize);
  153. memcpy(pStr, pOpen, istrSize-1);
  154. if(*(pEnd-1)=='\r')
  155. *(pStr+istrSize-1) = '\0';
  156. else
  157. *(pStr+istrSize) = '\0';
  158. m_pfilePos = pEnd+1;
  159. str.ReleaseBuffer();
  160. return 1;
  161. }
  162. //////////////////////////////////////////////////////////////////////////////////////////
  163. // File functions
  164. LONG CInfFile::Seek( LONG lOff, UINT nFrom )
  165. {
  166. switch(nFrom)
  167. {
  168. case SEEK_SET:
  169. if(lOff<=m_lBufSize)
  170. m_pfilePos = m_pfileStart+lOff;
  171. else return -1;
  172. break;
  173. case SEEK_CUR:
  174. if(lOff<=m_lBufSize-(m_pfilePos-m_pfileStart))
  175. m_pfilePos = m_pfilePos+lOff;
  176. else return -1;
  177. break;
  178. case SEEK_END:
  179. if(lOff<=m_lBufSize)
  180. m_pfilePos = m_pfileStart+(m_lBufSize-lOff);
  181. else return -1;
  182. break;
  183. case SEEK_LOC:
  184. if(m_pfileLocalize)
  185. m_pfilePos = m_pfileLocalize;
  186. else return -1;
  187. break;
  188. default:
  189. break;
  190. }
  191. return ((LONG)(m_pfilePos-m_pfileStart));
  192. }
  193. BOOL CInfFile::Open( LPCTSTR lpszFileName, UINT nOpenFlags, CFileException* pError )
  194. {
  195. CFileException fe;
  196. if(!pError)
  197. pError = &fe;
  198. if(!m_file.Open(lpszFileName, nOpenFlags, pError))
  199. {
  200. AfxThrowFileException(pError->m_cause, pError->m_lOsError);
  201. return FALSE;
  202. }
  203. m_lBufSize = m_file.GetLength()+1;
  204. m_pfileStart = new BYTE[m_lBufSize];
  205. if(m_pfileStart==NULL)
  206. {
  207. AfxThrowMemoryException();
  208. return FALSE;
  209. }
  210. m_pfileLastPos = m_pfilePos = m_pfileStart;
  211. m_file.Read(m_pfileStart, m_lBufSize );
  212. *(m_pfilePos+m_lBufSize) = '\0';
  213. // find the localization section
  214. /*************************************************************************************\
  215. I'm assuming there are no other \0 in the buffer other than the one I've just placed.
  216. This is a fair assumption since this is a text file and not a binary file.
  217. I can then use strstr to get to the first occurrence, if any of the localization
  218. string section and place my current position buffer there.
  219. \*************************************************************************************/
  220. m_pfileLocalize = m_pfilePos = (BYTE*)strstr((LPSTR)m_pfileStart, LanguageSection);
  221. //
  222. // Check if we have the other language ID tag
  223. //
  224. if(!m_pfileLocalize)
  225. m_pfileLocalize = m_pfilePos = (BYTE*)strstr((LPSTR)m_pfileStart, LanguageSection1);
  226. // Get the language
  227. if(m_pfileLocalize)
  228. {
  229. BYTE * pStr = ((BYTE*)memchr(m_pfileLocalize, '\n', (size_t)(m_lBufSize-(m_pfileLocalize-m_pfileStart)))+1);
  230. BYTE * pEnd = ((BYTE*)memchr(pStr, '\n', (size_t)(m_lBufSize-(pStr-m_pfileStart)))-1);
  231. TRACE("CInfFile::Open =====> pStr = 0X%X, pEnd = 0X%X\n", pStr, pEnd);
  232. m_strLang = "";
  233. while( pStr<pEnd )
  234. {
  235. TRACE("CInfFile::Open =====> pStr = %c, 0X%X\n", *pStr, pStr);
  236. if( isalpha(*pStr++) )
  237. m_strLang += *(pStr-1);
  238. }
  239. }
  240. return TRUE;
  241. }
  242. //////////////////////////////////////////////////////////////////////////////////////////
  243. // Buffer functions
  244. const BYTE * CInfFile::GetBuffer(LONG lPos /* = 0 */)
  245. {
  246. if(lPos>m_lBufSize || lPos<0)
  247. return NULL;
  248. return( (const BYTE *)(m_pfileStart+lPos) );
  249. }
  250. /******************************************************************************************\
  251. CInfLine
  252. This class will parse the line and separate tag and text
  253. \******************************************************************************************/
  254. CInfLine::CInfLine()
  255. {
  256. m_strData = "";
  257. m_strTag = "";
  258. m_strText = "";
  259. m_bMultipleLine = FALSE;
  260. }
  261. CInfLine::CInfLine( LPCSTR lpStr )
  262. {
  263. m_bMultipleLine = FALSE;
  264. m_strData = lpStr;
  265. SetTag();
  266. SetText();
  267. }
  268. void CInfLine::SetTag()
  269. {
  270. m_strTag = "";
  271. // find the = in m_strData
  272. int iPos = m_strData.Find('=');
  273. if(iPos==-1)
  274. return;
  275. m_strTag = Clean(m_strData.Left( iPos ));
  276. m_strTag.TrimRight();
  277. m_strTag.TrimLeft();
  278. }
  279. void CInfLine::SetText()
  280. {
  281. m_strText = "";
  282. // find the = in m_strData
  283. int iPos = m_strData.Find('=');
  284. if(iPos==-1)
  285. return;
  286. m_strText = Clean(m_strData.Right( m_strData.GetLength()-iPos-1 ));
  287. m_strText = m_strData.Right( m_strData.GetLength()-iPos-1 );
  288. }
  289. void CInfLine::ChangeText(LPCSTR str)
  290. {
  291. m_strText = str;
  292. // find the = in m_strData
  293. int iPos = m_strData.Find('=');
  294. if(iPos==-1)
  295. return;
  296. m_strData = m_strData.Left( iPos+1 );
  297. m_strData += m_strText;
  298. }
  299. //////////////////////////////////////////////////////////////////////////////////////////
  300. // copy operators
  301. CInfLine& CInfLine::operator=(const CInfLine& infstringSrc)
  302. {
  303. m_strData = infstringSrc.m_strData;
  304. m_strTag = infstringSrc.m_strTag;
  305. m_strText = infstringSrc.m_strText;
  306. m_bMultipleLine = infstringSrc.m_bMultipleLine;
  307. return *this;
  308. }
  309. CInfLine& CInfLine::operator=(LPCTSTR lpsz)
  310. {
  311. m_bMultipleLine = FALSE;
  312. m_strData = lpsz;
  313. SetTag();
  314. SetText();
  315. return *this;
  316. }
  317. //////////////////////////////////////////////////////////////////////////////////////////
  318. // support functions
  319. CString CInfLine::Clean(LPCSTR lpstr)
  320. {
  321. CString str = lpstr;
  322. int iPos = str.Find('"');
  323. if(iPos!=-1)
  324. {
  325. str = str.Right( str.GetLength()-iPos-1 );
  326. iPos = str.ReverseFind('"');
  327. if(iPos!=-1)
  328. {
  329. str = str.Left( iPos );
  330. }
  331. }
  332. return str;
  333. }