File:  [WindowsNT SDKs] / mstools / samples / sdktools / image / imagehlp / debug.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 18:24:28 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: ntsdk-nov-1993, ntsdk-jul-1993, HEAD
Microsoft Windows NT Build 511 (SDK Final Release) 07-24-1993

/*++

Copyright (c) 1993  Microsoft Corporation

Module Name:

    debug.c

Abstract:

    This module implements functions for splitting debugging information
    out of an image file and into a separate .DBG file.

Author:

    Steven R. Wood 4-May-1993

Revision History:

--*/

#include <windows.h>
#include <imagehlp.h>
#include <stdio.h>

// Helper routines

PIMAGE_NT_HEADERS
ImageNtHeader (
    IN PVOID Base
    );

PVOID
ImageDirectoryEntryToData (
    IN PVOID Base,
    IN BOOLEAN MappedAsImage,
    IN USHORT DirectoryEntry,
    OUT PULONG Size
    );

BOOL
SplitSymbols(
    LPSTR ImageName,
    LPSTR SymbolsPath,
    LPSTR SymbolFilePath
    )
{
    HANDLE FileHandle, SymbolFileHandle;
    HANDLE hMappedFile;
    LPVOID ImageBase;
    PIMAGE_NT_HEADERS NtHeaders;
    LPSTR ImageFileName;
    LPVOID Symbols, SymbolsToFree;
    DWORD SizeOfSymbols, Unused, ImageNameOffset, cb;
    PIMAGE_SECTION_HEADER Sections;
    DWORD SectionNumber, BytesWritten, BytesRead, NewFileSize, HeaderSum, CheckSum;
    PIMAGE_DEBUG_DIRECTORY DebugDirectories;
    PIMAGE_DEBUG_DIRECTORY DebugDirectory;
    PIMAGE_DEBUG_DIRECTORY MiscDebugDirectory;
    PIMAGE_DEBUG_DIRECTORY FpoDebugDirectory;
    DWORD DebugDirectorySize, DbgFileHeaderSize, NumberOfDebugDirectories;
    IMAGE_SEPARATE_DEBUG_HEADER DbgFileHeader;
    PIMAGE_EXPORT_DIRECTORY ExportDirectory;
    DWORD  ExportedNamesSize;
    LPDWORD pp;
    LPSTR ExportedNames, Src, Dst;
    DWORD i, RvaOffset, ExportDirectorySize;
    PFPO_DATA FpoTable;
    DWORD FpoTableSize;
    PIMAGE_RUNTIME_FUNCTION_ENTRY RuntimeFunctionTable, pSrc;
    DWORD RuntimeFunctionTableSize;
    PIMAGE_FUNCTION_ENTRY FunctionTable, pDst;
    DWORD FunctionTableSize;
    ULONG NumberOfFunctionTableEntries;
    IMAGE_DEBUG_DIRECTORY PhonyFPODbgDir;
    DWORD SavedErrorCode;
    BOOL InsertExtensionSubDir;
    LPSTR ImageFilePathToSaveInImage;

    ImageFileName = ImageName + strlen( ImageName );
    while (ImageFileName > ImageName) {
        if (ImageFileName[ -1 ] == '\\' ||
            ImageFileName[ -1 ] == '/' ||
            ImageFileName[ -1 ] == ':'
           ) {
            break;
            }
        else {
            ImageFileName -= 1;
            }
        }

    if (SymbolsPath == NULL ||
        SymbolsPath[ 0 ] == '\0' ||
        SymbolsPath[ 0 ] == '.'
       ) {
        strncpy( SymbolFilePath, ImageName, ImageFileName - ImageName );
        SymbolFilePath[ ImageFileName - ImageName ] = '\0';
        InsertExtensionSubDir = FALSE;
        }
    else {
        strcpy( SymbolFilePath, SymbolsPath );
        InsertExtensionSubDir = TRUE;
        }

    Dst = SymbolFilePath + strlen( SymbolFilePath );
    if (Dst > SymbolFilePath && Dst[-1] != '\\' && Dst[-1] != '/' && Dst[-1] != ':') {
        *Dst++ = '\\';
        }
    ImageFilePathToSaveInImage = Dst;
    Src = strrchr( ImageFileName, '.' );
    if (Src != NULL && InsertExtensionSubDir) {
        while (*Dst = *++Src) {
            Dst += 1;
            }
        *Dst++ = '\\';
        }
    strcpy( Dst, ImageFileName );
    Dst = strrchr( Dst, '.' );
    if (Dst == NULL) {
        Dst = SymbolFilePath + strlen( SymbolFilePath );
        }
    strcpy( Dst, ".DBG" );

    //
    // open and map the file.
    //
    FileHandle = CreateFile( ImageName,
                             GENERIC_READ | GENERIC_WRITE,
                             FILE_SHARE_READ,
                             NULL,
                             OPEN_EXISTING,
                             0,
                             NULL
                           );


    if (FileHandle == INVALID_HANDLE_VALUE) {
        return FALSE;
        }

    hMappedFile = CreateFileMapping( FileHandle,
                                     NULL,
                                     PAGE_READWRITE,
                                     0,
                                     0,
                                     NULL
                                   );
    if (!hMappedFile) {
        CloseHandle( FileHandle );
        return FALSE;
        }

    ImageBase = MapViewOfFile( hMappedFile,
                               FILE_MAP_WRITE,
                               0,
                               0,
                               0
                             );
    if (!ImageBase) {
        CloseHandle( hMappedFile );
        CloseHandle( FileHandle );
        return FALSE;
        }

    //
    // Everything is mapped. Now check the image and find nt image headers
    //

    NtHeaders = ImageNtHeader( ImageBase );
    if (NtHeaders == NULL) {
        UnmapViewOfFile( ImageBase );
        CloseHandle( hMappedFile );
        CloseHandle( FileHandle );
        SetLastError( ERROR_BAD_EXE_FORMAT );
        return FALSE;
        }

    if (NtHeaders->OptionalHeader.MajorLinkerVersion < 2 ||
        NtHeaders->OptionalHeader.MinorLinkerVersion < 5
       ) {
        UnmapViewOfFile( ImageBase );
        CloseHandle( hMappedFile );
        CloseHandle( FileHandle );
        SetLastError( ERROR_BAD_EXE_FORMAT );
        return FALSE;
        }

    if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED) {
        UnmapViewOfFile( ImageBase );
        CloseHandle( hMappedFile );
        CloseHandle( FileHandle );
        SetLastError( ERROR_ALREADY_ASSIGNED );
        return FALSE;
        }

    DebugDirectories = ImageDirectoryEntryToData( ImageBase,
                                                  FALSE,
                                                  IMAGE_DIRECTORY_ENTRY_DEBUG,
                                                  &DebugDirectorySize
                                                );
    if (DebugDirectories == NULL || DebugDirectorySize == 0) {
        UnmapViewOfFile( ImageBase );
        CloseHandle( hMappedFile );
        CloseHandle( FileHandle );
        SetLastError( ERROR_BAD_EXE_FORMAT );
        return FALSE;
        }
    NumberOfDebugDirectories = DebugDirectorySize / sizeof( IMAGE_DEBUG_DIRECTORY );

    Sections = IMAGE_FIRST_SECTION( NtHeaders );
    for (SectionNumber = 0;
         SectionNumber < NtHeaders->FileHeader.NumberOfSections;
         SectionNumber++
        ) {
        if (Sections[ SectionNumber ].PointerToRawData != 0 &&
            !stricmp( Sections[ SectionNumber ].Name, ".debug" )
           ) {
            break;
            }
        }

    FpoTable = NULL;
    SymbolsToFree = NULL;
    ExportedNames = NULL;
    MiscDebugDirectory = NULL;
    FpoDebugDirectory = NULL;
    if (SectionNumber >= NtHeaders->FileHeader.NumberOfSections) {
        if (NtHeaders->FileHeader.PointerToSymbolTable == 0 ||
            NtHeaders->FileHeader.NumberOfSymbols == 0
           ) {
            goto nosyms;
            }

        NewFileSize = NtHeaders->FileHeader.PointerToSymbolTable;
        DebugDirectory = DebugDirectories;
        for (i=0; i<NumberOfDebugDirectories; i++) {
            if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_MISC) {
                NewFileSize = DebugDirectory->PointerToRawData +
                              DebugDirectory->SizeOfData;
                MiscDebugDirectory = DebugDirectory;
                }
            else
            if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_FPO) {
                FpoTableSize = DebugDirectory->SizeOfData;
                FpoTable = VirtualAlloc( NULL,
                                         FpoTableSize,
                                         MEM_COMMIT,
                                         PAGE_READWRITE
                                       );
                if ( FpoTable == NULL) {
                    goto nosyms;
                    }
                if (SetFilePointer( FileHandle,
                                    DebugDirectory->PointerToRawData,
                                    NULL,
                                    FILE_BEGIN
                                  ) != DebugDirectory->PointerToRawData
                   ) {
                    goto nosyms;
                    }

                if (!ReadFile( FileHandle, FpoTable, FpoTableSize, &BytesRead, NULL ) ||
                    FpoTableSize != BytesRead
                   ) {
                    goto nosyms;
                    }
                }

            DebugDirectory += 1;
            }

        SizeOfSymbols = GetFileSize( FileHandle, &Unused ) - NewFileSize;
        Symbols = VirtualAlloc( NULL,
                                SizeOfSymbols,
                                MEM_COMMIT,
                                PAGE_READWRITE
                              );
        if (Symbols == NULL) {
            goto nosyms;
            }
        SymbolsToFree = Symbols;

        if (SetFilePointer( FileHandle,
                            NewFileSize,
                            NULL,
                            FILE_BEGIN
                          ) != NewFileSize
           ) {
            goto nosyms;
            }

        if (!ReadFile( FileHandle, Symbols, SizeOfSymbols, &BytesRead, NULL ) ||
            SizeOfSymbols != BytesRead
           ) {
            goto nosyms;
            }
        Sections = NULL;
        }
    else {
        NewFileSize = Sections[ SectionNumber ].PointerToRawData;
        DebugDirectory = DebugDirectories;
        for (i=0; i<NumberOfDebugDirectories; i++) {
            if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_MISC) {
                NewFileSize = DebugDirectory->PointerToRawData +
                              DebugDirectory->SizeOfData;
                MiscDebugDirectory = DebugDirectory;
                }
            else
            if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_FPO) {
                FpoTableSize = DebugDirectory->SizeOfData;
                FpoTable = VirtualAlloc( NULL,
                                         FpoTableSize,
                                         MEM_COMMIT,
                                         PAGE_READWRITE
                                       );
                if ( FpoTable == NULL) {
                    goto nosyms;
                    }

                memmove( FpoTable,
                         ((PCHAR)ImageBase + DebugDirectory->PointerToRawData),
                         FpoTableSize
                       );
                }

            DebugDirectory += 1;
            }

        Symbols = (PCHAR)ImageBase + NewFileSize;
        SizeOfSymbols = GetFileSize( FileHandle, &Unused ) - NewFileSize;
        }

    ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)
        ImageDirectoryEntryToData( ImageBase,
                                   FALSE,
                                   IMAGE_DIRECTORY_ENTRY_EXPORT,
                                   &ExportDirectorySize
                                 );
    if (ExportDirectory) {
        //
        // This particular piece of magic gets us the RVA of the
        // EXPORT section.  Dont ask.
        //

        RvaOffset = (DWORD)
            ImageDirectoryEntryToData( ImageBase,
                                       TRUE,
                                       IMAGE_DIRECTORY_ENTRY_EXPORT,
                                       &ExportDirectorySize
                                     ) - (DWORD)ImageBase;

        pp = (LPDWORD)((DWORD)ExportDirectory +
                      (DWORD)ExportDirectory->AddressOfNames - RvaOffset
                     );

        ExportedNamesSize = 1;
        for (i=0; i<ExportDirectory->NumberOfNames; i++) {
            Src = (LPSTR)((DWORD)ExportDirectory + *pp++ - RvaOffset);
            ExportedNamesSize += strlen( Src ) + 1;
            }
        ExportedNamesSize = (ExportedNamesSize + 16) & ~15;

        Dst = (LPSTR)LocalAlloc( LPTR, ExportedNamesSize );
        if (Dst != NULL) {
            ExportedNames = Dst;
            pp = (LPDWORD)((DWORD)ExportDirectory +
                          (DWORD)ExportDirectory->AddressOfNames - RvaOffset
                         );
            for (i=0; i<ExportDirectory->NumberOfNames; i++) {
                Src = (LPSTR)((DWORD)ExportDirectory + *pp++ - RvaOffset);
                while (*Dst++ = *Src++) {
                    }
                }
            }
        }
    else {
        ExportedNamesSize = 0;
        }

    RuntimeFunctionTable = (PIMAGE_RUNTIME_FUNCTION_ENTRY)
        ImageDirectoryEntryToData( ImageBase,
                                   FALSE,
                                   IMAGE_DIRECTORY_ENTRY_EXCEPTION,
                                   &RuntimeFunctionTableSize
                                 );
    if (RuntimeFunctionTable == NULL) {
        RuntimeFunctionTableSize = 0;
        FunctionTableSize = 0;
        FunctionTable = NULL;
        }
    else {
        NumberOfFunctionTableEntries = RuntimeFunctionTableSize / sizeof( IMAGE_RUNTIME_FUNCTION_ENTRY );
        FunctionTableSize = NumberOfFunctionTableEntries * sizeof( IMAGE_FUNCTION_ENTRY );
        FunctionTable = (PIMAGE_FUNCTION_ENTRY)VirtualAlloc( NULL,
                                                             FunctionTableSize,
                                                             MEM_COMMIT,
                                                             PAGE_READWRITE
                                                           );
        if (FunctionTable == NULL) {
            goto nosyms;
            }

        pSrc = RuntimeFunctionTable;
        pDst = FunctionTable;
        for (i=0; i<NumberOfFunctionTableEntries; i++) {
            //
            // Make .pdata entries in .DBG file relative.
            //
            pDst->StartingAddress = pSrc->BeginAddress - NtHeaders->OptionalHeader.ImageBase;
            pDst->EndingAddress = pSrc->EndAddress - NtHeaders->OptionalHeader.ImageBase;
            pDst->EndOfPrologue = pSrc->PrologEndAddress - NtHeaders->OptionalHeader.ImageBase;
            pSrc += 1;
            pDst += 1;
            }
        }

    if (!MakeSureDirectoryPathExists( SymbolFilePath )) {
        return FALSE;
        }

    SymbolFileHandle = CreateFile( SymbolFilePath,
                                   GENERIC_WRITE,
                                   0,
                                   NULL,
                                   CREATE_ALWAYS,
                                   0,
                                   NULL
                                 );
    if (SymbolFileHandle == INVALID_HANDLE_VALUE) {
        goto nosyms;
        }

    DbgFileHeaderSize = sizeof( DbgFileHeader ) +
                        (NtHeaders->FileHeader.NumberOfSections * sizeof( IMAGE_SECTION_HEADER )) +
                        ExportedNamesSize +
                        FunctionTableSize +
                        DebugDirectorySize;
    if (FunctionTable != NULL) {
        DbgFileHeaderSize += sizeof( PhonyFPODbgDir );
        memset( &PhonyFPODbgDir, 0, sizeof( PhonyFPODbgDir ) );
        PhonyFPODbgDir.Type = IMAGE_DEBUG_TYPE_EXCEPTION;
        PhonyFPODbgDir.SizeOfData = FunctionTableSize;
        PhonyFPODbgDir.PointerToRawData = DbgFileHeaderSize -
                                          FunctionTableSize;
        if (Sections != NULL) {
            PhonyFPODbgDir.PointerToRawData -= sizeof( IMAGE_SECTION_HEADER );
            }
        }
    DbgFileHeaderSize = ((DbgFileHeaderSize + 15) & ~15);

    if (SetFilePointer( SymbolFileHandle,
                        DbgFileHeaderSize,
                        NULL,
                        FILE_BEGIN
                      ) != DbgFileHeaderSize
       ) {
        BytesWritten = 0;
        }
    else {
        if (!WriteFile( SymbolFileHandle,
                        Symbols,
                        SizeOfSymbols,
                        &BytesWritten,
                        NULL
                      )
           ) {
            BytesWritten = 0;
            }
        }

    if (BytesWritten == SizeOfSymbols) {
        cb = DebugDirectorySize;
        DebugDirectory = DebugDirectories;
        while (cb >= sizeof( *DebugDirectory )) {
            if (DebugDirectory->AddressOfRawData) {
                DebugDirectory->AddressOfRawData = 0;
                }

            if (NewFileSize <= DebugDirectory->PointerToRawData) {
                DebugDirectory->PointerToRawData -= NewFileSize;
                DebugDirectory->PointerToRawData += DbgFileHeaderSize;
                }

            if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_FPO) {
                PhonyFPODbgDir = *DebugDirectory;
                DebugDirectory->PointerToRawData = NewFileSize;
                }

            DebugDirectory += 1;
            cb -= sizeof( *DebugDirectory );
            }

        NtHeaders->FileHeader.PointerToSymbolTable = 0;
        NtHeaders->FileHeader.Characteristics |= IMAGE_FILE_DEBUG_STRIPPED;

        if (Sections != NULL) {
            NtHeaders->OptionalHeader.SizeOfImage = Sections[ SectionNumber ].VirtualAddress;
            NtHeaders->OptionalHeader.SizeOfInitializedData -= Sections[ SectionNumber ].SizeOfRawData;
            NtHeaders->FileHeader.NumberOfSections -= 1;
            }

        if (MiscDebugDirectory != NULL && MiscDebugDirectory->Type == IMAGE_DEBUG_TYPE_MISC) {
            ImageNameOffset = MiscDebugDirectory->PointerToRawData +
                              FIELD_OFFSET( IMAGE_DEBUG_MISC, Data );
            if (SetFilePointer( FileHandle, ImageNameOffset, NULL, FILE_BEGIN ) == ImageNameOffset) {
                WriteFile( FileHandle, ImageFilePathToSaveInImage, strlen( ImageFilePathToSaveInImage ) + 1, &Unused, NULL );
                }
            }

        if (FpoTable) {
            memcpy( (PCHAR)ImageBase + NewFileSize,
                    FpoTable,
                    FpoTableSize
                  );

            NewFileSize += PhonyFPODbgDir.SizeOfData;
            }

        CheckSumMappedFile( ImageBase,
                            NewFileSize,
                            &HeaderSum,
                            &CheckSum
                          );
        NtHeaders->OptionalHeader.CheckSum = CheckSum;

        DbgFileHeader.Signature = IMAGE_SEPARATE_DEBUG_SIGNATURE;
        DbgFileHeader.Flags = 0;
        DbgFileHeader.Machine = NtHeaders->FileHeader.Machine;
        DbgFileHeader.Characteristics = NtHeaders->FileHeader.Characteristics;
        DbgFileHeader.TimeDateStamp = NtHeaders->FileHeader.TimeDateStamp;
        DbgFileHeader.CheckSum = CheckSum;
        DbgFileHeader.ImageBase = NtHeaders->OptionalHeader.ImageBase;
        DbgFileHeader.SizeOfImage = NtHeaders->OptionalHeader.SizeOfImage;
        DbgFileHeader.ExportedNamesSize = ExportedNamesSize;
        DbgFileHeader.DebugDirectorySize = DebugDirectorySize;
        DbgFileHeader.NumberOfSections = NtHeaders->FileHeader.NumberOfSections;
        memset( DbgFileHeader.Reserved, 0, sizeof( DbgFileHeader.Reserved ) );
        DebugDirectory = DebugDirectories;

        SetFilePointer( SymbolFileHandle, 0, NULL, FILE_BEGIN );
        WriteFile( SymbolFileHandle,
                   &DbgFileHeader,
                   sizeof( DbgFileHeader ),
                   &BytesWritten,
                   NULL
                 );
        WriteFile( SymbolFileHandle,
                   IMAGE_FIRST_SECTION( NtHeaders ),
                   sizeof( IMAGE_SECTION_HEADER ) * NtHeaders->FileHeader.NumberOfSections,
                   &BytesWritten,
                   NULL
                 );

        if (ExportedNamesSize) {
            WriteFile( SymbolFileHandle,
                       ExportedNames,
                       ExportedNamesSize,
                       &BytesWritten,
                       NULL
                     );
            }

        if (FunctionTable) {
            WriteFile( SymbolFileHandle,
                       &PhonyFPODbgDir,
                       sizeof( PhonyFPODbgDir ),
                       &BytesWritten,
                       NULL
                     );
            }
        else
        if (FpoTable) {
            WriteFile( SymbolFileHandle,
                       &PhonyFPODbgDir,
                       sizeof( PhonyFPODbgDir ),
                       &BytesWritten,
                       NULL
                     );
            DebugDirectory += 1;
            DebugDirectorySize -= sizeof( PhonyFPODbgDir );
            }

        WriteFile( SymbolFileHandle,
                   DebugDirectory,
                   DebugDirectorySize,
                   &BytesWritten,
                   NULL
                 );

        if (FunctionTable) {
            WriteFile( SymbolFileHandle,
                       FunctionTable,
                       FunctionTableSize,
                       &BytesWritten,
                       NULL
                     );
            }

        SetFilePointer( SymbolFileHandle, 0, NULL, FILE_END );
        CloseHandle( SymbolFileHandle );

        FlushViewOfFile( ImageBase, NewFileSize );
        UnmapViewOfFile( ImageBase );
        CloseHandle( hMappedFile );
        if (SetFilePointer( FileHandle, NewFileSize, NULL, FILE_BEGIN ) != NewFileSize ||
            !SetEndOfFile( FileHandle )
           ) {
            }

        TouchFileTimes( FileHandle, NULL );
        CloseHandle( FileHandle );

        if (ExportedNames != NULL) {
            LocalFree( ExportedNames );
            }

        if (FpoTable != NULL) {
            VirtualFree( FpoTable, 0, MEM_RELEASE );
            }

        if (SymbolsToFree != NULL) {
            VirtualFree( SymbolsToFree, 0, MEM_RELEASE );
            }

        if (FunctionTable != NULL) {
            VirtualFree( FunctionTable, 0, MEM_RELEASE );
            }
        return TRUE;
        }
    else {
        CloseHandle( SymbolFileHandle );
        DeleteFile( SymbolFilePath );
        }

nosyms:
    SavedErrorCode = GetLastError();
    if (ExportedNames != NULL) {
        LocalFree( ExportedNames );
        }

    if (FpoTable != NULL) {
        VirtualFree( FpoTable, 0, MEM_RELEASE );
        }

    if (SymbolsToFree != NULL) {
        VirtualFree( SymbolsToFree, 0, MEM_RELEASE );
        }

    if (FunctionTable != NULL) {
        VirtualFree( FunctionTable, 0, MEM_RELEASE );
        }

    UnmapViewOfFile( ImageBase );
    CloseHandle( hMappedFile );
    CloseHandle( FileHandle );
    SetLastError( SavedErrorCode );
    return FALSE;
}

BOOL
SearchTreeForFile(
    LPSTR RootPath,
    PCHAR InputPathName,
    PCHAR OutputPathBuffer
    );

HANDLE
FindExecutableImage(
    LPSTR FileName,
    LPSTR SymbolPath,
    LPSTR ImageFilePath
    );

BOOL
GetImageNameFromMiscDebugData(
    HANDLE FileHandle,
    PVOID MappedBase,
    PIMAGE_NT_HEADERS NtHeaders,
    PIMAGE_DEBUG_DIRECTORY DebugDirectories,
    ULONG NumberOfDebugDirectories,
    LPSTR ImageFilePath
    );

PIMAGE_DEBUG_INFORMATION
MapDebugInformation(
    HANDLE FileHandle,
    LPSTR FileName,
    LPSTR SymbolPath,
    ULONG ImageBase
    )
{
    ULONG NumberOfHandlesToClose;
    HANDLE HandlesToClose[ 4 ];
    HANDLE MappingHandle;
    PVOID MappedBase, Next;
    BOOL SeparateSymbols;
    UCHAR ImageFilePath[ MAX_PATH ];
    UCHAR DebugFilePath[ MAX_PATH ];
    PIMAGE_DEBUG_INFORMATION DebugInfo;
    PIMAGE_NT_HEADERS NtHeaders;
    PIMAGE_DEBUG_DIRECTORY DebugDirectories;
    PIMAGE_DEBUG_DIRECTORY DebugDirectory;
    PIMAGE_SEPARATE_DEBUG_HEADER DebugFileHeader;
    PIMAGE_EXPORT_DIRECTORY ExportDirectory;
    PIMAGE_RUNTIME_FUNCTION_ENTRY RuntimeFunctionTable;
    PIMAGE_FUNCTION_ENTRY FunctionTable;
    ULONG NumberOfFunctionTableEntries, FunctionTableSize;
    PVOID DebugData;
    LPSTR Src, Dst;
    PULONG pp;
    ULONG RvaOffset;
    ULONG i, j;
    ULONG ExportedNamesSize;
    ULONG DebugInfoHeaderSize;
    ULONG DebugInfoSize;
    ULONG Size;
    ULONG NumberOfDebugDirectories;
    LONG BaseOffset;
    HANDLE SavedImageFileHandle;

    if (FileHandle == NULL && (FileName == NULL || FileName[ 0 ] == '\0')) {
        return NULL;
        }

    DebugInfo = NULL;
    NumberOfHandlesToClose = 0;
    MappedBase = NULL;
    SeparateSymbols = FALSE;
    SavedImageFileHandle = NULL;
    ImageFilePath[ 0 ] = '\0';
    NumberOfFunctionTableEntries = 0;
    FunctionTableSize = 0;
    FunctionTable = NULL; 
    try {
        try {
            if (FileHandle == NULL) {
                FileHandle = FindExecutableImage( FileName, SymbolPath, ImageFilePath );
                if (FileHandle == NULL) {
                    strcpy( ImageFilePath, FileName );
getDebugFile:
                    FileHandle = FindDebugInfoFile( FileName, SymbolPath, DebugFilePath );
                    if (FileHandle == NULL) {
                        if (SavedImageFileHandle != NULL) {
                            FileHandle = SavedImageFileHandle;
                            goto noDebugFile;
                            }
                        else {
                            leave;
                            }
                        }
                    else {
                        SeparateSymbols = TRUE;
                        }
                    }
                else {
                    SavedImageFileHandle = FileHandle;
                    }

                HandlesToClose[ NumberOfHandlesToClose++ ] = FileHandle;
                }
            else {
                SavedImageFileHandle = FileHandle;
                }

            //
            //  map image file and process enough to get the image name and capture
            //  stuff from header.
            //

            MappingHandle = CreateFileMapping( FileHandle,
                                          NULL,
                                          PAGE_READONLY,
                                          0,
                                          0,
                                          NULL
                                        );
            if (MappingHandle == NULL) {
                leave;
                }
            HandlesToClose[ NumberOfHandlesToClose++ ] = MappingHandle;

            MappedBase = MapViewOfFile( MappingHandle,
                                        FILE_MAP_READ,
                                        0,
                                        0,
                                        0
                                      );
            if (MappedBase == NULL) {
                leave;
                }

            DebugInfoSize = sizeof( *DebugInfo ) + strlen( ImageFilePath ) + 1;
            if (SeparateSymbols) {
                DebugInfoSize += strlen( DebugFilePath ) + 1;
                }

            if (!SeparateSymbols) {
                NtHeaders = ImageNtHeader( MappedBase );
                if (NtHeaders == NULL) {
                    leave;
                    }

                DebugDirectories = (PIMAGE_DEBUG_DIRECTORY)
                    ImageDirectoryEntryToData( MappedBase,
                                               FALSE,
                                               IMAGE_DIRECTORY_ENTRY_DEBUG,
                                               &Size
                                             );
                if (DebugDirectories != NULL) {
                    NumberOfDebugDirectories = Size / sizeof( IMAGE_DEBUG_DIRECTORY );
                    }
                else {
                    NumberOfDebugDirectories = 0;
                    }

                if (FileName == NULL &&
                    GetImageNameFromMiscDebugData( FileHandle,
                                                   MappedBase,
                                                   NtHeaders,
                                                   DebugDirectories,
                                                   NumberOfDebugDirectories,
                                                   ImageFilePath
                                                 )
                   ) {
                    FileName = ImageFilePath;
                    DebugInfoSize += strlen( ImageFilePath );
                    }

                DebugInfoSize = (DebugInfoSize + 16) & ~15;
                DebugInfoHeaderSize = DebugInfoSize;

                if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED) {
                    goto getDebugFile;
                    }

noDebugFile:
                ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)
                    ImageDirectoryEntryToData( MappedBase,
                                               FALSE,
                                               IMAGE_DIRECTORY_ENTRY_EXPORT,
                                               &Size
                                             );
                if (ExportDirectory) {
                    //
                    // This particular piece of magic gets us the RVA of the
                    // EXPORT section.  Dont ask.
                    //

                    RvaOffset = (ULONG)
                        ImageDirectoryEntryToData( MappedBase,
                                                   TRUE,
                                                   IMAGE_DIRECTORY_ENTRY_EXPORT,
                                                   &Size
                                                 ) - (DWORD)MappedBase;

                    pp = (PULONG)((ULONG)ExportDirectory +
                                  (ULONG)ExportDirectory->AddressOfNames - RvaOffset
                                 );

                    ExportedNamesSize = 1;
                    for (i=0; i<ExportDirectory->NumberOfNames; i++) {
                        Src = (LPSTR)((ULONG)ExportDirectory + *pp++ - RvaOffset);
                        ExportedNamesSize += strlen( Src ) + 1;
                        }
                    ExportedNamesSize = (ExportedNamesSize + 16) & ~15;
                    DebugInfoSize += ExportedNamesSize;
                    }
                else {
                    ExportedNamesSize = 0;
                    }

                RuntimeFunctionTable = (PIMAGE_RUNTIME_FUNCTION_ENTRY)
                    ImageDirectoryEntryToData( MappedBase,
                                               FALSE,
                                               IMAGE_DIRECTORY_ENTRY_EXCEPTION,
                                               &Size
                                             );
                if (RuntimeFunctionTable != NULL) {
                    NumberOfFunctionTableEntries = Size / sizeof( IMAGE_RUNTIME_FUNCTION_ENTRY );
                    FunctionTableSize = NumberOfFunctionTableEntries *
                                        sizeof( IMAGE_FUNCTION_ENTRY );

                    DebugInfoSize += FunctionTableSize;
                    }

                if (NumberOfDebugDirectories != 0) {
                    DebugDirectory = DebugDirectories;
                    for (i=0; i<NumberOfDebugDirectories; i++) {
                        if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_FPO ||
                            DebugDirectory->Type == IMAGE_DEBUG_TYPE_COFF
                           ) {
                            if (DebugDirectory->AddressOfRawData == 0) {
                                DebugInfoSize += DebugDirectory->SizeOfData;
                                }
                            }

                        DebugDirectory += 1;
                        }
                    }
                }
            else {
                DebugFileHeader = (PIMAGE_SEPARATE_DEBUG_HEADER)MappedBase;
                Next = (PVOID)((PIMAGE_SECTION_HEADER)(DebugFileHeader + 1) + DebugFileHeader->NumberOfSections);
                if (DebugFileHeader->ExportedNamesSize != 0) {
                    Next = (PVOID)((PCHAR)Next + DebugFileHeader->ExportedNamesSize);
                    }
                DebugDirectories = (PIMAGE_DEBUG_DIRECTORY)Next;
                DebugDirectory = DebugDirectories;
                NumberOfDebugDirectories = DebugFileHeader->DebugDirectorySize / sizeof( IMAGE_DEBUG_DIRECTORY );

                for (i=0; i<NumberOfDebugDirectories; i++) {
                    if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_EXCEPTION) {
                        FunctionTableSize = DebugDirectory->SizeOfData;
                        NumberOfFunctionTableEntries = FunctionTableSize / sizeof( IMAGE_FUNCTION_ENTRY );
                        break;
                        }

                    DebugDirectory += 1;
                    }

                DebugInfoSize = (DebugInfoSize + 16) & ~15;
                DebugInfoHeaderSize = DebugInfoSize;
                DebugInfoSize += FunctionTableSize;
                }

            DebugInfo = VirtualAlloc( NULL, DebugInfoSize, MEM_COMMIT, PAGE_READWRITE );
            if (DebugInfo == NULL) {
                leave;
                }

            DebugInfo->Size = DebugInfoSize;
            DebugInfo->ImageFilePath = (LPSTR)(DebugInfo + 1);
            strcpy( DebugInfo->ImageFilePath, ImageFilePath );
            Src = strchr( DebugInfo->ImageFilePath, '\0' );
            while (Src > DebugInfo->ImageFilePath) {
                if (Src[ -1 ] == '\\' || Src[ -1 ] == '/' || Src[ -1 ] == ':') {
                    break;
                    }
                else {
                    Src -= 1;
                    }
                }
            DebugInfo->ImageFileName = Src;
            DebugInfo->DebugFilePath = DebugInfo->ImageFilePath;
            if (SeparateSymbols) {
                DebugInfo->DebugFilePath += strlen( DebugInfo->ImageFilePath ) + 1;
                strcpy( DebugInfo->DebugFilePath, DebugFilePath );
                }

            DebugInfo->MappedBase = MappedBase;
            if (SeparateSymbols) {
                DebugInfo->Machine = DebugFileHeader->Machine;
                DebugInfo->Characteristics = DebugFileHeader->Characteristics;
                DebugInfo->TimeDateStamp = DebugFileHeader->TimeDateStamp;
                DebugInfo->CheckSum = DebugFileHeader->CheckSum;
                DebugInfo->ImageBase = DebugFileHeader->ImageBase;
                DebugInfo->SizeOfImage = DebugFileHeader->SizeOfImage;
                DebugInfo->NumberOfSections = DebugFileHeader->NumberOfSections;
                DebugInfo->Sections = (PIMAGE_SECTION_HEADER)(DebugFileHeader + 1);
                Next = (PVOID)(DebugInfo->Sections + DebugInfo->NumberOfSections);

                DebugInfo->ExportedNamesSize = DebugFileHeader->ExportedNamesSize;
                if (DebugInfo->ExportedNamesSize) {
                    DebugInfo->ExportedNames = (LPSTR)Next;
                    Next = (PVOID)((PCHAR)Next + DebugInfo->ExportedNamesSize);
                    }
                DebugDirectory = DebugDirectories;
                NumberOfDebugDirectories = DebugFileHeader->DebugDirectorySize / sizeof( IMAGE_DEBUG_DIRECTORY );
                Next = (PVOID)((PCHAR)Next + DebugFileHeader->DebugDirectorySize);
                for (i=0; i<NumberOfDebugDirectories; i++) {
                    if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_EXCEPTION) {
                        DebugInfo->NumberOfFunctionTableEntries = NumberOfFunctionTableEntries;
                        DebugInfo->FunctionTableEntries = (PIMAGE_FUNCTION_ENTRY)
                            ((PCHAR)MappedBase + DebugDirectory->PointerToRawData);

                        BaseOffset = ImageBase;
                        FunctionTable = (PIMAGE_FUNCTION_ENTRY)((ULONG)DebugInfo + DebugInfoHeaderSize);
                        memmove( FunctionTable, DebugInfo->FunctionTableEntries, FunctionTableSize );
                        DebugInfo->FunctionTableEntries = FunctionTable;
                        DebugInfo->LowestFunctionStartingAddress = (ULONG)0xFFFFFFFF;
                        DebugInfo->HighestFunctionEndingAddress = 0;
                        for (j=0; j<DebugInfo->NumberOfFunctionTableEntries; j++) {
                            FunctionTable->StartingAddress += BaseOffset;
                            if (FunctionTable->StartingAddress < DebugInfo->LowestFunctionStartingAddress) {
                                DebugInfo->LowestFunctionStartingAddress = FunctionTable->StartingAddress;
                                }

                            FunctionTable->EndingAddress += BaseOffset;
                            if (FunctionTable->EndingAddress > DebugInfo->HighestFunctionEndingAddress) {
                                DebugInfo->HighestFunctionEndingAddress = FunctionTable->EndingAddress;
                                }

                            FunctionTable->EndOfPrologue += BaseOffset;
                            FunctionTable += 1;
                            }
                        }
                    else
                    if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_FPO) {
                        DebugInfo->NumberOfFpoTableEntries =
                            DebugDirectory->SizeOfData / sizeof( FPO_DATA );
                        DebugInfo->FpoTableEntries = (PFPO_DATA)
                            ((PCHAR)MappedBase + DebugDirectory->PointerToRawData);
                        }
                    else
                    if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_COFF) {
                        DebugInfo->SizeOfCoffSymbols = DebugDirectory->SizeOfData;
                        DebugInfo->CoffSymbols = (PIMAGE_COFF_SYMBOLS_HEADER)
                            ((PCHAR)MappedBase + DebugDirectory->PointerToRawData);
                        }

                    DebugDirectory += 1;
                    }
                }
            else {
                DebugInfo->Machine = NtHeaders->FileHeader.Machine;
                DebugInfo->Characteristics = NtHeaders->FileHeader.Characteristics;
                DebugInfo->TimeDateStamp = NtHeaders->FileHeader.TimeDateStamp;
                DebugInfo->CheckSum = NtHeaders->OptionalHeader.CheckSum;
                DebugInfo->ImageBase = NtHeaders->OptionalHeader.ImageBase;
                DebugInfo->SizeOfImage = NtHeaders->OptionalHeader.SizeOfImage;
                DebugInfo->NumberOfSections = NtHeaders->FileHeader.NumberOfSections;
                DebugInfo->Sections = IMAGE_FIRST_SECTION( NtHeaders );
                Next = (PVOID)((ULONG)DebugInfo + DebugInfoHeaderSize);

                DebugInfo->ExportedNamesSize = ExportedNamesSize;
                if (DebugInfo->ExportedNamesSize) {
                    DebugInfo->ExportedNames = (LPSTR)Next;
                    Next = (PVOID)((LPSTR)Next + ExportedNamesSize);

                    pp = (PULONG)((ULONG)ExportDirectory +
                                  (ULONG)ExportDirectory->AddressOfNames - RvaOffset
                                 );

                    Dst = DebugInfo->ExportedNames;
                    for (i=0; i<ExportDirectory->NumberOfNames; i++) {
                        Src = (LPSTR)((ULONG)ExportDirectory + *pp++ - RvaOffset);
                        while (*Dst++ = *Src++) {
                            }
                        }
                    }

                if (RuntimeFunctionTable != NULL) {
                    BaseOffset = ImageBase - DebugInfo->ImageBase;
                    DebugInfo->FunctionTableEntries = (PIMAGE_FUNCTION_ENTRY)Next;
                    DebugInfo->NumberOfFunctionTableEntries = NumberOfFunctionTableEntries;
                    Next = (PVOID)((LPSTR)Next + FunctionTableSize);

                    DebugInfo->LowestFunctionStartingAddress = (ULONG)0xFFFFFFFF;
                    DebugInfo->HighestFunctionEndingAddress = 0;
                    FunctionTable = DebugInfo->FunctionTableEntries;
                    for (i=0; i<NumberOfFunctionTableEntries; i++) {
                        FunctionTable->StartingAddress = RuntimeFunctionTable->BeginAddress + BaseOffset;
                        if (FunctionTable->StartingAddress < DebugInfo->LowestFunctionStartingAddress) {
                            DebugInfo->LowestFunctionStartingAddress = FunctionTable->StartingAddress;
                            }

                        FunctionTable->EndingAddress = RuntimeFunctionTable->EndAddress + BaseOffset;
                        if (FunctionTable->EndingAddress > DebugInfo->HighestFunctionEndingAddress) {
                            DebugInfo->HighestFunctionEndingAddress = FunctionTable->EndingAddress;
                            }

                        FunctionTable->EndOfPrologue = RuntimeFunctionTable->PrologEndAddress + BaseOffset;
                        RuntimeFunctionTable += 1;
                        FunctionTable += 1;
                        }
                    }

                DebugDirectory = DebugDirectories;
                for (i=0; i<NumberOfDebugDirectories; i++) {
                    if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_FPO ||
                        ((DebugDirectory->Type == IMAGE_DEBUG_TYPE_COFF) &&
                         !(NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED)
                        )
                       ) {
                        DebugData = NULL;
                        if (DebugDirectory->AddressOfRawData == 0) {
                            if (SetFilePointer( FileHandle,
                                                DebugDirectory->PointerToRawData,
                                                NULL,
                                                FILE_BEGIN
                                              ) == DebugDirectory->PointerToRawData
                               ) {
                                if (ReadFile( FileHandle,
                                              Next,
                                              DebugDirectory->SizeOfData,
                                              &Size,
                                              NULL
                                            ) &&
                                    DebugDirectory->SizeOfData == Size
                                   ) {
                                    DebugData = Next;
                                    Next = (PVOID)((LPSTR)Next + Size);
                                    }
                                }
                            }
                        else {
                            DebugData = (LPSTR)MappedBase + DebugDirectory->PointerToRawData;
                            Size = DebugDirectory->SizeOfData;
                            }

                        if (DebugData != NULL) {
                            if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_FPO) {
                                DebugInfo->FpoTableEntries = DebugData;
                                DebugInfo->NumberOfFpoTableEntries = Size / sizeof( FPO_DATA );
                                }
                            else {
                                DebugInfo->CoffSymbols = DebugData;
                                DebugInfo->SizeOfCoffSymbols = Size;
                                }
                            }
                        }

                    DebugDirectory += 1;
                    }
                }
            }
        except( EXCEPTION_EXECUTE_HANDLER ) {
            if (DebugInfo != NULL) {
                VirtualFree( DebugInfo, 0, MEM_RELEASE );
                DebugInfo = NULL;
                }
            }
        }
    finally {
        if (DebugInfo == NULL) {
            if (MappedBase != NULL) {
                UnmapViewOfFile( MappedBase );
                }
            }

        while (NumberOfHandlesToClose--) {
            CloseHandle( HandlesToClose[ NumberOfHandlesToClose ] );
            }
        }

    return DebugInfo;
}


BOOL
UnmapDebugInformation(
    PIMAGE_DEBUG_INFORMATION DebugInfo
    )
{
    if (DebugInfo != NULL) {
        try {
            UnmapViewOfFile( DebugInfo->MappedBase );
            memset( DebugInfo, 0, sizeof( *DebugInfo ) );
            VirtualFree( DebugInfo, 0, MEM_RELEASE );
            }
        except( EXCEPTION_EXECUTE_HANDLER ) {
            return FALSE;
            }
        }

    return TRUE;
}

HANDLE
FindExecutableImage(
    LPSTR FileName,
    LPSTR SymbolPath,
    LPSTR ImageFilePath
    )
{
    LPSTR Start, End;
    HANDLE FileHandle;
    UCHAR DirectoryPath[ MAX_PATH ];

    Start = SymbolPath;
    while (Start && *Start != '\0') {
        if (End = strchr( Start, ';' )) {
            strncpy( DirectoryPath, Start, End - Start );
            DirectoryPath[ End - Start ] = '\0';
            End += 1;
            }
        else {
            strcpy( DirectoryPath, Start );
            }

        if (SearchTreeForFile( DirectoryPath, FileName, ImageFilePath )) {
            FileHandle = CreateFile( ImageFilePath,
                                     GENERIC_READ,
                                     FILE_SHARE_READ | FILE_SHARE_WRITE,
                                     NULL,
                                     OPEN_EXISTING,
                                     0,
                                     NULL
                                   );
            if (FileHandle != INVALID_HANDLE_VALUE) {
                return FileHandle;
                }
            }

        Start = End;
        }

    return NULL;
}


HANDLE
FindDebugInfoFile(
    LPSTR FileName,
    LPSTR SymbolPath,
    LPSTR DebugFilePath
    )
{
    HANDLE FileHandle;
    LPSTR s;
    LPSTR Start, End;
    UCHAR BaseName[ MAX_PATH ];
    DWORD n;

    if (!(s = strrchr( FileName, '.' )) || stricmp( s, ".DBG" )) {
        if (s != NULL) {
            strcpy( BaseName, s+1 );
            strcat( BaseName, "\\" );
            }
        else {
            BaseName[ 0 ] = '\0';
            }

        s = FileName + strlen( FileName );
        while (s > FileName) {
            if (*--s == '\\' || *s == '/' || *s == ':') {
                s += 1;
                break;
                }
            }
        strcat( BaseName, s );
        if (!(s = strrchr( BaseName, '.' ))) {
            s = strchr( BaseName, '\0' );
            }
        strcpy( s, ".DBG" );
        }
    else {
        strcpy( BaseName, FileName );
        }

    Start = SymbolPath;
    while (Start && *Start != '\0') {
        if (End = strchr( Start, ';' )) {
            *End = '\0';
            }

        n = GetFullPathName( Start, MAX_PATH, DebugFilePath, &s );
        if (End) {
            *End++ = ';';
            }
        Start = End;
        if (n == 0) {
            continue;
            }

        if (s != NULL && !stricmp( s, "Symbols" )) {
            strcat( DebugFilePath, "\\" );
            }
        else {
            strcat( DebugFilePath, "\\Symbols\\" );
            }
        strcat( DebugFilePath, BaseName );

        FileHandle = CreateFile( DebugFilePath,
                                 GENERIC_READ,
                                 FILE_SHARE_READ | FILE_SHARE_WRITE,
                                 NULL,
                                 OPEN_EXISTING,
                                 0,
                                 NULL
                               );
        if (FileHandle != INVALID_HANDLE_VALUE) {
            return FileHandle;
            }
        }

    return NULL;
}

BOOL
GetImageNameFromMiscDebugData(
    HANDLE FileHandle,
    PVOID MappedBase,
    PIMAGE_NT_HEADERS NtHeaders,
    PIMAGE_DEBUG_DIRECTORY DebugDirectories,
    ULONG NumberOfDebugDirectories,
    LPSTR ImageFilePath
    )
{
    IMAGE_DEBUG_MISC TempMiscData;
    PIMAGE_DEBUG_MISC DebugMiscData;
    ULONG BytesToRead, BytesRead;
    BOOLEAN FoundImageName;
    LPSTR ImageName;

    while (NumberOfDebugDirectories) {
        if (DebugDirectories->Type == IMAGE_DEBUG_TYPE_MISC) {
            break;
            }
        else {
            DebugDirectories += 1;
            NumberOfDebugDirectories -= 1;
            }
        }

    if (NumberOfDebugDirectories == 0) {
        return FALSE;
        }

    if (NtHeaders->OptionalHeader.MinorLinkerVersion < 36) {
        BytesToRead = FIELD_OFFSET( IMAGE_DEBUG_MISC, Reserved );
        }
    else {
        BytesToRead = FIELD_OFFSET( IMAGE_DEBUG_MISC, Data );
        }

    DebugMiscData = NULL;
    if (DebugDirectories->AddressOfRawData == 0) {
        if (SetFilePointer( FileHandle,
                            DebugDirectories->PointerToRawData,
                            NULL,
                            FILE_BEGIN
                          ) == DebugDirectories->PointerToRawData
           ) {
            if (ReadFile( FileHandle,
                          &TempMiscData,
                          BytesToRead,
                          &BytesRead,
                          NULL
                        ) &&
                BytesRead == BytesToRead
               ) {
                DebugMiscData = &TempMiscData;
                }
            }
        }
    else {
        DebugMiscData = (PIMAGE_DEBUG_MISC)((PCHAR)MappedBase +
                                            DebugDirectories->PointerToRawData
                                           );
        }

    FoundImageName = FALSE;
    if (DebugMiscData != NULL && DebugMiscData->DataType == IMAGE_DEBUG_MISC_EXENAME) {
        if (DebugMiscData == &TempMiscData) {
            BytesToRead = DebugMiscData->Length - BytesToRead;
            if (ReadFile( FileHandle,
                          ImageFilePath,
                          BytesToRead,
                          &BytesRead,
                          NULL
                        ) &&
                BytesRead == BytesToRead
               ) {
                FoundImageName = TRUE;
                }
            }
        else {
            ImageName = (PCHAR)DebugMiscData + BytesToRead;
            BytesToRead = DebugMiscData->Length - BytesToRead;
            if (*ImageName != '\0' ) {
                memcpy( ImageFilePath, ImageName, BytesToRead );
                FoundImageName = TRUE;
                }
            }
        }

    return FoundImageName;
}



#define MAX_DEPTH 32

BOOL
SearchTreeForFile(
    LPSTR RootPath,
    LPSTR InputPathName,
    LPSTR OutputPathBuffer
    )
{
    PCHAR FileName;
    PUCHAR Prefix = "";
    CHAR PathBuffer[ MAX_PATH ];
    ULONG Depth;
    PCHAR PathTail[ MAX_DEPTH ];
    PCHAR FindHandle[ MAX_DEPTH ];
    LPWIN32_FIND_DATA FindFileData;
    UCHAR FindFileBuffer[ MAX_PATH + sizeof( WIN32_FIND_DATA ) ];
    BOOL Result;

    strcpy( PathBuffer, RootPath );
    FileName = InputPathName;
    while (*InputPathName) {
        if (*InputPathName == ':' || *InputPathName == '\\' || *InputPathName == '/') {
            FileName = ++InputPathName;
            }
        else {
            InputPathName++;
            }
        }
    FindFileData = (LPWIN32_FIND_DATA)FindFileBuffer;
    Depth = 0;
    Result = FALSE;
    while (TRUE) {
startDirectorySearch:
        PathTail[ Depth ] = strchr( PathBuffer, '\0' );
        if (PathTail[ Depth ] > PathBuffer && PathTail[ Depth ][ -1 ] != '\\') {
            *(PathTail[ Depth ])++ = '\\';
            }

        strcpy( PathTail[ Depth ], "*.*" );
        FindHandle[ Depth ] = FindFirstFile( PathBuffer, FindFileData );
        if (FindHandle[ Depth ] != INVALID_HANDLE_VALUE) {
            do {
                if (FindFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
                    if (strcmp( FindFileData->cFileName, "." ) &&
                        strcmp( FindFileData->cFileName, ".." ) &&
                        Depth < MAX_DEPTH
                       ) {
                        sprintf( PathTail[ Depth ], "%s\\", FindFileData->cFileName );
                        Depth++;
                        goto startDirectorySearch;
                        }
                    }
                else
                if (!stricmp( FindFileData->cFileName, FileName )) {
                    strcpy( PathTail[ Depth ], FindFileData->cFileName );
                    strcpy( OutputPathBuffer, PathBuffer );
                    Result = TRUE;
                    }

restartDirectorySearch:
                if (Result) {
                    break;
                    }
                }
            while (FindNextFile( FindHandle[ Depth ], FindFileData ));
            FindClose( FindHandle[ Depth ] );

            if (Depth == 0) {
                break;
                }

            Depth--;
            goto restartDirectorySearch;
            }
        }

    return Result;
}


BOOL
MakeSureDirectoryPathExists(
    LPSTR DirPath
    )
{
    LPSTR Dir,p;
    DWORD dw;

    Dir = DirPath;
    p = Dir+1;

    //
    //  If the second character in the path is "\", then this is a UNC
    //  path, and we should skip forward until we reach the 2nd \ in the
    //  path.
    //
    if (*p == '\\') {
        p++;            // Skip over the second \ in the name.

        //
        //  Skip until we hit the first "\" (\\Server\).
        //

        while (*p && *p != '\\') {
            p++;
            }

        if (*p) {
            *p++;
            }

        //
        //  Skip until we hit the second "\" (\\Server\Share\).
        //

        while (*p && *p != '\\') {
            p++;
            }

        //
        //  The directory to check is the "path" part of \\Server\Share\path
        //

        if (*p) {
            Dir = p-1;
            }
        }
    else if (*p == ':' ) {
        p++;
        p++;
        }

    while( *p ) {
        if ( *p == '\\' ) {
            *p = '\0';
            dw = GetFileAttributes(DirPath);
            if ( dw == 0xffffffff || dw & FILE_ATTRIBUTE_DIRECTORY != FILE_ATTRIBUTE_DIRECTORY ) {
                if ( dw == 0xffffffff ) {
                    if ( !CreateDirectory(DirPath,NULL) ) {
                        return FALSE;
                        }
                    }
                }

            *p = '\\';
            }
        p++;
        }

    return TRUE;
}


BOOL
UpdateDebugInfoFile(
    LPSTR ImageFileName,
    LPSTR SymbolPath,
    LPSTR DebugFilePath,
    PIMAGE_NT_HEADERS NtHeaders
    )
{
    HANDLE hDebugFile, hMappedFile;
    PVOID MappedAddress;
    PIMAGE_SEPARATE_DEBUG_HEADER DbgFileHeader;

    hDebugFile = FindDebugInfoFile(
                    ImageFileName,
                    SymbolPath,
                    DebugFilePath
                    );
    if ( hDebugFile == NULL ) {
        return FALSE;
        }
    CloseHandle(hDebugFile);

    hDebugFile = CreateFile( DebugFilePath,
                             GENERIC_READ | GENERIC_WRITE,
                             FILE_SHARE_READ | FILE_SHARE_WRITE,
                             NULL,
                             OPEN_EXISTING,
                             0,
                             NULL
                           );
    if ( hDebugFile == INVALID_HANDLE_VALUE ) {
        return FALSE;
        }

    hMappedFile = CreateFileMapping(
                    hDebugFile,
                    NULL,
                    PAGE_READWRITE,
                    0,
                    0,
                    NULL
                    );
    if ( !hMappedFile ) {
        CloseHandle(hDebugFile);
        return FALSE;
        }

    MappedAddress = MapViewOfFile(hMappedFile,
                        FILE_MAP_WRITE,
                        0,
                        0,
                        0
                        );
    CloseHandle(hMappedFile);
    if ( !MappedAddress ) {
        CloseHandle(hDebugFile);
        return FALSE;
        }

    DbgFileHeader = (PIMAGE_SEPARATE_DEBUG_HEADER)MappedAddress;
    if (DbgFileHeader->ImageBase != NtHeaders->OptionalHeader.ImageBase ||
        DbgFileHeader->CheckSum != NtHeaders->OptionalHeader.CheckSum
       ) {
        DbgFileHeader->ImageBase = NtHeaders->OptionalHeader.ImageBase;
        DbgFileHeader->CheckSum = NtHeaders->OptionalHeader.CheckSum;
        UnmapViewOfFile(MappedAddress);
        FlushViewOfFile(MappedAddress,0);
        TouchFileTimes(hDebugFile,NULL);
        CloseHandle(hDebugFile);
        return TRUE;
        }
    else {
        UnmapViewOfFile(MappedAddress);
        FlushViewOfFile(MappedAddress,0);
        CloseHandle(hDebugFile);
        return FALSE;
        }
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.