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.

230 lines
8.3 KiB

  1. #include <windows.h>
  2. #include <stdlib.h>
  3. #include <strsafe.h>
  4. #define BINPLACE_MAX_FULL_PATH 4096 // must match value in binplace.c
  5. extern BOOL fVerbose; // imported from binplace.c
  6. BOOL
  7. PlaceFileMatch(
  8. IN LPCSTR FullFileName,
  9. IN OUT LPSTR PlaceFileEntry, // May be modified by env. var expansion
  10. OUT LPSTR PlaceFileClass, // assumed CHAR[BINPLACE_MAX_FULL_PATH]
  11. OUT LPSTR *PlaceFileNewName
  12. )
  13. // Returns TRUE if the filename matches the placefile entry.
  14. // On TRUE return, PlaceFileNewName points to location within
  15. // PlaceFileEntry. On FALSE return, PlaceFileClass and PlaceFileNewName are undefined.
  16. {
  17. const CHAR *pchEntryOrig; // Point to current parse pos of PlaceFileEntry
  18. CHAR szEntryExp[BINPLACE_MAX_FULL_PATH]; // Holds fileEntry after environment expansion
  19. PCHAR pchEntryExp, pchEntryExpEnd; // Point to current pos and end of EntryExp
  20. PCHAR pchVarStart; // Points into EntryExp: where an env. expansion should start replacing
  21. LPCSTR pszEnvVar;
  22. const CHAR *pchEntryFnEnd; // Stores the end of the filename
  23. const CHAR *pchFn; // Stores the current position within the filename
  24. PCHAR pch;
  25. PCHAR pchClass; // Current position within PlaceFileClass
  26. // Check for early-exit opportunities
  27. if(
  28. !PlaceFileEntry ||
  29. !FullFileName ||
  30. !PlaceFileClass ||
  31. PlaceFileEntry[0]==';' || // It is a full-line comment
  32. PlaceFileEntry[0]=='\0' // Blank line
  33. ) {
  34. return FALSE;
  35. }
  36. // ***
  37. // *** Expand any environment variables in PlaceFileEntry (result goes back into PlaceFileEntry)
  38. // ***
  39. pchEntryExp = szEntryExp;
  40. pchEntryExpEnd = pchEntryExp + (sizeof(szEntryExp)/sizeof(szEntryExp[0])) - 1;
  41. pchVarStart = NULL; // Indicates that I haven't passed the starting % of an env. var.
  42. // Skip over leading whitespace
  43. for(
  44. pchEntryOrig = PlaceFileEntry;
  45. *pchEntryOrig==' ' || *pchEntryOrig=='\t';
  46. pchEntryOrig++
  47. )
  48. {}
  49. // StrCopy with environment variable replacement
  50. while(*pchEntryOrig && pchEntryExp<pchEntryExpEnd) {
  51. if(*pchEntryOrig == '%') {
  52. if(pchVarStart) { // If this is a closing %
  53. *pchEntryExp = 0; // Make sure the env. var. is null-terminated
  54. // pchVarStart points to first %
  55. if(pszEnvVar = getenv(pchVarStart + 1)) { // If the env. var is valid
  56. // Copy it over
  57. StringCchCopyEx(
  58. pchVarStart, // Start where the first % was copied to
  59. pchEntryExpEnd - pchVarStart, // Remaining = end - curPos
  60. pszEnvVar,
  61. &pchEntryExp,
  62. NULL, // Don't need chars remaining
  63. 0 // No special flags
  64. );
  65. }
  66. else // Environment variable not defined
  67. {
  68. pchEntryExp = pchVarStart; // Back up to opening %
  69. // This effectively expands the undefined variable to ""
  70. }
  71. pchVarStart = NULL; // Reset to "unstarted"
  72. pchEntryOrig++; // Skip past %
  73. continue;
  74. } else {
  75. // This is an opening % - remember it, then continue copying in case
  76. // they never close it.
  77. pchVarStart = pchEntryExp;
  78. }
  79. }
  80. *pchEntryExp++ = *pchEntryOrig++; // Unless we "continue", we copy the next char.
  81. }
  82. // NULL terminate expanded string
  83. *pchEntryExp = 0;
  84. // Copy result back
  85. StringCchCopy(PlaceFileEntry, BINPLACE_MAX_FULL_PATH, szEntryExp);
  86. // Chop off comment, if any
  87. if(pch = strchr(PlaceFileEntry,';'))
  88. *pch = 0;
  89. // Chop off newline, if any
  90. if(pch = strchr(PlaceFileEntry,'\n'))
  91. *pch = 0;
  92. // PlaceFileEntry now:
  93. // - Has no leading whitespace
  94. // - Has no comments (;)
  95. // - All environment variables (%VARNAME%) have been expanded.
  96. // - May have been truncated if the environment variables were really long!
  97. // ***
  98. // *** Determine if this is a match
  99. // ***
  100. // Scan for end of filename (next whitespace OR !)
  101. for(
  102. pchEntryOrig = PlaceFileEntry;
  103. *pchEntryOrig!=0 && *pchEntryOrig!=' ' && *pchEntryOrig!='\t' && *pchEntryOrig!='!';
  104. pchEntryOrig++
  105. )
  106. {}
  107. if(*pchEntryOrig!=' ' && *pchEntryOrig!='\t') { // No class name specified
  108. return FALSE;
  109. }
  110. pchEntryFnEnd = pchEntryOrig; // Save end of filename for later
  111. pchFn = FullFileName + strlen(FullFileName);
  112. // Scan backwards over filename and path
  113. while(pchEntryOrig>PlaceFileEntry && pchFn > FullFileName)
  114. {
  115. pchEntryOrig--;
  116. pchFn--;
  117. if('*' == *pchEntryOrig) { // Wildcard for this portion
  118. if(*(pchEntryOrig+1)!='\\' && *(pchEntryOrig+1)!='/') { // Invalid: "dir\*abc\filename"
  119. // This also catches the invalid "dir\*" (wildcard invalid for filename).
  120. if (fVerbose) {
  121. fprintf( stdout, "BINPLACE : warning BNP0000: No wildcard in filename or mixed wildcard/text in class name: \"%s\"\n", PlaceFileEntry ) ;
  122. }
  123. return FALSE;
  124. }
  125. pchEntryOrig--; // Skip over the *
  126. if(
  127. pchEntryOrig <= PlaceFileEntry || // Can't start with wildcard ("*\dir\filename").
  128. ('\\'!=*pchEntryOrig && '/'!=*pchEntryOrig) // No partial wildcard ("dir\abc*\filename").
  129. ) {
  130. if (fVerbose) {
  131. fprintf( stdout, "BINPLACE : warning BNP0000: No wildcard at start of path or mixed wildcard/text in class name: \"%s\"\n", PlaceFileEntry ) ;
  132. }
  133. return FALSE;
  134. }
  135. while(pchFn > FullFileName && *pchFn != '\\' && *pchFn != '/') // Skip wildcarded directory name
  136. pchFn--;
  137. // Both pchFn and pchEntryOrig are now on a slash.
  138. } else {
  139. if(toupper(*pchFn) != toupper(*pchEntryOrig)) {
  140. if( // Mismatch ok only on forward/backward slashes.
  141. !(*pchFn == '/' || *pchFn == '\\') ||
  142. !(*pchEntryOrig == '/' || *pchEntryOrig == '\\')
  143. )
  144. {
  145. return FALSE; // Names don't match - exit
  146. }
  147. }
  148. }
  149. }
  150. // Did we match? Conditions to be met:
  151. // pchEntryOrig==PlaceFileEntry (match pattern completely consumed)
  152. // pchFn==FullFileName (full file name completely consumed, perverse case) OR *pchFn==slash (normal case).
  153. if(
  154. pchEntryOrig != PlaceFileEntry ||
  155. (pchFn != FullFileName && *(pchFn-1) !='/' && *(pchFn-1) != '\\')
  156. )
  157. {
  158. return FALSE;
  159. }
  160. // ***
  161. // *** Its a match. Set output variables accordingly.
  162. // ***
  163. // Skip to next whitespace (to skip over NewName, if present).
  164. for(
  165. pchEntryOrig = pchEntryFnEnd; // This is 1 past the end of the filename (saved previously)
  166. *pchEntryOrig!=0 && *pchEntryOrig!=' ' && *pchEntryOrig!='\t';
  167. pchEntryOrig++
  168. )
  169. {}
  170. // Skip over whitespace before the class name
  171. for(
  172. ; // Already set
  173. *pchEntryOrig==' ' || *pchEntryOrig=='\t';
  174. pchEntryOrig++
  175. )
  176. {}
  177. // pchEntryOrig is now at the start of the class name. Copy till an invalid char is reached.
  178. pchClass = PlaceFileClass;
  179. while(*pchEntryOrig!=0 && *pchEntryOrig!=' ' && *pchEntryOrig!='\t' && *pchEntryOrig!='!') {
  180. *pchClass++ = *pchEntryOrig++;
  181. }
  182. *pchClass = 0; // NULL terminate
  183. if(pchClass == PlaceFileClass) { // No class name specified!
  184. if (fVerbose) {
  185. fprintf( stdout, "BINPLACE : warning BNP0000: No class name in entry \"%s\"\n", PlaceFileEntry ) ;
  186. }
  187. return FALSE;
  188. }
  189. if (PlaceFileNewName != NULL) {
  190. *PlaceFileNewName = strchr(PlaceFileEntry,'!');
  191. if(*PlaceFileNewName) {
  192. *(*PlaceFileNewName)++ = 0; // Set the '!' to NULL, and skip past it to the Newname.
  193. }
  194. }
  195. return TRUE;
  196. }