Goto sanos source index

//
// verinfo.c
//
// Module version information
//
// Copyright (C) 2002 Michael Ringgaard. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 
// 1. Redistributions of source code must retain the above copyright 
//    notice, this list of conditions and the following disclaimer.  
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.  
// 3. Neither the name of the project nor the names of its contributors
//    may be used to endorse or promote products derived from this software
//    without specific prior written permission. 
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
// SUCH DAMAGE.
// 

#ifdef KERNEL
#include <os/krnl.h>
#else
#include <os.h>
#include <string.h>
#include <sys/types.h>
#include <moddb.h>
#include <verinfo.h>
#endif

#define ALIGN(p) ((char *)(((unsigned long) (p) + 3) & ~3))

#define TYPE_VALUE_BINARY 0
#define TYPE_VALUE_TEXT   1

#pragma pack(push, 1)

struct stringinfo {
  unsigned short length;
  unsigned short value_length;
  unsigned short type;
  wchar_t key[0];
};

struct version_resource {
  unsigned short length;
  unsigned short value_length;
  unsigned short type;
  wchar_t key[16];
  unsigned short padding1;
  struct verinfo fixed;
  char value[0];
};

#pragma pack(pop)

static int streq(wchar_t *s1, char *s2) {
  while (*s1 && *s2) if (*s1++ != *s2++) return 0;
  return !*s1 && !*s2;
}

static char *getchild(char *start, char *end, char *name, int *size) {
  char *p = start;
  while (p < end) {
    struct stringinfo *si = (struct stringinfo *) p;
    if (si->length == 0) break;
    if (streq(si->key, name)) {
      end = p + si->length;
      p += 3 * sizeof(unsigned short) + (strlen(name) + 1) * sizeof(wchar_t);
      p = ALIGN(p);
      *size = end - p;
      return p;
    }

    p += si->length;
    p = ALIGN(p);
  }

  return NULL;
}

static struct version_resource *getver(hmodule_t hmod) {
  int rc;
  struct version_resource *ver;

  rc = get_resource_data(hmod, INTRES(16), INTRES(1), 0, (void **) &ver);
  if (rc < 0) return NULL;
  if (rc < sizeof(struct version_resource)) return NULL;
  if (ver->fixed.signature != VER_SIGNATURE) return NULL;
  
  return ver;
}

struct verinfo *get_version_info(hmodule_t hmod) {
  struct version_resource *ver;
  
  ver = getver(hmod);
  if (ver == NULL) return NULL;
  return &ver->fixed;
}

int get_version_value(hmodule_t hmod, char *name, char *buf, int size) {
  struct version_resource *ver;
  char *start;
  char *end;
  int len;
  char *p;
  wchar_t *q;
  
  ver = getver(hmod);
  if (ver == NULL) return -EINVAL;

  start = (char *) ver->value;
  end = (char *) ver + ver->length;

  p = getchild(start, end, "StringFileInfo", &len);
  if (!p) return -ENOENT;

  p = getchild(p, p + len, "00000000", &len);
  if (!p) return -ENOENT;

  p = getchild(p, p + len, name, &len);
  if (!p) return -ENOENT;

  q = (wchar_t *) p;
  p = buf;
  while (*q) {
    if (--size == 0) return -E2BIG;
    *p++ = (char) *q++;
  }
  *p = 0;

  return p - buf;
}