f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync/* $Id$ */
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync/** @file
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync * IPRT - RTDirCreateUniqueNumbered, generic implementation.
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync */
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync/*
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync * Copyright (C) 2013 Oracle Corporation
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync *
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync * available from http://www.virtualbox.org. This file is free software;
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync * you can redistribute it and/or modify it under the terms of the GNU
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync * General Public License (GPL) as published by the Free Software
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync *
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync * The contents of this file may alternatively be used under the terms
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync * of the Common Development and Distribution License Version 1.0
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync * VirtualBox OSE distribution, in which case the provisions of the
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync * CDDL are applicable instead of those of the GPL.
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync *
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync * You may elect to license modified versions of this file under the
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync * terms and conditions of either the GPL or the CDDL or both.
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync */
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync/*******************************************************************************
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync* Header Files *
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync*******************************************************************************/
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync#include <Windows.h>
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync#include <Dbghelp.h>
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync#include <iprt/alloca.h>
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync#include <iprt/dir.h>
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync#include <iprt/file.h>
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync#include <iprt/getopt.h>
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync#include <iprt/initterm.h>
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync#include <iprt/list.h>
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync#include <iprt/mem.h>
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync#include <iprt/message.h>
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync#include <iprt/path.h>
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync#include <iprt/stream.h>
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync#include <iprt/string.h>
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync#include <iprt/err.h>
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync#include "r0drv/nt/symdb.h"
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync/*******************************************************************************
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync* Structures and Typedefs *
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync*******************************************************************************/
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync/** A structure member we're interested in. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsynctypedef struct MYMEMBER
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync{
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /** The member name. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync const char * const pszName;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /** Reserved. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint32_t const fFlags;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /** The offset of the member. UINT32_MAX if not found. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint32_t off;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /** The size of the member. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint32_t cb;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /** Alternative names, optional.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * This is a string of zero terminated strings, ending with an zero length
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * string (or double '\\0' if you like). */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync const char * const pszzAltNames;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync} MYMEMBER;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync/** Pointer to a member we're interested. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsynctypedef MYMEMBER *PMYMEMBER;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync/** Members we're interested in. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsynctypedef struct MYSTRUCT
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync{
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /** The structure name. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync const char * const pszName;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /** Array of members we're interested in. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync MYMEMBER *paMembers;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /** The number of members we're interested in. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint32_t const cMembers;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /** Reserved. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint32_t const fFlags;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync} MYSTRUCT;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync/** Architecture. */
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsynctypedef enum MYARCH
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync{
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync MYARCH_X86,
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync MYARCH_AMD64,
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync MYARCH_DETECT
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync} MYARCH;
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync/** Set of structures for one kernel. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsynctypedef struct MYSET
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync{
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /** The list entry. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTLISTNODE ListEntry;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /** The source PDB. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync char *pszPdb;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /** The OS version we've harvested structs for */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTNTSDBOSVER OsVerInfo;
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync /** The architecture. */
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync MYARCH enmArch;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /** The structures and their member. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync MYSTRUCT aStructs[1];
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync} MYSET;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync/** Pointer a set of structures for one kernel. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsynctypedef MYSET *PMYSET;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync/*******************************************************************************
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync* Global Variables *
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync*******************************************************************************/
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync/** Verbosity level (-v, --verbose). */
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsyncstatic uint32_t g_iOptVerbose = 1;
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync/** Set if we should force ahead despite errors. */
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsyncstatic bool g_fOptForce = false;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync/** The members of the KPRCB structure that we're interested in. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsyncstatic MYMEMBER g_aKprcbMembers[] =
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync{
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync { "QuantumEnd", 0, UINT32_MAX, UINT32_MAX, NULL },
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync { "DpcQueueDepth", 0, UINT32_MAX, UINT32_MAX, "DpcData[0].DpcQueueDepth\0" },
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync { "VendorString", 0, UINT32_MAX, UINT32_MAX, NULL },
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync};
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync/** The structures we're interested in. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsyncstatic MYSTRUCT g_aStructs[] =
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync{
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync { "_KPRCB", &g_aKprcbMembers[0], RT_ELEMENTS(g_aKprcbMembers), 0 },
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync};
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync/** List of data we've found. This is sorted by version info. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsyncstatic RTLISTANCHOR g_SetList;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync/**
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * For debug/verbose output.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync *
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param pszFormat The format string.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param ... The arguments referenced in the format string.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsyncstatic void MyDbgPrintf(const char *pszFormat, ...)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync{
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync if (g_iOptVerbose > 1)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync va_list va;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync va_start(va, pszFormat);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTPrintf("debug: ");
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTPrintfV(pszFormat, va);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync va_end(va);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync}
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync/**
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Returns the name we wish to use in the C code.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @returns Structure name.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param pStruct The structure descriptor.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsyncstatic const char *figureCStructName(MYSTRUCT const *pStruct)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync{
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync const char *psz = pStruct->pszName;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync while (*psz == '_')
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync psz++;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync return psz;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync}
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync/**
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Returns the name we wish to use in the C code.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @returns Member name.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param pStruct The member descriptor.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsyncstatic const char *figureCMemberName(MYMEMBER const *pMember)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync{
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync return pMember->pszName;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync}
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync/**
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Creates a MYSET with copies of all the data and inserts it into the
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * g_SetList in a orderly fashion.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync *
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param pOut The output stream.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsyncstatic void generateHeader(PRTSTREAM pOut)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync{
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTStrmPrintf(pOut,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "/* $" "I" "d" ": $ */\n" /* avoid it being expanded */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "/** @file\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " * IPRT - NT kernel type helpers - Autogenerated, do NOT edit.\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " */\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "/*\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " * Copyright (C) 2013 Oracle Corporation\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " *\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " * This file is part of VirtualBox Open Source Edition (OSE), as\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " * available from http://www.virtualbox.org. This file is free software;\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " * you can redistribute it and/or modify it under the terms of the GNU\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " * General Public License (GPL) as published by the Free Software\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " * Foundation, in version 2 as it comes in the \"COPYING\" file of the\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " * VirtualBox OSE distribution. VirtualBox OSE is distributed in the\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " *\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " * The contents of this file may alternatively be used under the terms\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " * of the Common Development and Distribution License Version 1.0\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " * (CDDL) only, as it comes in the \"COPYING.CDDL\" file of the\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " * VirtualBox OSE distribution, in which case the provisions of the\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " * CDDL are applicable instead of those of the GPL.\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " *\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " * You may elect to license modified versions of this file under the\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " * terms and conditions of either the GPL or the CDDL or both.\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " */\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "#ifndef ___r0drv_nt_symdbdata_h\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "#define ___r0drv_nt_symdbdata_h\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "#include \"r0drv/nt/symdb.h\"\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync );
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /*
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Generate types.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync for (uint32_t i = 0; i < RT_ELEMENTS(g_aStructs); i++)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync const char *pszStructName = figureCStructName(&g_aStructs[i]);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTStrmPrintf(pOut,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "typedef struct RTNTSDBTYPE_%s\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "{\n",
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pszStructName);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync PMYMEMBER paMembers = g_aStructs[i].paMembers;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync for (uint32_t j = 0; j < g_aStructs->cMembers; j++)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync const char *pszMemName = figureCMemberName(&paMembers[j]);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTStrmPrintf(pOut,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " uint32_t off%s;\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " uint32_t cb%s;\n",
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pszMemName, pszMemName);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTStrmPrintf(pOut,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "} RTNTSDBTYPE_%s;\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "\n",
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pszStructName);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTStrmPrintf(pOut,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "typedef struct RTNTSDBSET\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "{\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " RTNTSDBOSVER%-20s OsVerInfo;\n", "");
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync for (uint32_t i = 0; i < RT_ELEMENTS(g_aStructs); i++)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync const char *pszStructName = figureCStructName(&g_aStructs[i]);
2ccca012d772c237b97e06a362720b3fb6c236b8vboxsync RTStrmPrintf(pOut, " RTNTSDBTYPE_%-20s %s;\n", pszStructName, pszStructName);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTStrmPrintf(pOut,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "} RTNTSDBSET;\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "typedef RTNTSDBSET const *PCRTNTSDBSET;\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "\n");
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /*
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Output the data.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTStrmPrintf(pOut,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "#ifndef RTNTSDB_NO_DATA\n"
2ccca012d772c237b97e06a362720b3fb6c236b8vboxsync "const RTNTSDBSET g_artNtSdbSets[] = \n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "{\n");
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync PMYSET pSet;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTListForEach(&g_SetList, pSet, MYSET, ListEntry)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync const char *pszArch = pSet->enmArch == MYARCH_AMD64 ? "AMD64" : "X86";
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTStrmPrintf(pOut,
5efc3716063572a178abdb9c572ddc2bf68ac0abvboxsync "# ifdef RT_ARCH_%s\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " { /* Source: %s */\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " /*.OsVerInfo = */\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " {\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " /* .uMajorVer = */ %u,\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " /* .uMinorVer = */ %u,\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " /* .fChecked = */ %s,\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " /* .fSmp = */ %s,\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " /* .uCsdNo = */ %u,\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " /* .uBuildNo = */ %u,\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " },\n",
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync pszArch,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pSet->pszPdb,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pSet->OsVerInfo.uMajorVer,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pSet->OsVerInfo.uMinorVer,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pSet->OsVerInfo.fChecked ? "true" : "false",
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pSet->OsVerInfo.fSmp ? "true" : "false",
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pSet->OsVerInfo.uCsdNo,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pSet->OsVerInfo.uBuildNo);
2ccca012d772c237b97e06a362720b3fb6c236b8vboxsync for (uint32_t i = 0; i < RT_ELEMENTS(pSet->aStructs); i++)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
2ccca012d772c237b97e06a362720b3fb6c236b8vboxsync const char *pszStructName = figureCStructName(&pSet->aStructs[i]);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTStrmPrintf(pOut,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " /* .%s = */\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " {\n", pszStructName);
2ccca012d772c237b97e06a362720b3fb6c236b8vboxsync PMYMEMBER paMembers = pSet->aStructs[i].paMembers;
2ccca012d772c237b97e06a362720b3fb6c236b8vboxsync for (uint32_t j = 0; j < pSet->aStructs[i].cMembers; j++)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync const char *pszMemName = figureCMemberName(&paMembers[j]);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTStrmPrintf(pOut,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " /* .off%-25s = */ %#06x,\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " /* .cb%-26s = */ %#06x,\n",
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pszMemName, paMembers[j].off,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pszMemName, paMembers[j].cb);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTStrmPrintf(pOut,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync " },\n");
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTStrmPrintf(pOut,
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync " },\n"
5efc3716063572a178abdb9c572ddc2bf68ac0abvboxsync "# endif\n"
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync );
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTStrmPrintf(pOut,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "};\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "#endif /* !RTNTSDB_NO_DATA */\n"
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync "\n");
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
2ccca012d772c237b97e06a362720b3fb6c236b8vboxsync RTStrmPrintf(pOut, "\n#endif\n\n");
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync}
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync/**
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Creates a MYSET with copies of all the data and inserts it into the
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * g_SetList in a orderly fashion.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync *
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @returns Fully complained exit code.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param pOsVerInfo The OS version info.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsyncstatic RTEXITCODE saveStructures(PRTNTSDBOSVER pOsVerInfo, MYARCH enmArch, const char *pszPdb)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync{
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /*
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Allocate one big chunk, figure it's size once.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync static size_t s_cbNeeded = 0;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (s_cbNeeded == 0)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync s_cbNeeded = RT_OFFSETOF(MYSET, aStructs[RT_ELEMENTS(g_aStructs)]);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync for (uint32_t i = 0; i < RT_ELEMENTS(g_aStructs); i++)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync s_cbNeeded += sizeof(MYMEMBER) * g_aStructs[i].cMembers;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync size_t cbPdb = strlen(pszPdb) + 1;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync PMYSET pSet = (PMYSET)RTMemAlloc(s_cbNeeded + cbPdb);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (!pSet)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "Out of memory!\n");
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /*
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Copy over the data.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync pSet->enmArch = enmArch;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync memcpy(&pSet->OsVerInfo, pOsVerInfo, sizeof(pSet->OsVerInfo));
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync memcpy(&pSet->aStructs[0], g_aStructs, sizeof(g_aStructs));
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync PMYMEMBER pDst = (PMYMEMBER)&pSet->aStructs[RT_ELEMENTS(g_aStructs)];
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync for (uint32_t i = 0; i < RT_ELEMENTS(g_aStructs); i++)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pSet->aStructs[i].paMembers = pDst;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync memcpy(pDst, g_aStructs[i].paMembers, g_aStructs[i].cMembers * sizeof(*pDst));
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pDst += g_aStructs[i].cMembers;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pSet->pszPdb = (char *)pDst;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync memcpy(pDst, pszPdb, cbPdb);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /*
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Link it.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync PMYSET pInsertBefore;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTListForEach(&g_SetList, pInsertBefore, MYSET, ListEntry)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
c33049ffa29c187c81c78c13b35978aed13ebb21vboxsync int iDiff = rtNtOsVerInfoCompare(&pInsertBefore->OsVerInfo, &pSet->OsVerInfo);
c33049ffa29c187c81c78c13b35978aed13ebb21vboxsync if (iDiff >= 0)
c33049ffa29c187c81c78c13b35978aed13ebb21vboxsync {
c33049ffa29c187c81c78c13b35978aed13ebb21vboxsync if (iDiff > 0 || pInsertBefore->enmArch > pSet->enmArch)
c33049ffa29c187c81c78c13b35978aed13ebb21vboxsync {
2ccca012d772c237b97e06a362720b3fb6c236b8vboxsync RTListNodeInsertBefore(&pInsertBefore->ListEntry, &pSet->ListEntry);
c33049ffa29c187c81c78c13b35978aed13ebb21vboxsync return RTEXITCODE_SUCCESS;
c33049ffa29c187c81c78c13b35978aed13ebb21vboxsync }
c33049ffa29c187c81c78c13b35978aed13ebb21vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
c33049ffa29c187c81c78c13b35978aed13ebb21vboxsync RTListAppend(&g_SetList, &pSet->ListEntry);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync return RTEXITCODE_SUCCESS;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync}
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync/**
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Checks that we found everything.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync *
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @returns Fully complained exit code.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsyncstatic RTEXITCODE checkThatWeFoundEverything(void)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync{
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync for (uint32_t i = 0; i < RT_ELEMENTS(g_aStructs); i++)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync PMYMEMBER paMembers = g_aStructs[i].paMembers;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint32_t j = g_aStructs[i].cMembers;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync while (j-- > 0)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (paMembers[j].off == UINT32_MAX)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, " Missing %s::%s\n", g_aStructs[i].pszName, paMembers[j].pszName);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync return rcExit;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync}
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync/**
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Matches the member against what we're looking for.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync *
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @returns Number of hits.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param cWantedMembers The number members in paWantedMembers.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param paWantedMembers The members we're looking for.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param pszPrefix The member name prefix.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param pszMember The member name.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param offMember The member offset.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param cbMember The member size.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsyncstatic uint32_t matchUpStructMembers(unsigned cWantedMembers, PMYMEMBER paWantedMembers,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync const char *pszPrefix, const char *pszMember,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint32_t offMember, uint32_t cbMember)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync{
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync size_t cchPrefix = strlen(pszPrefix);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint32_t cHits = 0;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint32_t iMember = cWantedMembers;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync while (iMember-- > 0)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if ( !strncmp(pszPrefix, paWantedMembers[iMember].pszName, cchPrefix)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync && !strcmp(pszMember, paWantedMembers[iMember].pszName + cchPrefix))
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync paWantedMembers[iMember].off = offMember;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync paWantedMembers[iMember].cb = cbMember;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync cHits++;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync else if (paWantedMembers[iMember].pszzAltNames)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync char const *pszCur = paWantedMembers[iMember].pszzAltNames;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync while (*pszCur)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync size_t cchCur = strlen(pszCur);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if ( !strncmp(pszPrefix, pszCur, cchPrefix)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync && !strcmp(pszMember, pszCur + cchPrefix))
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync paWantedMembers[iMember].off = offMember;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync paWantedMembers[iMember].cb = cbMember;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync cHits++;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync break;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pszCur += cchCur + 1;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync return cHits;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync}
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync/**
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Resets the writable structure members prior to processing a PDB.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync *
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * While processing the PDB, will fill in the sizes and offsets of what we find.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Afterwards we'll use look for reset values to see that every structure and
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * member was located successfully.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsyncstatic void resetMyStructs(void)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync{
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync for (uint32_t i = 0; i < RT_ELEMENTS(g_aStructs); i++)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync PMYMEMBER paMembers = g_aStructs[i].paMembers;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint32_t j = g_aStructs[i].cMembers;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync while (j-- > 0)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync paMembers[j].off = UINT32_MAX;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync paMembers[j].cb = UINT32_MAX;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync}
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync/**
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Find members in the specified structure type (@a idxType).
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync *
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @returns Fully bitched exit code.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param hFake Fake process handle.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param uModAddr The module address.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param idxType The type index of the structure which members we're
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * going to process.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param cWantedMembers The number of wanted members.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param paWantedMembers The wanted members. This will be modified.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param offDisp Displacement when calculating member offsets.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param pszStructNm The top level structure name.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param pszPrefix The member name prefix.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param pszLogTag The log tag.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsyncstatic RTEXITCODE findMembers(HANDLE hFake, uint64_t uModAddr, uint32_t idxType,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint32_t cWantedMembers, PMYMEMBER paWantedMembers,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint32_t offDisp, const char *pszStructNm, const char *pszPrefix, const char *pszLogTag)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync{
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync DWORD cChildren = 0;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (!SymGetTypeInfo(hFake, uModAddr, idxType, TI_GET_CHILDRENCOUNT, &cChildren))
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: TI_GET_CHILDRENCOUNT failed on _KPRCB: %u\n", pszLogTag, GetLastError());
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync MyDbgPrintf(" %s: cChildren=%u (%#x)\n", pszStructNm, cChildren);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync TI_FINDCHILDREN_PARAMS *pChildren;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pChildren = (TI_FINDCHILDREN_PARAMS *)alloca(RT_OFFSETOF(TI_FINDCHILDREN_PARAMS, ChildId[cChildren]));
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pChildren->Start = 0;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pChildren->Count = cChildren;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (!SymGetTypeInfo(hFake, uModAddr, idxType, TI_FINDCHILDREN, pChildren))
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: TI_FINDCHILDREN failed on _KPRCB: %u\n", pszLogTag, GetLastError());
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync for (uint32_t i = 0; i < cChildren; i++)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync //MyDbgPrintf(" %s: child#%u: TypeIndex=%u\n", pszStructNm, i, pChildren->ChildId[i]);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync IMAGEHLP_SYMBOL_TYPE_INFO enmErr;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync PWCHAR pwszMember = NULL;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint32_t idxRefType = 0;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint32_t offMember = 0;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint64_t cbMember = 0;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint32_t cMemberChildren = 0;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if ( SymGetTypeInfo(hFake, uModAddr, pChildren->ChildId[i], enmErr = TI_GET_SYMNAME, &pwszMember)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync && SymGetTypeInfo(hFake, uModAddr, pChildren->ChildId[i], enmErr = TI_GET_OFFSET, &offMember)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync && SymGetTypeInfo(hFake, uModAddr, pChildren->ChildId[i], enmErr = TI_GET_TYPE, &idxRefType)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync && SymGetTypeInfo(hFake, uModAddr, idxRefType, enmErr = TI_GET_LENGTH, &cbMember)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync && SymGetTypeInfo(hFake, uModAddr, idxRefType, enmErr = TI_GET_CHILDRENCOUNT, &cMemberChildren)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync )
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync offMember += offDisp;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync char *pszMember;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync int rc = RTUtf16ToUtf8(pwszMember, &pszMember);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (RT_SUCCESS(rc))
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync matchUpStructMembers(cWantedMembers, paWantedMembers, pszPrefix, pszMember, offMember, cbMember);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /*
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Gather more info and do some debug printing. We'll use some
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * of this info below when recursing into sub-structures
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * and arrays.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint32_t fNested = 0; SymGetTypeInfo(hFake, uModAddr, idxRefType, TI_GET_NESTED, &fNested);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint32_t uDataKind = 0; SymGetTypeInfo(hFake, uModAddr, idxRefType, TI_GET_DATAKIND, &uDataKind);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint32_t uBaseType = 0; SymGetTypeInfo(hFake, uModAddr, idxRefType, TI_GET_BASETYPE, &uBaseType);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint32_t uMembTag = 0; SymGetTypeInfo(hFake, uModAddr, pChildren->ChildId[i], TI_GET_SYMTAG, &uMembTag);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint32_t uBaseTag = 0; SymGetTypeInfo(hFake, uModAddr, idxRefType, TI_GET_SYMTAG, &uBaseTag);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint32_t cElements = 0; SymGetTypeInfo(hFake, uModAddr, idxRefType, TI_GET_COUNT, &cElements);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint32_t idxArrayType = 0; SymGetTypeInfo(hFake, uModAddr, idxRefType, TI_GET_ARRAYINDEXTYPEID, &idxArrayType);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync MyDbgPrintf(" %#06x LB %#06llx %c%c %2d %2d %2d %2d %2d %4d %s::%s%s\n",
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync offMember, cbMember,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync cMemberChildren > 0 ? 'c' : '-',
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync fNested != 0 ? 'n' : '-',
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uDataKind,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uBaseType,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uMembTag,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uBaseTag,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync cElements,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync idxArrayType,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pszStructNm,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pszPrefix,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pszMember);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /*
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Recurse into children.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (cMemberChildren > 0)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync size_t cbNeeded = strlen(pszMember) + strlen(pszPrefix) + sizeof(".");
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync char *pszSubPrefix = (char *)RTMemTmpAlloc(cbNeeded);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (pszSubPrefix)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync strcat(strcat(strcpy(pszSubPrefix, pszPrefix), pszMember), ".");
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTEXITCODE rcExit2 = findMembers(hFake, uModAddr, idxRefType, cWantedMembers,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync paWantedMembers, offMember,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pszStructNm,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pszSubPrefix,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pszLogTag);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (rcExit2 != RTEXITCODE_SUCCESS)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync rcExit = rcExit2;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTMemTmpFree(pszSubPrefix);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync else
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "out of memory\n");
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /*
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Recurse into arrays too.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync else if (cElements > 0 && idxArrayType > 0)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync BOOL fRc;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint32_t idxElementRefType = 0;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync fRc = SymGetTypeInfo(hFake, uModAddr, idxRefType, TI_GET_TYPE, &idxElementRefType); Assert(fRc);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint64_t cbElement = cbMember / cElements;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync fRc = SymGetTypeInfo(hFake, uModAddr, idxElementRefType, TI_GET_LENGTH, &cbElement); Assert(fRc);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync MyDbgPrintf("idxArrayType=%u idxElementRefType=%u cbElement=%u\n", idxArrayType, idxElementRefType, cbElement);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync size_t cbNeeded = strlen(pszMember) + strlen(pszPrefix) + sizeof("[xxxxxxxxxxxxxxxx].");
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync char *pszSubPrefix = (char *)RTMemTmpAlloc(cbNeeded);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (pszSubPrefix)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync for (uint32_t iElement = 0; iElement < cElements; iElement++)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTStrPrintf(pszSubPrefix, cbNeeded, "%s%s[%u].", pszPrefix, pszMember, iElement);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTEXITCODE rcExit2 = findMembers(hFake, uModAddr, idxElementRefType, cWantedMembers,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync paWantedMembers,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync offMember + iElement * cbElement,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pszStructNm,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pszSubPrefix,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pszLogTag);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (rcExit2 != RTEXITCODE_SUCCESS)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync rcExit = rcExit2;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTMemTmpFree(pszSubPrefix);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync else
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "out of memory\n");
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTStrFree(pszMember);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync else
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: RTUtf16ToUtf8 failed on %s child#%u: %Rrc\n",
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pszLogTag, pszStructNm, i, rc);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /* TI_GET_OFFSET fails on bitfields, so just ignore+skip those. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync else if (enmErr != TI_GET_OFFSET || GetLastError() != ERROR_INVALID_FUNCTION)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: SymGetTypeInfo(,,,%d,) failed on %s child#%u: %u\n",
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pszLogTag, enmErr, pszStructNm, i, GetLastError());
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync LocalFree(pwszMember);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync } /* For each child. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync return rcExit;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync}
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync/**
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Lookup up structures and members in the given module.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync *
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @returns Fully bitched exit code.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param hFake Fake process handle.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param uModAddr The module address.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param pszLogTag The log tag.
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync * @param pszPdb The full PDB path.
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync * @param pOsVerInfo The OS version info for altering the error handling
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync * for older OSes.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsyncstatic RTEXITCODE findStructures(HANDLE hFake, uint64_t uModAddr, const char *pszLogTag, const char *pszPdb,
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync PCRTNTSDBOSVER pOsVerInfo)
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync{
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync PSYMBOL_INFO pSymInfo = (PSYMBOL_INFO)alloca(sizeof(*pSymInfo));
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync for (uint32_t iStruct = 0; iStruct < RT_ELEMENTS(g_aStructs); iStruct++)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pSymInfo->SizeOfStruct = sizeof(*pSymInfo);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pSymInfo->MaxNameLen = 0;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (!SymGetTypeFromName(hFake, uModAddr, g_aStructs[iStruct].pszName, pSymInfo))
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync {
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync if (!(pOsVerInfo->uMajorVer == 5 && pOsVerInfo->uMinorVer == 0) /* w2k */)
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Failed to find _KPRCB: %u\n", pszPdb, GetLastError());
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync RTMsgInfo("%s: Skipping - failed to find _KPRCB: %u\n", pszPdb, GetLastError());
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync return RTEXITCODE_SKIPPED;
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync MyDbgPrintf(" %s: TypeIndex=%u\n", g_aStructs[iStruct].pszName, pSymInfo->TypeIndex);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync MyDbgPrintf(" %s: Size=%u (%#x)\n", g_aStructs[iStruct].pszName, pSymInfo->Size, pSymInfo->Size);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync rcExit = findMembers(hFake, uModAddr, pSymInfo->TypeIndex,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync g_aStructs[iStruct].cMembers, g_aStructs[iStruct].paMembers, 0 /* offDisp */,
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync g_aStructs[iStruct].pszName, "", pszLogTag);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (rcExit != RTEXITCODE_SUCCESS)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync return rcExit;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync } /* for each struct we want */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync return rcExit;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync}
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsyncstatic bool strIEndsWith(const char *pszString, const char *pszSuffix)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync{
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync size_t cchString = strlen(pszString);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync size_t cchSuffix = strlen(pszSuffix);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (cchString < cchSuffix)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync return false;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync return RTStrICmp(pszString + cchString - cchSuffix, pszSuffix) == 0;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync}
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
0a468f537f2ac175b7cc7b54c32bfc84f1f04674vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync/**
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Use various hysterics to figure out the OS version details from the PDB path.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync *
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * This ASSUMES quite a bunch of things:
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * -# Working on unpacked symbol packages. This does not work for
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * windbg symbol stores/caches.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * -# The symbol package has been unpacked into a directory with the same
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * name as the symbol package (sans suffixes).
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync *
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @returns Fully complained exit code.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param pszPdb The path to the PDB.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param pVerInfo Where to return the version info.
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync * @param penmArch Where to return the architecture.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsyncstatic RTEXITCODE FigurePdbVersionInfo(const char *pszPdb, PRTNTSDBOSVER pVerInfo, MYARCH *penmArch)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync{
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync /*
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync * Split the path.
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync */
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync union
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync {
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync RTPATHSPLIT Split;
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync uint8_t abPad[RTPATH_MAX + 1024];
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync } u;
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync int rc = RTPathSplit(pszPdb, &u.Split, sizeof(u), 0);
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync if (RT_FAILURE(rc))
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTPathSplit failed on '%s': %Rrc", pszPdb, rc);
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync if (!(u.Split.fProps & RTPATH_PROP_FILENAME))
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTPATH_PROP_FILENAME not set for: '%s'", pszPdb);
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync const char *pszFilename = u.Split.apszComps[u.Split.cComps - 1];
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync /*
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync * SMP or UNI kernel?
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync */
8f65f0a635d0f2d4d9d07b5fe473f5b414c3f80avboxsync if ( !RTStrICmp(pszFilename, "ntkrnlmp.pdb")
8f65f0a635d0f2d4d9d07b5fe473f5b414c3f80avboxsync || !RTStrICmp(pszFilename, "ntkrpamp.pdb")
8f65f0a635d0f2d4d9d07b5fe473f5b414c3f80avboxsync )
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pVerInfo->fSmp = true;
8f65f0a635d0f2d4d9d07b5fe473f5b414c3f80avboxsync else if ( !RTStrICmp(pszFilename, "ntoskrnl.pdb")
8f65f0a635d0f2d4d9d07b5fe473f5b414c3f80avboxsync || !RTStrICmp(pszFilename, "ntkrnlpa.pdb")
8f65f0a635d0f2d4d9d07b5fe473f5b414c3f80avboxsync )
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pVerInfo->fSmp = false;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync else
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "Doesn't recognize the filename '%s'...", pszFilename);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync /*
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync * Look for symbol pack names in the path. This is stuff like:
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync * - WindowsVista.6002.090410-1830.x86fre
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync * - WindowsVista.6002.090410-1830.amd64chk
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync * - Windows_Win7.7600.16385.090713-1255.X64CHK
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync * - Windows_Win7SP1.7601.17514.101119-1850.AMD64FRE
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync * - Windows_Win8.9200.16384.120725-1247.X86CHK
762c72c98ae9be90e2ff8a05a500a75aae161100vboxsync * - en_windows_8_1_symbols_debug_checked_x64_2712568
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync */
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync bool fFound = false;
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync uint32_t i = u.Split.cComps - 1;
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync while (i-- > 0)
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync {
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync static struct
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync {
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync const char *pszPrefix;
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync size_t cchPrefix;
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync uint8_t uMajorVer;
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync uint8_t uMinorVer;
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync uint8_t uCsdNo;
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync uint32_t uBuildNo; /**< UINT32_MAX means the number immediately after the prefix. */
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync } const s_aSymPacks[] =
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync {
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync { RT_STR_TUPLE("w2kSP1SYM"), 5, 0, 1, 2195 },
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync { RT_STR_TUPLE("w2ksp2srp1"), 5, 0, 2, 2195 },
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync { RT_STR_TUPLE("w2ksp2sym"), 5, 0, 2, 2195 },
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync { RT_STR_TUPLE("w2ksp3sym"), 5, 0, 3, 2195 },
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync { RT_STR_TUPLE("w2ksp4sym"), 5, 0, 4, 2195 },
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync { RT_STR_TUPLE("Windows2000-KB891861"), 5, 0, 4, 2195 },
5efc3716063572a178abdb9c572ddc2bf68ac0abvboxsync { RT_STR_TUPLE("windowsxp"), 5, 1, 0, 2600 },
5efc3716063572a178abdb9c572ddc2bf68ac0abvboxsync { RT_STR_TUPLE("xpsp1sym"), 5, 1, 1, 2600 },
5efc3716063572a178abdb9c572ddc2bf68ac0abvboxsync { RT_STR_TUPLE("WindowsXP-KB835935-SP2-"), 5, 1, 2, 2600 },
5efc3716063572a178abdb9c572ddc2bf68ac0abvboxsync { RT_STR_TUPLE("WindowsXP-KB936929-SP3-"), 5, 1, 3, 2600 },
5efc3716063572a178abdb9c572ddc2bf68ac0abvboxsync { RT_STR_TUPLE("Windows2003."), 5, 2, 0, 3790 },
5efc3716063572a178abdb9c572ddc2bf68ac0abvboxsync { RT_STR_TUPLE("Windows2003_sp1."), 5, 2, 1, 3790 },
5efc3716063572a178abdb9c572ddc2bf68ac0abvboxsync { RT_STR_TUPLE("WindowsServer2003-KB933548-v1"), 5, 2, 1, 3790 },
5efc3716063572a178abdb9c572ddc2bf68ac0abvboxsync { RT_STR_TUPLE("WindowsVista.6000."), 6, 0, 0, 6000 },
5efc3716063572a178abdb9c572ddc2bf68ac0abvboxsync { RT_STR_TUPLE("Windows_Longhorn.6001."), 6, 0, 1, 6001 }, /* incl w2k8 */
5efc3716063572a178abdb9c572ddc2bf68ac0abvboxsync { RT_STR_TUPLE("WindowsVista.6002."), 6, 0, 2, 6002 }, /* incl w2k8 */
5efc3716063572a178abdb9c572ddc2bf68ac0abvboxsync { RT_STR_TUPLE("Windows_Winmain.7000"), 6, 1, 0, 7000 }, /* Beta */
5efc3716063572a178abdb9c572ddc2bf68ac0abvboxsync { RT_STR_TUPLE("Windows_Winmain.7100"), 6, 1, 0, 7100 }, /* RC */
5efc3716063572a178abdb9c572ddc2bf68ac0abvboxsync { RT_STR_TUPLE("Windows_Win7.7600"), 6, 1, 0, 7600 }, /* RC */
5efc3716063572a178abdb9c572ddc2bf68ac0abvboxsync { RT_STR_TUPLE("Windows_Win7SP1.7601"), 6, 1, 1, 7601 }, /* RC */
762c72c98ae9be90e2ff8a05a500a75aae161100vboxsync { RT_STR_TUPLE("Windows_Winmain.8102"), 6, 2, 0, 8102 }, /* preview */
762c72c98ae9be90e2ff8a05a500a75aae161100vboxsync { RT_STR_TUPLE("Windows_Winmain.8250"), 6, 2, 0, 8250 }, /* beta */
762c72c98ae9be90e2ff8a05a500a75aae161100vboxsync { RT_STR_TUPLE("Windows_Winmain.8400"), 6, 2, 0, 8400 }, /* RC */
762c72c98ae9be90e2ff8a05a500a75aae161100vboxsync { RT_STR_TUPLE("Windows_Win8.9200"), 6, 2, 0, 9200 }, /* RTM */
762c72c98ae9be90e2ff8a05a500a75aae161100vboxsync { RT_STR_TUPLE("en_windows_8_1"), 6, 3, 0, 9600 }, /* RTM */
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync };
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync
c33049ffa29c187c81c78c13b35978aed13ebb21vboxsync const char *pszComp = u.Split.apszComps[i];
c33049ffa29c187c81c78c13b35978aed13ebb21vboxsync uint32_t iSymPack = RT_ELEMENTS(s_aSymPacks);
c33049ffa29c187c81c78c13b35978aed13ebb21vboxsync while (iSymPack-- > 0)
c33049ffa29c187c81c78c13b35978aed13ebb21vboxsync if (!RTStrNICmp(pszComp, s_aSymPacks[iSymPack].pszPrefix, s_aSymPacks[iSymPack].cchPrefix))
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync break;
c33049ffa29c187c81c78c13b35978aed13ebb21vboxsync if (iSymPack >= RT_ELEMENTS(s_aSymPacks))
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync continue;
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync
c33049ffa29c187c81c78c13b35978aed13ebb21vboxsync pVerInfo->uMajorVer = s_aSymPacks[iSymPack].uMajorVer;
c33049ffa29c187c81c78c13b35978aed13ebb21vboxsync pVerInfo->uMinorVer = s_aSymPacks[iSymPack].uMinorVer;
c33049ffa29c187c81c78c13b35978aed13ebb21vboxsync pVerInfo->uCsdNo = s_aSymPacks[iSymPack].uCsdNo;
5efc3716063572a178abdb9c572ddc2bf68ac0abvboxsync pVerInfo->fChecked = false;
c33049ffa29c187c81c78c13b35978aed13ebb21vboxsync pVerInfo->uBuildNo = s_aSymPacks[iSymPack].uBuildNo;
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync /* Parse build number if necessary. */
c33049ffa29c187c81c78c13b35978aed13ebb21vboxsync if (s_aSymPacks[iSymPack].uBuildNo == UINT32_MAX)
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync {
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync char *pszNext;
c33049ffa29c187c81c78c13b35978aed13ebb21vboxsync rc = RTStrToUInt32Ex(pszComp + s_aSymPacks[iSymPack].cchPrefix, &pszNext, 10, &pVerInfo->uBuildNo);
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync if (RT_FAILURE(rc))
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to decode build number in '%s': %Rrc", pszComp, rc);
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync if (*pszNext != '.' && *pszNext != '_' && *pszNext != '-')
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to decode build number in '%s': '%c'", pszComp, *pszNext);
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync }
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync /* Look for build arch and checked/free. */
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync if ( RTStrIStr(pszComp, ".x86.chk.")
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync || RTStrIStr(pszComp, ".x86chk.")
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync || RTStrIStr(pszComp, "_x86_chk_")
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync || RTStrIStr(pszComp, "_x86chk_")
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync || RTStrIStr(pszComp, "-x86-DEBUG")
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync || (RTStrIStr(pszComp, "-x86-") && RTStrIStr(pszComp, "-DEBUG"))
762c72c98ae9be90e2ff8a05a500a75aae161100vboxsync || RTStrIStr(pszComp, "_debug_checked_x86")
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync )
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync {
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync pVerInfo->fChecked = true;
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync *penmArch = MYARCH_X86;
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync }
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync else if ( RTStrIStr(pszComp, ".amd64.chk.")
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync || RTStrIStr(pszComp, ".amd64chk.")
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync || RTStrIStr(pszComp, ".x64.chk.")
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync || RTStrIStr(pszComp, ".x64chk.")
762c72c98ae9be90e2ff8a05a500a75aae161100vboxsync || RTStrIStr(pszComp, "_debug_checked_x64")
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync )
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync {
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync pVerInfo->fChecked = true;
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync *penmArch = MYARCH_AMD64;
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync }
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync else if ( RTStrIStr(pszComp, ".amd64.fre.")
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync || RTStrIStr(pszComp, ".amd64fre.")
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync || RTStrIStr(pszComp, ".x64.fre.")
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync || RTStrIStr(pszComp, ".x64fre.")
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync )
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync {
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync pVerInfo->fChecked = false;
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync *penmArch = MYARCH_AMD64;
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync }
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync else if ( RTStrIStr(pszComp, "DEBUG")
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync || RTStrIStr(pszComp, "_chk")
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync )
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync {
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync pVerInfo->fChecked = true;
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync *penmArch = MYARCH_X86;
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync }
762c72c98ae9be90e2ff8a05a500a75aae161100vboxsync else if (RTStrIStr(pszComp, "_x64"))
762c72c98ae9be90e2ff8a05a500a75aae161100vboxsync {
762c72c98ae9be90e2ff8a05a500a75aae161100vboxsync pVerInfo->fChecked = false;
762c72c98ae9be90e2ff8a05a500a75aae161100vboxsync *penmArch = MYARCH_AMD64;
762c72c98ae9be90e2ff8a05a500a75aae161100vboxsync }
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync else
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync {
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync pVerInfo->fChecked = false;
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync *penmArch = MYARCH_X86;
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync }
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync return RTEXITCODE_SUCCESS;
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync }
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "Giving up on '%s'...\n", pszPdb);
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync}
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync/**
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Process one PDB.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync *
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @returns Fully bitched exit code.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param pszPdb The path to the PDB.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsyncstatic RTEXITCODE processPdb(const char *pszPdb)
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync{
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync /*
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync * We need the size later on, so get that now and present proper IPRT error
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync * info if the file is missing or inaccessible.
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync */
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync RTFSOBJINFO ObjInfo;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync int rc = RTPathQueryInfoEx(pszPdb, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_FOLLOW_LINK);
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync if (RT_FAILURE(rc))
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTPathQueryInfo fail on '%s': %Rrc\n", pszPdb, rc);
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /*
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Figure the windows version details for the given PDB.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync MYARCH enmArch;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTNTSDBOSVER OsVerInfo;
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync RTEXITCODE rcExit = FigurePdbVersionInfo(pszPdb, &OsVerInfo, &enmArch);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (rcExit != RTEXITCODE_SUCCESS)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to figure the OS version info for '%s'.\n'", pszPdb);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync /*
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync * Create a fake handle and open the PDB.
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync */
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync static uintptr_t s_iHandle = 0;
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync HANDLE hFake = (HANDLE)++s_iHandle;
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync if (!SymInitialize(hFake, NULL, FALSE))
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "SymInitialied failed: %u\n", GetLastError());
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync uint64_t uModAddr = UINT64_C(0x1000000);
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync uModAddr = SymLoadModuleEx(hFake, NULL /*hFile*/, pszPdb, NULL /*pszModuleName*/,
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync uModAddr, ObjInfo.cbObject, NULL /*pData*/, 0 /*fFlags*/);
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync if (uModAddr != 0)
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync MyDbgPrintf("*** uModAddr=%#llx \"%s\" ***\n", uModAddr, pszPdb);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync char szLogTag[32];
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTStrCopy(szLogTag, sizeof(szLogTag), RTPathFilename(pszPdb));
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync /*
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Find the structures.
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync */
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync rcExit = findStructures(hFake, uModAddr, szLogTag, pszPdb, &OsVerInfo);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (rcExit == RTEXITCODE_SUCCESS)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync rcExit = checkThatWeFoundEverything();
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (rcExit == RTEXITCODE_SUCCESS)
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /*
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Save the details for later when we produce the header.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync rcExit = saveStructures(&OsVerInfo, enmArch, pszPdb);
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync }
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync else
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "SymLoadModuleEx failed: %u\n", GetLastError());
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync if (!SymCleanup(hFake))
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "SymCleanup failed: %u\n", GetLastError());
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync if (rcExit == RTEXITCODE_SKIPPED)
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync rcExit = RTEXITCODE_SUCCESS;
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync return rcExit;
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync}
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync/** The size of the directory entry buffer we're using. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync#define MY_DIRENTRY_BUF_SIZE (sizeof(RTDIRENTRYEX) + RTPATH_MAX)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync/**
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync * Checks if the name is of interest to us.
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync *
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync * @returns true/false.
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync * @param pszName The name.
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync * @param cchName The length of the name.
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync */
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsyncstatic bool isInterestingName(const char *pszName, size_t cchName)
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync{
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync static struct { const char *psz; size_t cch; } const s_aNames[] =
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync {
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync RT_STR_TUPLE("ntoskrnl.pdb"),
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync RT_STR_TUPLE("ntkrnlmp.pdb"),
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync RT_STR_TUPLE("ntkrnlpa.pdb"),
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync RT_STR_TUPLE("ntkrpamp.pdb"),
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync };
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync if ( cchName == s_aNames[0].cch
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync && (pszName[0] == 'n' || pszName[0] == 'N')
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync && (pszName[1] == 't' || pszName[1] == 'T')
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync )
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync {
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync int i = RT_ELEMENTS(s_aNames);
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync while (i-- > 0)
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync if ( s_aNames[i].cch == cchName
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync && !RTStrICmp(s_aNames[i].psz, pszName))
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync return true;
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync }
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync return false;
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync}
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync/**
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Recursively processes relevant files in the specified directory.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync *
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @returns Fully complained exit code.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param pszDir Pointer to the directory buffer.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param cchDir The length of pszDir in pszDir.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param pDirEntry Pointer to the directory buffer.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsyncstatic RTEXITCODE processDirSub(char *pszDir, size_t cchDir, PRTDIRENTRYEX pDirEntry, int iLogDepth)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync{
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync Assert(cchDir > 0); Assert(pszDir[cchDir] == '\0');
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /* Make sure we've got some room in the path, to save us extra work further down. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (cchDir + 3 >= RTPATH_MAX)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "Path too long: '%s'\n", pszDir);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /* Open directory. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync PRTDIR pDir;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync int rc = RTDirOpen(&pDir, pszDir);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (RT_FAILURE(rc))
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTDirOpen failed on '%s': %Rrc\n", pszDir, rc);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /* Ensure we've got a trailing slash (there is space for it see above). */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (!RTPATH_IS_SEP(pszDir[cchDir - 1]))
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pszDir[cchDir++] = RTPATH_SLASH;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync pszDir[cchDir] = '\0';
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /*
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Process the files and subdirs.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync for (;;)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /* Get the next directory. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync size_t cbDirEntry = MY_DIRENTRY_BUF_SIZE;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync rc = RTDirReadEx(pDir, pDirEntry, &cbDirEntry, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (RT_FAILURE(rc))
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync break;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /* Skip the dot and dot-dot links. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if ( (pDirEntry->cbName == 1 && pDirEntry->szName[0] == '.')
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync || (pDirEntry->cbName == 2 && pDirEntry->szName[0] == '.' && pDirEntry->szName[1] == '.'))
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync continue;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /* Check length. */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (pDirEntry->cbName + cchDir + 3 >= RTPATH_MAX)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Path too long: '%s' in '%.*s'\n", pDirEntry->szName, cchDir, pszDir);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync break;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (RTFS_IS_FILE(pDirEntry->Info.Attr.fMode))
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync /*
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync * Process debug info files of interest.
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync */
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync if (isInterestingName(pDirEntry->szName, pDirEntry->cbName))
8f65f0a635d0f2d4d9d07b5fe473f5b414c3f80avboxsync {
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync memcpy(&pszDir[cchDir], pDirEntry->szName, pDirEntry->cbName + 1);
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync RTEXITCODE rcExit2 = processPdb(pszDir);
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync if (rcExit2 != RTEXITCODE_SUCCESS)
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync rcExit = rcExit2;
8f65f0a635d0f2d4d9d07b5fe473f5b414c3f80avboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync else if (RTFS_IS_DIRECTORY(pDirEntry->Info.Attr.fMode))
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync /*
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync * Recurse into the subdirectory. In order to speed up Win7+
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync * symbol pack traversals, we skip directories with ".pdb" suffixes
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync * unless they match any of the .pdb files we're looking for.
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync *
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Note! When we get back pDirEntry will be invalid.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync if ( pDirEntry->cbName <= 4
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync || RTStrICmp(&pDirEntry->szName[pDirEntry->cbName - 4], ".pdb")
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync || isInterestingName(pDirEntry->szName, pDirEntry->cbName))
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync {
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync memcpy(&pszDir[cchDir], pDirEntry->szName, pDirEntry->cbName + 1);
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync if (iLogDepth > 0)
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync RTMsgInfo("%s%s ...\n", pszDir, RTPATH_SLASH_STR);
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync RTEXITCODE rcExit2 = processDirSub(pszDir, cchDir + pDirEntry->cbName, pDirEntry, iLogDepth - 1);
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync if (rcExit2 != RTEXITCODE_SUCCESS)
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync rcExit = rcExit2;
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (rc != VERR_NO_MORE_FILES)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "RTDirReadEx failed: %Rrc\npszDir=%.*s", rc, cchDir, pszDir);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync rc = RTDirClose(pDir);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (RT_FAILURE(rc))
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "RTDirClose failed: %Rrc\npszDir=%.*s", rc, cchDir, pszDir);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync return rcExit;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync}
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync/**
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * Recursively processes relevant files in the specified directory.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync *
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @returns Fully complained exit code.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync * @param pszDir The directory to search.
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync */
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsyncstatic RTEXITCODE processDir(const char *pszDir)
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync{
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync char szPath[RTPATH_MAX];
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync int rc = RTPathAbs(pszDir, szPath, sizeof(szPath));
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync if (RT_FAILURE(rc))
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTPathAbs failed on '%s': %Rrc\n", pszDir, rc);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync union
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync uint8_t abPadding[MY_DIRENTRY_BUF_SIZE];
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTDIRENTRYEX DirEntry;
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync } uBuf;
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync return processDirSub(szPath, strlen(szPath), &uBuf.DirEntry, g_iOptVerbose);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync}
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsyncint main(int argc, char **argv)
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync{
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync int rc = RTR3InitExe(argc, &argv, 0 /*fFlags*/);
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync if (RT_FAILURE(rc))
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync return RTMsgInitFailure(rc);
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync RTListInit(&g_SetList);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync /*
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync * Parse options.
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync */
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync static const RTGETOPTDEF s_aOptions[] =
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync {
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync { "--force", 'f', RTGETOPT_REQ_NOTHING },
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync { "--output", 'o', RTGETOPT_REQ_STRING },
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync { "--verbose", 'v', RTGETOPT_REQ_NOTHING },
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync { "--quiet", 'q', RTGETOPT_REQ_NOTHING },
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync };
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync const char *pszOutput = "-";
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync int ch;
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync RTGETOPTUNION ValueUnion;
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync RTGETOPTSTATE GetState;
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1,
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync RTGETOPTINIT_FLAGS_OPTS_FIRST);
f4eb9833d0bf82024b2a64c205fae154c1e8b770vboxsync while ((ch = RTGetOpt(&GetState, &ValueUnion)) != 0)
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync {
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync switch (ch)
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync {
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync case 'f':
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync g_fOptForce = true;
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync break;
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync case 'v':
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync g_iOptVerbose++;
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync break;
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync case 'q':
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync g_iOptVerbose++;
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync break;
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync case 'o':
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync pszOutput = ValueUnion.psz;
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync break;
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync case 'V':
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync RTPrintf("$Revision$");
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync break;
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync case 'h':
230654b26af53ddc6efd70365a1347c36e03e5b4vboxsync RTPrintf("usage: %s [-v|--verbose] [-q|--quiet] [-f|--force] [-o|--output <file.h>] <dir1|pdb1> [...]\n"
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync " or: %s [-V|--version]\n"
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync " or: %s [-h|--help]\n",
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync argv[0], argv[0], argv[0]);
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync return RTEXITCODE_SUCCESS;
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync case VINF_GETOPT_NOT_OPTION:
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync {
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync RTEXITCODE rcExit2;
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync if (RTFileExists(ValueUnion.psz))
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync rcExit2 = processPdb(ValueUnion.psz);
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync else
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync rcExit2 = processDir(ValueUnion.psz);
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync if (rcExit2 != RTEXITCODE_SUCCESS)
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync {
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync if (!g_fOptForce)
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync return rcExit2;
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync rcExit = rcExit2;
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync }
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync break;
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync }
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync default:
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync return RTGetOptPrintError(ch, &ValueUnion);
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync }
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync }
5efc3716063572a178abdb9c572ddc2bf68ac0abvboxsync if (RTListIsEmpty(&g_SetList))
5efc3716063572a178abdb9c572ddc2bf68ac0abvboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "No usable debug files found.\n");
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync /*
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync * Generate the output.
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync */
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync PRTSTREAM pOut = g_pStdOut;
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync if (strcmp(pszOutput, "-"))
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync {
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync rc = RTStrmOpen(pszOutput, "w", &pOut);
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync if (RT_FAILURE(rc))
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error opening '%s' for writing: %Rrc\n", pszOutput, rc);
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync }
be8a316f38a47c77279ec3eefdca315d8ea05de9vboxsync
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync generateHeader(pOut);
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync if (pOut != g_pStdOut)
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync rc = RTStrmClose(pOut);
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync else
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync rc = RTStrmFlush(pOut);
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync if (RT_FAILURE(rc))
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error %s '%s': %Rrc\n", pszOutput,
30949e413b17e12e9d6cecd6ccf02ca09dde2e67vboxsync pOut != g_pStdOut ? "closing" : "flushing", rc);
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync return rcExit;
f43a0c088fd5cc014b52d34b0e7d23b9e5ca5858vboxsync}