Release 961222

Sun Dec 22 13:30:18 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [graphics/metafiledrv/init.c] [graphisc/metafiledrv/mapping.c]
	Added mapping functions.

	* [if1632/gdi.spec] [objects/*.c] [include/windows.h]
	Added a lot of Win32 functions.

	* [memory/heap.c]
	Added HEAP_strdupAtoW and HEAP_strdupWtoA.

	* [misc/lstr.c] [memory/string.c]
	Moved OEM<->Ansi conversion to string.c. Fixed a couple of bugs.

	* [object/font.c]
	Avoid uppercasing font names.

	* [windows/hook.c]
	Set ds = ss before calling hook procedure.

Sat Dec 21 21:44:17 1996  Alex Korobka <alex@trantor.pharm.sunysb.edu>

	* [objects/color.c]
	Use colors allocated by other clients. 

	* [windows/caret.c]
	Set default blink time to 500.

	* [windows/win.c] [windows/event.c]
	Delete X context before XDestroyWindow().

	* [windows/keyboard.c]
	Fixed GetKeyState() once more.

Fri Dec 20 08:26:33 1996  Eric Youngdale <eric@sub2304.jic.com>

	* [debugger/*.c]
	Lots of built-in debugger improvements: parse Win32 EXEs debug
 	information, display local variables, source files and line
 	numbers, get symbols directly from the Wine executable, etc.

Tue Dec 17 22:39:42 1996  Philippe De Muyter  <phdm@info.ucl.ac.be>

	* [misc/winsock_async.c]
 	Extern declaration added for h_errno.

Tue Dec 17 21:29:34 1996  Albrecht Kleine  <kleine@ak.sax.de>

	* [windows/message.c]
	Added two more CBT hook calls: HCBT_CLICKSKIPPED/HCBT_KEYSKIPPED.
diff --git a/debugger/msc.c b/debugger/msc.c
new file mode 100644
index 0000000..dc29ca9
--- /dev/null
+++ b/debugger/msc.c
@@ -0,0 +1,413 @@
+/*
+ * File msc.c - read VC++ debug information from COFF and eventually
+ * from PDB files.
+ *
+ * Copyright (C) 1996, Eric Youngdale.
+ *
+ * Note - this handles reading debug information for 32 bit applications
+ * that run under Windows-NT for example.  I doubt that this would work well
+ * for 16 bit applications, but I don't think it really matters since the
+ * file format is different, and we should never get in here in such cases.
+ */
+
+#include <stdio.h>
+
+
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <strings.h>
+#include <unistd.h>
+#include <malloc.h>
+
+#include "win.h"
+#include "pe_image.h"
+#include "debugger.h"
+#include "peexe.h"
+#include "xmalloc.h"
+
+/*
+ * For the type CODEVIEW debug directory entries, the debug directory
+ * points to a structure like this.  The cv_name field is the name
+ * of an external .PDB file.
+ */
+struct CodeViewDebug
+{
+	char		    cv_nbtype[8];
+	unsigned int	    cv_timestamp;
+	char		    cv_unknown[4];
+	char		    cv_name[1];
+};
+
+struct MiscDebug {
+    unsigned int       DataType;
+    unsigned int       Length;
+    char	       Unicode;
+    char	       Reserved[3];
+    char	       Data[1];
+};
+
+/*
+ * This is the header that the COFF variety of debug header points to.
+ */
+struct CoffDebug {
+    unsigned int   N_Sym;
+    unsigned int   SymbolOffset;
+    unsigned int   N_Linenum;
+    unsigned int   LinenumberOffset;
+    unsigned int   Unused[4];
+};
+
+struct CoffLinenum {
+	unsigned int	VirtualAddr;
+	unsigned int	Linenum;
+};
+
+struct CoffFiles {
+	unsigned int	startaddr;
+	unsigned int	endaddr;
+	char	      * filename;
+};
+
+
+struct CoffSymbol {
+    union {
+        char    ShortName[8];
+        struct {
+            unsigned int   NotLong;
+            unsigned int   StrTaboff;
+        } Name;
+    } N;
+    unsigned int   Value;
+    short	   SectionNumber;
+    short	   Type;
+    char	   StorageClass;
+    unsigned char  NumberOfAuxSymbols;
+};
+
+struct CoffAuxSection{
+  unsigned int   Length;
+  unsigned short NumberOfRelocations;
+  unsigned short NumberOfLinenumbers;
+  unsigned int   CheckSum;
+  short          Number;
+  char           Selection;
+} Section;
+
+struct deferred_debug_info
+{
+	struct deferred_debug_info	* next;
+	char				* load_addr;
+	char				* dbg_info;
+	int				  dbg_size;
+	struct PE_Debug_dir		* dbgdir;
+	struct pe_data			* pe;
+};
+
+struct deferred_debug_info * dbglist = NULL;
+
+/*
+ * A simple macro that tells us whether a given COFF symbol is a
+ * function or not.
+ */
+#define N_TMASK                             0x0030
+#define IMAGE_SYM_DTYPE_FUNCTION            2
+#define N_BTSHFT                            4
+#define ISFCN(x) (((x) & N_TMASK) == (IMAGE_SYM_DTYPE_FUNCTION << N_BTSHFT))
+
+
+/*
+ * This is what we are looking for in the COFF symbols.
+ */
+#define IMAGE_SYM_CLASS_EXTERNAL            0x2
+#define IMAGE_SYM_CLASS_STATIC              0x3
+#define IMAGE_SYM_CLASS_FILE                0x67
+
+/*
+ * In this function, we keep track of deferred debugging information
+ * that we may need later if we were to need to use the internal debugger.
+ * We don't fully process it here for performance reasons.
+ */
+int
+DEBUG_RegisterDebugInfo(int fd, struct pe_data * pe, 
+			int load_addr, u_long v_addr, u_long size)
+{
+  int			  rtn = FALSE;
+  struct PE_Debug_dir	* dbgptr;
+  struct deferred_debug_info * deefer;
+
+  dbgptr = (struct PE_Debug_dir *) (load_addr + v_addr);
+  for(; size > 0; size -= sizeof(*dbgptr), dbgptr++ )
+    {
+      switch(dbgptr->type)
+	{
+	case IMAGE_DEBUG_TYPE_COFF:
+	case IMAGE_DEBUG_TYPE_CODEVIEW:
+	case IMAGE_DEBUG_TYPE_MISC:
+	  /*
+	   * This is usually an indirection to a .DBG file.
+	   * This is similar to (but a slightly older format) from the
+	   * PDB file.
+	   *
+	   * First check to see if the image was 'stripped'.  If so, it
+	   * means that this entry points to a .DBG file.  Otherwise,
+	   * it just points to itself, and we can ignore this.
+	   */
+	  if(    (dbgptr->type == IMAGE_DEBUG_TYPE_MISC)
+	      && (pe->pe_header->coff.Characteristics & IMAGE_FILE_DEBUG_STRIPPED) == 0 )
+	    {
+	      break;
+	    }
+
+	  deefer = (struct deferred_debug_info *) xmalloc(sizeof(*deefer));
+	  deefer->pe = pe;
+
+	  deefer->dbg_info = NULL;
+	  deefer->dbg_size = 0;
+
+	  /*
+	   * Read the important bits.  What we do after this depends
+	   * upon the type, but this is always enough so we are able
+	   * to proceed if we know what we need to do next.
+	   */
+	  deefer->dbg_size = dbgptr->dbgsize;
+	  deefer->dbg_info = (char *) xmalloc(dbgptr->dbgsize);
+	  lseek(fd, dbgptr->dbgoff, SEEK_SET);
+	  read(fd, deefer->dbg_info, deefer->dbg_size);
+
+	  deefer->load_addr = (char *) load_addr;
+	  deefer->dbgdir = dbgptr;
+	  deefer->next = dbglist;
+	  dbglist = deefer;
+	  break;
+	default:
+	}
+    }
+
+  return (rtn);
+
+}
+
+/*
+ * Process COFF debugging information embedded in a Win32 application.
+ *
+ * FIXME - we need to process the source file information and the line
+ * numbers.
+ */
+static
+int
+DEBUG_ProcessCoff(struct deferred_debug_info * deefer)
+{
+  struct CoffAuxSection * aux;
+  struct CoffDebug   * coff;
+  struct CoffSymbol  * coff_sym;
+  struct CoffSymbol  * coff_symbol;
+  struct CoffLinenum * coff_linetab;
+  char		     * coff_strtab;
+  int		       i;
+  DBG_ADDR	       new_addr;
+  int		       rtn = FALSE;
+  int		       naux;
+  char		       namebuff[9];
+  char		     * nampnt;
+  int		       nfiles = 0;
+  int		       nfiles_alloc = 0;
+  struct CoffFiles   * coff_files = NULL;
+  struct CoffFiles   * curr_file = NULL;
+  char		     * this_file;
+  int		       j;
+
+  coff = (struct CoffDebug *) deefer->dbg_info;
+
+  coff_symbol = (struct CoffSymbol *) ((unsigned int) coff + coff->SymbolOffset);
+  coff_linetab = (struct CoffLinenum *) ((unsigned int) coff + coff->LinenumberOffset);
+  coff_strtab = (char *) ((unsigned int) coff_symbol + 18*coff->N_Sym);
+
+  for(i=0; i < coff->N_Sym; i++ )
+    {
+      /*
+       * We do this because some compilers (i.e. gcc) incorrectly
+       * pad the structure up to a 4 byte boundary.  The structure
+       * is really only 18 bytes long, so we have to manually make sure
+       * we get it right.
+       *
+       * FIXME - there must be a way to have autoconf figure out the
+       * correct compiler option for this.  If it is always gcc, that
+       * makes life simpler, but I don't want to force this.
+       */
+      coff_sym = (struct CoffSymbol *) ((unsigned int) coff_symbol + 18*i);
+      naux = coff_sym->NumberOfAuxSymbols;
+
+      if( coff_sym->StorageClass == IMAGE_SYM_CLASS_FILE )
+	{
+	  if( nfiles + 1 >= nfiles_alloc )
+	    {
+	      nfiles_alloc += 10;
+	      coff_files = (struct CoffFiles *) realloc( coff_files,
+			nfiles_alloc * sizeof(struct CoffFiles));
+	    }
+	  curr_file = coff_files + nfiles;
+	  nfiles++;
+	  curr_file->startaddr = 0xffffffff;
+	  curr_file->endaddr   = 0;
+	  curr_file->filename =  ((char *) coff_sym) + 18;
+	}
+
+      /*
+       * This guy marks the size and location of the text section
+       * for the current file.  We need to keep track of this so
+       * we can figure out what file the different global functions
+       * go with.
+       */
+      if(    (coff_sym->StorageClass == IMAGE_SYM_CLASS_STATIC)
+	  && (naux != 0)
+	  && (coff_sym->SectionNumber == 1) )
+	{
+	  aux = (struct CoffAuxSection *) ((unsigned int) coff_sym + 18);
+	  if( curr_file->startaddr > coff_sym->Value )
+	    {
+	      curr_file->startaddr = coff_sym->Value;
+	    }
+	  
+	  if( curr_file->startaddr > coff_sym->Value )
+	    {
+	      curr_file->startaddr = coff_sym->Value;
+	    }
+	  
+	  if( curr_file->endaddr < coff_sym->Value + aux->Length )
+	    {
+	      curr_file->endaddr = coff_sym->Value + aux->Length;
+	    }
+	  
+	}
+
+      if(    (coff_sym->StorageClass == IMAGE_SYM_CLASS_STATIC)
+	  && (naux == 0)
+	  && (coff_sym->SectionNumber == 1) )
+	{
+	  /*
+	   * This is a normal static function when naux == 0.
+	   * Just register it.  The current file is the correct
+	   * one in this instance.
+	   */
+	  if( coff_sym->N.Name.NotLong )
+	    {
+	      memcpy(namebuff, coff_sym->N.ShortName, 8);
+	      namebuff[8] = '\0';
+	      nampnt = &namebuff[0];
+	    }
+	  else
+	    {
+	      nampnt = coff_strtab + coff_sym->N.Name.StrTaboff;
+	    }
+
+	  new_addr.seg = 0;
+	  new_addr.off = (int) (deefer->load_addr + coff_sym->Value);
+	  DEBUG_AddSymbol( nampnt, &new_addr, curr_file->filename );
+	}
+
+      if(    (coff_sym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL)
+	  && ISFCN(coff_sym->Type)
+          && (coff_sym->SectionNumber > 0) )
+	{
+	  if( coff_sym->N.Name.NotLong )
+	    {
+	      memcpy(namebuff, coff_sym->N.ShortName, 8);
+	      namebuff[8] = '\0';
+	      nampnt = &namebuff[0];
+	    }
+	  else
+	    {
+	      nampnt = coff_strtab + coff_sym->N.Name.StrTaboff;
+	    }
+
+	  new_addr.seg = 0;
+	  new_addr.off = (int) (deefer->load_addr + coff_sym->Value);
+
+#if 0
+	  fprintf(stderr, "%d: %x %s\n", i, new_addr.off, nampnt);
+#endif
+
+	  /*
+	   * Now we need to figure out which file this guy belongs to.
+	   */
+	  this_file = NULL;
+	  for(j=0; j < nfiles; j++)
+	    {
+	      if( coff_files[j].startaddr <= coff_sym->Value
+		  && coff_files[j].endaddr > coff_sym->Value )
+		{
+		  this_file = coff_files[j].filename;
+		  break;
+		}
+	    }
+	  DEBUG_AddSymbol( nampnt, &new_addr, this_file );
+	}
+	  
+      /*
+       * For now, skip past the aux entries.
+       */
+      i += naux;
+      
+    }
+    
+  rtn = TRUE;
+
+  if( coff_files != NULL )
+    {
+      free(coff_files);
+    }
+
+  return (rtn);
+
+}
+
+int
+DEBUG_ProcessDeferredDebug()
+{
+  struct deferred_debug_info * deefer;
+  struct CodeViewDebug	     * cvd;
+  struct MiscDebug	     * misc;
+
+  for(deefer = dbglist; deefer; deefer = deefer->next)
+    {
+      switch(deefer->dbgdir->type)
+	{
+	case IMAGE_DEBUG_TYPE_COFF:
+	  /*
+	   * Standard COFF debug information that VC++ adds when you
+	   * use /debugtype:both with the linker.
+	   */
+#if 0
+	  fprintf(stderr, "Processing COFF symbols...\n");
+#endif
+	  DEBUG_ProcessCoff(deefer);
+	  break;
+	case IMAGE_DEBUG_TYPE_CODEVIEW:
+	  /*
+	   * This is a pointer to a PDB file of some sort.
+	   */
+	  cvd = (struct CodeViewDebug *) deefer->dbg_info;
+#if 0
+	  fprintf(stderr, "Processing PDB file %s\n", cvd->cv_name);
+#endif
+	  break;
+	case IMAGE_DEBUG_TYPE_MISC:
+	  /*
+	   * A pointer to a .DBG file of some sort.
+	   */
+	  misc = (struct MiscDebug *) deefer->dbg_info;
+#if 0
+	  fprintf(stderr, "Processing DBG file %s\n", misc->Data);
+#endif
+	  break;
+	default:
+	  /*
+	   * We should never get here...
+	   */
+	  break;
+	}
+    }
+  return TRUE;
+}