

   intro.

   while i was looking into the 'non executable first section' problem i came
   to realize that it would take relatively little code to write a loader32
   replacement, what's more, i could add DLL support as well (the lack of
   which is so much annoying for us ;-). so iceload was born and with a little
   tweaking over a few days me, G-RoM and muffin are happy to present you the
   result.
   

   usage.

      iceload [[-r]|[-n] file.dll]
      iceload [file.exe]

   file.*: may specify path, using long file names if necessary

   -r:     forces the DLL to relocate (or not load if it cannot due to missing
           relocations)

   -n:     notifies SoftICE about the DLL but will not load it, instead you
           should start up the target application which uses the DLL. this
           switch obviously cannot be used with -r.

   executing iceload without any parameters will start up its GUI which should
   be intuitive enough (watch the tooltips, courtesy of muffin ;-). SoftICE is
   automatically notified about the selected file, but it is not loaded (.dll)
   (as if the -n switch had been specified) or executed (.exe) immediately,
   use the 'Load/Run' icon for that. the GUI also lets you load exports from
   a DLL and save the SoftICE history buffer.

   keyboard accelerators (thanks to the rain for the idea):

      CTRL+O = Open PE
      CTRL+X = Exit
      CTRL+R = Run
      CTRL+L = Load exports
      CTRL+S = Save SI history
      CTRL+A = About


   technotes.

   this section explains how the whole thing works, might be of some interest
   to some people after all.

   nmtrans.NmSymLoadExecutableEx is the main function responsible for telling
   SoftICE where to put a breakpoint in a given module. it further calls down
   to nmtrans.NmSymGetModuleLoadRecord which among other things will decide
   what sort of module the user managed to select (can be various executable
   formats, symbol files, etc). as you can guess, a PE exe has a different ID
   than a DLL.

   next it calls nmtrans.NmSymIsModuleLoadable to figure out if SoftICE should
   be told about this module or not. guess what, a DLL is explicitly declared
   as non-loadable (although technically it is) and thus loader32/nmtrans will
   not even try to notify SoftICE.

   what's more, when nmtrans.NmSymLoadExecutableEx notifies SoftICE via
   nmtrans.DevIO_SetWLDRBreak (which in turn uses DeviceIoControl) and submits
   information about the module, it sends a flag which tells SoftICE whether
   the module is a PE exe or not (based on the type ID and not on what
   nmtrans.NmSymIsModuleLoadable said). as you might guess it, SoftICE sets
   a breakpoint on the entry point only if that flag is set...

   so to solve the problem we simply call nmtrans.NmSymGetModuleLoadRecord
   and then nmtrans.DevIO_SetWLDRBreak ourselves with that flag set. these
   two APIs are the sole reason for requiring nmtrans.dll and could have
   been replaced with handcoded versions, but development time over file
   size takes priority for such little gizmos ;-)
