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.

674 lines
14 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. /*********************************************************************/
  4. /***** Common Library Component - Context Handling Routines 1 ********/
  5. /*********************************************************************/
  6. //
  7. // Global variables
  8. //
  9. PINFCONTEXT pContextTop = NULL;
  10. PINFCONTEXT pContextBottom = NULL;
  11. PINFPERMINFO pInfPermInfoHead = NULL;
  12. PINFPERMINFO pInfPermInfoTail = NULL;
  13. PPARSED_INF pParsedInfCache = NULL;
  14. INT ParsedInfCached = 0;
  15. //
  16. // Maximum number of parsed INFs that we keep in the cache
  17. //
  18. #define INF_CACHE_THRESHOLD 4
  19. /*
  20. ** Purpose:
  21. ** Pushes INF context onto stack
  22. **
  23. ** Arguments:
  24. ** Context to push
  25. **
  26. ** Returns:
  27. ** True if pushed.
  28. **
  29. **
  30. **************************************************************************/
  31. BOOL APIENTRY PushContext( PINFCONTEXT pContext )
  32. {
  33. SZ szHelpContext;
  34. BOOL fOkay = fTrue;
  35. //
  36. // Set the per-context information
  37. //
  38. if ( pContextTop ) {
  39. if ( pContextTop->szHelpFile ) {
  40. while ((pContext->szHelpFile = SzDupl(pContextTop->szHelpFile )) == (SZ)NULL) {
  41. if (!FHandleOOM(hWndShell)) {
  42. pContext->szHelpFile = NULL;
  43. return fFalse;
  44. }
  45. }
  46. } else {
  47. pContext->szHelpFile = NULL;
  48. }
  49. pContext->pseflHead = NULL;
  50. pContext->dwLowContext = pContextTop->dwLowContext;
  51. pContext->dwHighContext = pContextTop->dwHighContext;
  52. pContext->dwHelpIndex = pContextTop->dwHelpIndex;
  53. pContext->bHelpIsIndexed = pContextTop->bHelpIsIndexed;
  54. szHelpContext = SzFindSymbolValueInSymTab("HelpContext");
  55. } else {
  56. pContext->pseflHead = NULL;
  57. pContext->szHelpFile = NULL;
  58. pContext->dwLowContext = 0;
  59. pContext->dwHighContext = 0;
  60. pContext->dwHelpIndex = 0;
  61. pContext->bHelpIsIndexed = fFalse;
  62. szHelpContext = NULL;
  63. }
  64. //
  65. // Allocate the local symbol table
  66. //
  67. if ( !(pContext->SymTab = SymTabAlloc()) ) {
  68. if ( pContext->szHelpFile ) {
  69. SFree( pContext->szHelpFile );
  70. pContext->szHelpFile = NULL;
  71. }
  72. return fFalse;
  73. }
  74. //
  75. // Push context onto stack
  76. //
  77. pContext->pNext = pContextTop;
  78. pContextTop = pContext;
  79. if ( !pContextBottom ) {
  80. pContextBottom = pContextTop;
  81. }
  82. //
  83. // Add to the symbol table any per-context values.
  84. //
  85. if ( szHelpContext ) {
  86. while (!FAddSymbolValueToSymTab("HelpContext", szHelpContext)) {
  87. if (!FHandleOOM(hWndShell)) {
  88. PopContext();
  89. fOkay = fFalse;
  90. break;
  91. }
  92. }
  93. }
  94. while (!FAddSymbolValueToSymTab("$ShellCode", "0")) {
  95. if (!FHandleOOM(hWndShell)) {
  96. PopContext();
  97. fOkay = fFalse;
  98. break;
  99. }
  100. }
  101. return fOkay;
  102. }
  103. /*
  104. ** Purpose:
  105. ** Pops a context off the stack
  106. **
  107. ** Arguments:
  108. ** none
  109. **
  110. ** Returns:
  111. ** Popped context
  112. **
  113. **
  114. **************************************************************************/
  115. PINFCONTEXT APIENTRY PopContext( VOID )
  116. {
  117. PINFCONTEXT pContext = pContextTop;
  118. pContextTop = pContext->pNext;
  119. return pContext;
  120. }
  121. /*
  122. ** Purpose:
  123. ** Frees memory of a context
  124. **
  125. ** Arguments:
  126. ** Pointer to context
  127. **
  128. ** Returns:
  129. ** nothing
  130. **
  131. **
  132. **************************************************************************/
  133. VOID APIENTRY FreeContext( PINFCONTEXT pContext )
  134. {
  135. //
  136. // Free per-context information
  137. //
  138. if ( pContext->pseflHead ) {
  139. PSEFL psefl = pContext->pseflHead;
  140. PSEFL pseflNext;
  141. while ( psefl ) {
  142. pseflNext = psefl->pseflNext;
  143. FFreePsefl(psefl);
  144. psefl = pseflNext;
  145. }
  146. }
  147. if ( pContext->szHelpFile ) {
  148. SFree( pContext->szHelpFile );
  149. }
  150. if ( pContext->szShlScriptSection ) {
  151. SFree( pContext->szShlScriptSection );
  152. }
  153. //
  154. // Free local symbol table
  155. //
  156. FFreeSymTab( pContext->SymTab );
  157. //
  158. // Free context
  159. //
  160. SFree( pContext );
  161. }
  162. /*
  163. ** Purpose:
  164. ** Given an INF name, returns a pointer to the corresponding
  165. ** INF permanent information block. It creates a new permanent
  166. ** information block if none exists for the name provided.
  167. **
  168. ** Arguments:
  169. ** INF name
  170. **
  171. ** Returns:
  172. ** Pointer to INF permanent information block.
  173. **
  174. **
  175. **************************************************************************/
  176. PINFPERMINFO APIENTRY NameToInfPermInfo( SZ szName , BOOL AllocIfNotPresent)
  177. {
  178. PINFPERMINFO pInfo;
  179. if ( pInfPermInfoHead ) {
  180. pInfo = pInfPermInfoHead;
  181. while ( pInfo ) {
  182. if (CrcStringCompare( szName, pInfo->szName ) == crcEqual) {
  183. return pInfo;
  184. }
  185. pInfo = pInfo->pNext;
  186. }
  187. }
  188. if( AllocIfNotPresent ) {
  189. return AddInfPermInfo( szName );
  190. }
  191. else {
  192. return (PINFPERMINFO)NULL;
  193. }
  194. }
  195. /*
  196. ** Purpose:
  197. ** Adds a new INF permanent information block with the given INF
  198. ** name.
  199. **
  200. ** Arguments:
  201. ** INF name
  202. **
  203. ** Returns:
  204. ** Pointer to the INF permanent information block.
  205. **
  206. **
  207. **************************************************************************/
  208. PINFPERMINFO APIENTRY AddInfPermInfo( SZ szName )
  209. {
  210. PINFPERMINFO pInfo;
  211. SZ szInfName;
  212. if ( (pInfo = (PINFPERMINFO)SAlloc( sizeof( INFPERMINFO ) )) != NULL ) {
  213. if ( (szInfName = (SZ)SAlloc( lstrlen( szName ) + 1 )) != NULL) {
  214. strcpy( szInfName, szName );
  215. pInfo->szName = szInfName;
  216. pInfo->psdleHead = NULL;
  217. pInfo->psdleCur = NULL;
  218. pInfo->pclnHead = NULL;
  219. pInfo->ppclnTail = &(pInfo->pclnHead);
  220. pInfo->pNext = NULL;
  221. pInfo->pstfHead = NULL;
  222. if ( pInfPermInfoTail ) {
  223. pInfo->InfId = pInfPermInfoTail->InfId+1;
  224. pInfPermInfoTail->pNext = pInfo;
  225. pInfPermInfoTail = pInfo;
  226. } else {
  227. pInfo->InfId = 0;
  228. pInfPermInfoHead = pInfPermInfoTail = pInfo;
  229. }
  230. return pInfo;
  231. }
  232. SFree( pInfo);
  233. }
  234. return NULL;
  235. }
  236. /*
  237. ** Purpose:
  238. ** Given the path of an INF file, obtains the INF name (i.e. the
  239. ** name of the file without extension.
  240. **
  241. ** Arguments:
  242. ** Path to inf file
  243. ** Pointer to buffer where the INF name will be stored
  244. **
  245. ** Returns:
  246. ** TRUE if name obtained.
  247. **
  248. **
  249. **************************************************************************/
  250. BOOL APIENTRY PathToInfName( SZ szPath, SZ szName )
  251. {
  252. PCHAR p,r,q;
  253. p = r = szPath + strlen(szPath) - 1;
  254. while ( (p >= szPath) && (*p != '\\') && (*p != ':') ) {
  255. p--;
  256. }
  257. p++;
  258. q = p;
  259. while ( (q <= r) && (*q != '.') && (*q != '\0') ) {
  260. q++;
  261. }
  262. memcpy( szName, p, (size_t)(q-p) );
  263. szName[q-p] = '\0';
  264. SzStrUpper( szName );
  265. return fTrue;
  266. }
  267. /*
  268. ** Purpose:
  269. ** Determines what symbol table to use for a given symbol
  270. **
  271. ** Arguments:
  272. ** szSymbol: non-NULL, non-empty zero terminated string containing
  273. ** the value of the symbol to be searched for.
  274. **
  275. **
  276. **
  277. ** Syntax:
  278. **
  279. ** VarName := [![<Modifier>:]]Name
  280. **
  281. ** Modifier := L | G | P | S
  282. **
  283. **
  284. ** L = Local (this context)
  285. ** G = Global (top context)
  286. ** P = Parent (parent context)
  287. ** S = Static (INF temp. info)
  288. **
  289. **
  290. **
  291. ** Returns:
  292. ** Pointer to the context in which to look for the symbol
  293. **
  294. **
  295. **************************************************************************/
  296. PSYMTAB APIENTRY PInfSymTabFind( SZ szSymbol, SZ *szRealSymbol )
  297. {
  298. SZ p;
  299. PSYMTAB pSymTab = NULL;
  300. p = szSymbol;
  301. if ( p && *p != '\0' ) {
  302. if ( *p == '!' ) {
  303. p++;
  304. if ( (strlen(p) > 2) && (*(p+1) == ':') ) {
  305. switch ( *p ) {
  306. case 'G':
  307. case 'g':
  308. //
  309. // Global
  310. //
  311. pSymTab = pGlobalContext()->SymTab;
  312. *szRealSymbol = p+2;
  313. break;
  314. case 'L':
  315. case 'l':
  316. //
  317. // Local
  318. //
  319. pSymTab = pLocalContext()->SymTab;
  320. *szRealSymbol = p+2;
  321. break;
  322. case 'P':
  323. case 'p':
  324. //
  325. // Parent
  326. //
  327. pSymTab = pLocalContext()->pNext->SymTab;
  328. *szRealSymbol = p+2;
  329. break;
  330. case 'S':
  331. case 's':
  332. //
  333. // Static
  334. //
  335. pSymTab = pLocalContext()->pInfTempInfo->SymTab;
  336. *szRealSymbol = p+2;
  337. break;
  338. default:
  339. //
  340. // Invalid
  341. //
  342. pSymTab = NULL;
  343. *szRealSymbol = NULL;
  344. break;
  345. }
  346. } else {
  347. //
  348. // Global variable
  349. //
  350. pSymTab = pGlobalContext()->SymTab;
  351. *szRealSymbol = p;
  352. }
  353. } else {
  354. //
  355. // Local variable
  356. //
  357. pSymTab = pLocalContext()->SymTab;
  358. *szRealSymbol = p;
  359. }
  360. }
  361. return pSymTab;
  362. }
  363. PPARSED_INF
  364. APIENTRY
  365. ParsedInfAlloc(
  366. PINFPERMINFO pInfPermInfo
  367. )
  368. {
  369. PPARSED_INF pParsedInf = NULL;
  370. //
  371. // If the cache is not empty, see if this INF is already in
  372. // the cache.
  373. //
  374. if ( ParsedInfCached > 0 ) {
  375. pParsedInf = pParsedInfCache;
  376. while ( pParsedInf ) {
  377. if ( pParsedInf->pInfPermInfo == pInfPermInfo ) {
  378. //
  379. // Found the parsed INF in the cache.
  380. // Take it out of the cache.
  381. //
  382. if (pParsedInf->pPrev) {
  383. (pParsedInf->pPrev)->pNext = pParsedInf->pNext;
  384. }
  385. if (pParsedInf->pNext) {
  386. (pParsedInf->pNext)->pPrev = pParsedInf->pPrev;
  387. }
  388. if ( pParsedInfCache == pParsedInf ) {
  389. pParsedInfCache = pParsedInf->pNext;
  390. }
  391. pParsedInf->pPrev = NULL;
  392. pParsedInf->pNext = NULL;
  393. ParsedInfCached--;
  394. break;
  395. }
  396. pParsedInf = pParsedInf->pNext;
  397. }
  398. }
  399. //
  400. // If the parsed INF was not in the cache, we allocate space for a
  401. // new one.
  402. //
  403. if ( pParsedInf == NULL ) {
  404. if ( pParsedInf = (PPARSED_INF)SAlloc( sizeof( PARSED_INF ) ) ) {
  405. pParsedInf->pPrev = NULL;
  406. pParsedInf->pNext = NULL;
  407. pParsedInf->pInfPermInfo = pInfPermInfo;
  408. pParsedInf->MasterLineArray = NULL;
  409. pParsedInf->MasterLineCount = 0;
  410. pParsedInf->MasterFile = NULL;
  411. pParsedInf->MasterFileSize = 0;
  412. }
  413. }
  414. return pParsedInf;
  415. }
  416. extern
  417. BOOL
  418. APIENTRY
  419. FFreeParsedInf(
  420. PPARSED_INF pParsedInf
  421. )
  422. {
  423. PPARSED_INF pInf;
  424. //
  425. // We will put this Parsed INF in the cache. If the number of cached
  426. // INFs is above the threshold we will free the least recently used
  427. // one.
  428. //
  429. if (pParsedInfCache) {
  430. pParsedInfCache->pPrev = pParsedInf;
  431. }
  432. pParsedInf->pNext = pParsedInfCache;
  433. pParsedInfCache = pParsedInf;
  434. if ( ParsedInfCached++ >= INF_CACHE_THRESHOLD ) {
  435. //
  436. // There are too many INFs in the cache, look for the last one
  437. // and free it.
  438. //
  439. pInf = pParsedInf;
  440. while ( pInf->pNext ) {
  441. pInf = pInf->pNext;
  442. }
  443. if (pInf->pPrev) {
  444. (pInf->pPrev)->pNext = pInf->pNext;
  445. }
  446. if (pInf->pNext) {
  447. (pInf->pNext)->pPrev = pInf->pPrev;
  448. }
  449. if ( pParsedInfCache == pInf ) {
  450. pParsedInfCache = pInf->pNext;
  451. }
  452. pInf->pPrev = NULL;
  453. pInf->pNext = NULL;
  454. ParsedInfCached--;
  455. if ( pInf->MasterLineArray ) {
  456. SFree( pInf->MasterLineArray);
  457. }
  458. if ( pInf->MasterFile ) {
  459. SFree( pInf->MasterFile );
  460. }
  461. SFree( pInf);
  462. }
  463. return TRUE;
  464. }
  465. extern
  466. BOOL
  467. APIENTRY
  468. FFlushInfParsedInfo(
  469. SZ szInfName
  470. )
  471. {
  472. CHAR szName[cchlFullPathMax];
  473. PINFPERMINFO pPermInfo;
  474. PPARSED_INF pInf;
  475. //
  476. // Convert the inf path passed in to an inf name
  477. //
  478. PathToInfName( szInfName, szName );
  479. //
  480. // Find the perminfo for this inf. If none exists then return
  481. //
  482. if( !( pPermInfo = NameToInfPermInfo( szName , FALSE ) ) ) {
  483. return ( TRUE );
  484. }
  485. //
  486. // Go through the parsed inf cache, see if inf exists in the cache.
  487. // if it does, flush it.
  488. //
  489. if (pParsedInfCache) {
  490. pInf = pParsedInfCache;
  491. while ( pInf ) {
  492. if( pInf->pInfPermInfo == pPermInfo ) {
  493. if (pInf->pPrev) {
  494. (pInf->pPrev)->pNext = pInf->pNext;
  495. }
  496. if (pInf->pNext) {
  497. (pInf->pNext)->pPrev = pInf->pPrev;
  498. }
  499. if ( pParsedInfCache == pInf ) {
  500. pParsedInfCache = pInf->pNext;
  501. }
  502. pInf->pPrev = NULL;
  503. pInf->pNext = NULL;
  504. ParsedInfCached--;
  505. if ( pInf->MasterLineArray ) {
  506. SFree( pInf->MasterLineArray );
  507. }
  508. if ( pInf->MasterFile ) {
  509. SFree( pInf->MasterFile );
  510. }
  511. SFree( pInf );
  512. break;
  513. }
  514. pInf = pInf->pNext;
  515. }
  516. }
  517. return ( TRUE );
  518. }