⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inffile.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
      if (parser->line == NULL)
	goto error;
    }
  else
    {
//      assert(!is_key);
    }

  if (is_key)
    {
      field = InfpAddKeyToLine(parser->line, parser->token);
    }
  else
    {
      field = InfpAddFieldToLine(parser->line, parser->token);
    }

  if (field != NULL)
    {
      parser->token_len = 0;
      return field;
    }

error:
  parser->error = FALSE;
  return NULL;
}


/* close the current line and prepare for parsing a new one */
static void close_current_line( struct parser *parser )
{
  parser->line = NULL;
}



/* handler for parser LINE_START state */
static const CHAR *line_start_state( struct parser *parser, const CHAR *pos )
{
  const CHAR *p;

  for (p = pos; !is_eof( parser, p ); p++)
    {
      switch(*p)
	{
	  case '\r':
	    continue;

	  case '\n':
	    parser->line_pos++;
	    close_current_line( parser );
	    break;

	  case ';':
	    push_state( parser, LINE_START );
	    set_state( parser, COMMENT );
	    return p + 1;

	  case '[':
	    parser->start = p + 1;
	    set_state( parser, SECTION_NAME );
	    return p + 1;

	  default:
	    if (!isspace(*p))
	      {
		parser->start = p;
		set_state( parser, KEY_NAME );
		return p;
	      }
	    break;
	}
    }
  close_current_line( parser );
  return NULL;
}


/* handler for parser SECTION_NAME state */
static const CHAR *section_name_state( struct parser *parser, const CHAR *pos )
{
  const CHAR *p;

  for (p = pos; !is_eol( parser, p ); p++)
    {
      if (*p == ']')
	{
	  push_token( parser, p );
	  if (add_section_from_token( parser ) == NULL)
	    return NULL;
	  push_state( parser, LINE_START );
	  set_state( parser, COMMENT );  /* ignore everything else on the line */
	  return p + 1;
	}
    }
  parser->error = STATUS_BAD_SECTION_NAME_LINE; /* unfinished section name */
  return NULL;
}


/* handler for parser KEY_NAME state */
static const CHAR *key_name_state( struct parser *parser, const CHAR *pos )
{
    const CHAR *p, *token_end = parser->start;

    for (p = pos; !is_eol( parser, p ); p++)
    {
        if (*p == ',') break;
        switch(*p)
        {

         case '=':
            push_token( parser, token_end );
            if (!add_field_from_token( parser, 1 )) return NULL;
            parser->start = p + 1;
            push_state( parser, VALUE_NAME );
            set_state( parser, LEADING_SPACES );
            return p + 1;
        case ';':
            push_token( parser, token_end );
            if (!add_field_from_token( parser, 0 )) return NULL;
            push_state( parser, LINE_START );
            set_state( parser, COMMENT );
            return p + 1;
        case '"':
            push_token( parser, token_end );
            parser->start = p + 1;
            push_state( parser, KEY_NAME );
            set_state( parser, QUOTES );
            return p + 1;
        case '\\':
            push_token( parser, token_end );
            parser->start = p;
            push_state( parser, KEY_NAME );
            set_state( parser, EOL_BACKSLASH );
            return p;
        default:
            if (!isspace(*p)) token_end = p + 1;
            else
            {
                push_token( parser, p );
                push_state( parser, KEY_NAME );
                set_state( parser, TRAILING_SPACES );
                return p;
            }
            break;
        }
    }
    push_token( parser, token_end );
    set_state( parser, VALUE_NAME );
    return p;
}


/* handler for parser VALUE_NAME state */
static const CHAR *value_name_state( struct parser *parser, const CHAR *pos )
{
    const CHAR *p, *token_end = parser->start;

    for (p = pos; !is_eol( parser, p ); p++)
    {
        switch(*p)
        {
        case ';':
            push_token( parser, token_end );
            if (!add_field_from_token( parser, 0 )) return NULL;
            push_state( parser, LINE_START );
            set_state( parser, COMMENT );
            return p + 1;
        case ',':
            push_token( parser, token_end );
            if (!add_field_from_token( parser, 0 )) return NULL;
            parser->start = p + 1;
            push_state( parser, VALUE_NAME );
            set_state( parser, LEADING_SPACES );
            return p + 1;
        case '"':
            push_token( parser, token_end );
            parser->start = p + 1;
            push_state( parser, VALUE_NAME );
            set_state( parser, QUOTES );
            return p + 1;
        case '\\':
            push_token( parser, token_end );
            parser->start = p;
            push_state( parser, VALUE_NAME );
            set_state( parser, EOL_BACKSLASH );
            return p;
        default:
            if (!isspace(*p)) token_end = p + 1;
            else
            {
                push_token( parser, p );
                push_state( parser, VALUE_NAME );
                set_state( parser, TRAILING_SPACES );
                return p;
            }
            break;
        }
    }
    push_token( parser, token_end );
    if (!add_field_from_token( parser, 0 )) return NULL;
    set_state( parser, LINE_START );
    return p;
}


/* handler for parser EOL_BACKSLASH state */
static const CHAR *eol_backslash_state( struct parser *parser, const CHAR *pos )
{
  const CHAR *p;

  for (p = pos; !is_eof( parser, p ); p++)
    {
      switch(*p)
	{
	  case '\r':
	    continue;

	  case '\n':
	    parser->line_pos++;
	    parser->start = p + 1;
	    set_state( parser, LEADING_SPACES );
	    return p + 1;

	  case '\\':
	    continue;

	  case ';':
	    push_state( parser, EOL_BACKSLASH );
	    set_state( parser, COMMENT );
	    return p + 1;

	  default:
	    if (isspace(*p))
	      continue;
	    push_token( parser, p );
	    pop_state( parser );
	    return p;
	}
    }
  parser->start = p;
  pop_state( parser );

  return p;
}


/* handler for parser QUOTES state */
static const CHAR *quotes_state( struct parser *parser, const CHAR *pos )
{
  const CHAR *p, *token_end = parser->start;

  for (p = pos; !is_eol( parser, p ); p++)
    {
      if (*p == '"')
	{
	  if (p+1 < parser->end && p[1] == '"')  /* double quotes */
	    {
	      push_token( parser, p + 1 );
	      parser->start = token_end = p + 2;
	      p++;
	    }
	  else  /* end of quotes */
	    {
	      push_token( parser, p );
	      parser->start = p + 1;
	      pop_state( parser );
	      return p + 1;
	    }
	}
    }
  push_token( parser, p );
  pop_state( parser );
  return p;
}


/* handler for parser LEADING_SPACES state */
static const CHAR *leading_spaces_state( struct parser *parser, const CHAR *pos )
{
  const CHAR *p;

  for (p = pos; !is_eol( parser, p ); p++)
    {
      if (*p == '\\')
	{
	  parser->start = p;
	  set_state( parser, EOL_BACKSLASH );
	  return p;
	}
      if (!isspace(*p))
	break;
    }
  parser->start = p;
  pop_state( parser );
  return p;
}


/* handler for parser TRAILING_SPACES state */
static const CHAR *trailing_spaces_state( struct parser *parser, const CHAR *pos )
{
  const CHAR *p;

  for (p = pos; !is_eol( parser, p ); p++)
    {
      if (*p == '\\')
	{
	  set_state( parser, EOL_BACKSLASH );
	  return p;
	}
      if (!isspace(*p))
	break;
    }
  pop_state( parser );
  return p;
}


/* handler for parser COMMENT state */
static const CHAR *comment_state( struct parser *parser, const CHAR *pos )
{
  const CHAR *p = pos;

  while (!is_eol( parser, p ))
     p++;
  pop_state( parser );
  return p;
}


/* parse a complete buffer */
static BOOLEAN
InfpParseBuffer (PINFCACHE file,
		 const CHAR *buffer,
		 const CHAR *end,
		 PULONG error_line)
{
  struct parser parser;
  const CHAR *pos = buffer;

  parser.start       = buffer;
  parser.end         = end;
  parser.file        = file;
  parser.line        = NULL;
  parser.state       = LINE_START;
  parser.stack_pos   = 0;
  parser.cur_section = NULL;
  parser.line_pos    = 1;
  parser.error       = TRUE;
  parser.token_len   = 0;

  /* parser main loop */
  while (pos)
    pos = (parser_funcs[parser.state])(&parser, pos);

  if (parser.error)
    {
      if (error_line)
	*error_line = parser.line_pos;
      return parser.error;
    }

  /* find the [strings] section */
  file->StringsSection = InfpCacheFindSection (file, "Strings");

  return TRUE;
}

/* PUBLIC FUNCTIONS *********************************************************/

BOOLEAN
InfOpenFile(PHINF InfHandle,
	    PCSTR FileName,
	    PULONG ErrorLine)
{
  PFILE FileHandle;
  PCHAR FileBuffer;
  ULONG FileSize;
  PINFCACHE Cache;
  BOOLEAN Success;


  *InfHandle = NULL;
  *ErrorLine = (ULONG)-1;


  /* Open the inf file */
  FileHandle = FsOpenFile (FileName);
  if (FileHandle == NULL)
    {
//      DPRINT("NtOpenFile() failed (Status %lx)\n", Status);
      return FALSE;
    }

//  DPRINT("NtOpenFile() successful\n");

  /* Query file size */
  FileSize = FsGetFileSize (FileHandle);
  if (FileSize == 0)
    {
//      DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status);
      FsCloseFile (FileHandle);
      return FALSE;
    }

//  DPRINT("File size: %lu\n", FileLength);

  /* Allocate file buffer */
  FileBuffer = MmAllocateMemory (FileSize + 1);
  if (FileBuffer == NULL)
    {
//      DPRINT1("RtlAllocateHeap() failed\n");
      FsCloseFile (FileHandle);
      return FALSE;
    }

  /* Read file */
  Success = FsReadFile(FileHandle, FileSize, NULL, FileBuffer);

  FsCloseFile (FileHandle);
  if (!Success)
    {
//      DPRINT("FsReadFile() failed\n");
      MmFreeMemory (FileBuffer);
      return FALSE;
    }

  /* Append string terminator */
  FileBuffer[FileSize] = 0;

  /* Allocate infcache header */
  Cache = (PINFCACHE)MmAllocateMemory (sizeof(INFCACHE));
  if (Cache == NULL)
    {
//      DPRINT("RtlAllocateHeap() failed\n");
      MmFreeMemory (FileBuffer);
      return FALSE;
    }

  /* Initialize inicache header */
  RtlZeroMemory(Cache,
		sizeof(INFCACHE));

  /* Parse the inf buffer */
  Success = InfpParseBuffer (Cache,
			     FileBuffer,
			     FileBuffer + FileSize,
			     ErrorLine);
  if (!Success)
    {
      MmFreeMemory (Cache);
      Cache = NULL;
    }

  /* Free file buffer */
  MmFreeMemory (FileBuffer);

  *InfHandle = (HINF)Cache;

  return Success;
}


VOID
InfCloseFile(HINF InfHandle)
{
  PINFCACHE Cache;

  Cache = (PINFCACHE)InfHandle;

  if (Cache == NULL)
    {
      return;
    }

  while (Cache->FirstSection != NULL)
    {
      Cache->FirstSection = InfpCacheFreeSection(Cache->FirstSection);
    }
  Cache->LastSection = NULL;

  MmFreeMemory(Cache);
}


BOOLEAN
InfFindFirstLine (HINF InfHandle,
		  PCSTR Section,
		  PCSTR Key,
		  PINFCONTEXT Context)
{
  PINFCACHE Cache;
  PINFCACHESECTION CacheSection;
  PINFCACHELINE CacheLine;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -