detect EXE/DLL bitness (x86 or x64)

Discuss and share scripts and script files...
bdeshi
Posts: 4256
Joined: 12 Mar 2014 17:27
Location: Asteroid B-612
Contact:

detect EXE/DLL bitness (x86 or x64)

Post by bdeshi »

Hi, here's a script to detect whether a selected binary executable file is 64bits or 32bits, or 16 bits, or DOS. Feel free to use it or modify it as you need.(in fact I'll be glad if you do :D )

See posts below for much better and more useful updates of this script

Versions:
v2: http://www.xyplorer.com/xyfc/viewtopic. ... 74#p111439
v3: http://www.xyplorer.com/xyfc/viewtopic. ... 74#p111498
v4: http://www.xyplorer.com/xyfc/viewtopic. ... 74#p111515
v5: http://www.xyplorer.com/xyfc/viewtopic. ... 74#p111533
v6: http://www.xyplorer.com/xyfc/viewtopic. ... 15#p111620

=============
These are the original very basic first versions of the script and CC by me, kept here for history's sake.
Script:

Code: Select all

"Bitness Detector"
//first version, by SammaySarkar, 13th April, 2014
  $filext = getpathcomponent(<curitem>,ext);
  if ($filext == "exe") || ($filext == "dll") || ($filext == "ocx") || ($filext == "cpl") { $file = "<curitem>"; }
  else { $file = inputfile("<curpath>","exe|dll|ocx|cpl", "Choose a valid file"); }
  unset $filext;
  if ( readfile($file, b, 2,, 1) == "MZ" ) {
    $pntr = hexdump(readfile($file, b, 4,, 61),,r);
    $pntr = hextodec(gettoken($pntr,2).gettoken($pntr,1));
    if ($pntr-8 <= filesize($file)) {
      $bitnum = hexdump(readfile($file, b, 6,, $pntr+1),,r);
      if     ( strpos($bitnum, '64 86') != -1 ) { msg "$file<crlf>is 64 bit."; }
      elseif ( strpos($bitnum, '00 02') != -1 ) { msg "$file<crlf>is 64 bit (IA64)."; }
      elseif ( strpos($bitnum, '4C 01') != -1 ) { msg "$file<crlf>is 32 bit."; }
      elseif (strpos($bitnum, '4E 45') != -1) || (strpos($bitnum, '4C 45') != -1) { msg "$file<crlf>is 16 bit."; }
      //elseif(  ) { msg"$file<crlf>is  bit"; }
      else { msg "$file<crlf>is a DOS program."; }
    } else { msg "$file<crlf>is probably a DOS program."; }
  } else { msg "Cannot detect bitness."; }
[/size]CustomColum snippet:

Code: Select all

Snip: CustomColumn 1
  XYplorer 14.00.0115, 5/14/2014 08:49:06 AM
Action
  ConfigureColumn
Caption
  Bitness
Type
  3
Definition
    $file = <cc_item>;
    if (readfile($file, b, 2, , 1) == "MZ") {
      $pntr   = hexdump(readfile($file, b, 4, , 61),,r);
      $pntr   = hextodec(gettoken($pntr,2).gettoken($pntr,1));
      if ($pntr-8 <= filesize($file)) {
        $bitnum = hexdump(readfile($file, b, 6,, $pntr+1), ,r);
        if     (strpos($bitnum, '64 86') != -1) { return "64bit"; }
        elseif (strpos($bitnum, '00 02') != -1) { return "~64bit"; }
        elseif (strpos($bitnum, '4C 01') != -1) { return "32bit"; }
        elseif (strpos($bitnum, '4E 45') != -1)||(strpos($bitnum, '4C 45') != -1) { return "16bit"; }
        else { return "DOS"; }
      } else { return "~DOS"; }
    } else { return "N/A"; }
Format
  0
Trigger
  1
Item Type
  0
Item Filter
  exe;dll;ocx;cpl
[/size]
It only detects "plain" 64bit and 32bit files, old DOS exe's and .NET is unsupported.
Check posts below for better detection.
Last edited by bdeshi on 14 May 2014 09:23, edited 4 times in total.
Icon Names | Onyx | Undocumented Commands | xypcre
[ this user is asleep ]

admin
Site Admin
Posts: 65075
Joined: 22 May 2004 16:48
Location: Win8.1, Win10, Win11, all @100%
Contact:

Re: detect EXE/DLL bitness (x86 or x64)

Post by admin »

Nice one! :appl:

With the new hexdump() you could even streamline it a bit... ;)

bdeshi
Posts: 4256
Joined: 12 Mar 2014 17:27
Location: Asteroid B-612
Contact:

Re: detect EXE/DLL bitness (x86 or x64)

Post by bdeshi »

Thanks, right.
Icon Names | Onyx | Undocumented Commands | xypcre
[ this user is asleep ]

bdeshi
Posts: 4256
Joined: 12 Mar 2014 17:27
Location: Asteroid B-612
Contact:

Re: detect EXE/DLL bitness (x86 or x64)

Post by bdeshi »

Okay, updated the script. Has basic detection of 16bit files. But more importantly, it won't generate a fatal error anymore when bytes to read are out of file size limits.
Tested in CustomColumn, pretty fast, so posted a CC script too.


And... it's more user-friendly now, can I ask this thread be moved to scripts exchange? :oops:
v
Thank you! :)
Last edited by bdeshi on 20 May 2014 19:10, edited 4 times in total.
Icon Names | Onyx | Undocumented Commands | xypcre
[ this user is asleep ]

admin
Site Admin
Posts: 65075
Joined: 22 May 2004 16:48
Location: Win8.1, Win10, Win11, all @100%
Contact:

Re: detect EXE/DLL bitness (x86 or x64)

Post by admin »

Sure, thanks! :)

Enternal
Posts: 1174
Joined: 10 Jan 2012 18:26

Re: detect EXE/DLL bitness (x86 or x64)

Post by Enternal »

Amazing! I just found several uses for it! Thanks!

bdeshi
Posts: 4256
Joined: 12 Mar 2014 17:27
Location: Asteroid B-612
Contact:

Re: detect EXE/DLL bitness (x86 or x64)

Post by bdeshi »

Ah, your comment made it a success!!! thank you!
Icon Names | Onyx | Undocumented Commands | xypcre
[ this user is asleep ]

PeterH
Posts: 2826
Joined: 21 Nov 2005 20:39
Location: DE W11Pro 24H2, 1920*1200*100% 3840*2160*150%

Re: detect EXE/DLL bitness (x86 or x64)

Post by PeterH »

SammaySarkar wrote:Hi, here's a script to detect whether a selected exe/dll/ocx/cpl file is 64bits or 32bits, or 16 bits, or DOS apps. Feel free to use it or modify it as you need.(in fact I'll be glad if you do :D )
Hi Sammay,
you asked for changes - here are some.

Real functional changes:
- centralized the allowed extensions to variable $extlist
- added extension 'sys'
- test for extension by GetTokenIndex(), allow mixed case

Non-functional
- added some quotes for syntax (e.g. 'b')
- added some blanks and some empty lines for format

The code:

Code: Select all

"BitnessDetector"

// by SammaySarkar, modified by PeterH 2014-09-09

  $extlist = 'exe|dll|ocx|cpl|sys';  // allowed extentions

  $filext = getpathcomponent(<curitem>,ext);
  If (GetTokenIndex($filext, $extlist, , 'i') > 0) { $file = "<curitem>"; }
  Else { $file = Inputfile("<curpath>", $filext, "Choose a valid file"); }
  if (readfile($file, 'b', 2, , 1) == "MZ") {
    $pntr = hexdump(readfile($file, 'b', 4, , 61), , 'r');
    $pntr = hextodec(gettoken($pntr, 2) . gettoken($pntr, 1));
    if ($pntr-8 <= filesize($file)) {
      $bitnum = hexdump(readfile($file, 'b', 6, , $pntr+1), , 'r');
      if     (strpos($bitnum, '64 86') != -1) { msg "$file<crlf>is 64 bit."; }
      elseif (strpos($bitnum, '00 02') != -1) { msg "$file<crlf>is 64 bit (IA64)."; }
      elseif (strpos($bitnum, '4C 01') != -1) { msg "$file<crlf>is 32 bit."; }
      elseif (strpos($bitnum, '4E 45') != -1)
          || (strpos($bitnum, '4C 45') != -1) { msg "$file<crlf>is 16 bit."; }
    //elseif (...)                            { msg "$file<crlf>is    bit."; }
      else { msg "$file<crlf>is a DOS program."; }
    }
    else { msg "$file<crlf>is probably a DOS program."; }
  }
  else { msg "Cannot detect bitness."; }
If OK you can copy it to first post.
Open for further suggestions...

bdeshi
Posts: 4256
Joined: 12 Mar 2014 17:27
Location: Asteroid B-612
Contact:

Re: detect EXE/DLL bitness (x86 or x64)

Post by bdeshi »

Of coure it's okay.I just replaced my original script (which reeked of noobidity :whistle: )
Much appreciated.

Edit 10th sep, 2014: since there have been many updates, I repasted my original script back in the first post (which does still reek of "noobidity" :lol: )
Icon Names | Onyx | Undocumented Commands | xypcre
[ this user is asleep ]

Snail
Posts: 22
Joined: 08 Sep 2014 17:05

Re: detect EXE/DLL bitness (x86 or x64)

Post by Snail »

Very nice.
Here is a little more updating.

Code: Select all

    "BitnessDetector"

    // by SammaySarkar, modified by PeterH 2014-09-09, and Snail 2014-09-09.
    // Expanded extensions list, added COM support, added more details, added none ext error trap, improved open file, added limited packed exe support.

	$extlist = 'exe|dll|ocx|cpl|sys|com';  // allowed extensions

      $filext = getpathcomponent(<curitem>, ext);
      If (GetTokenIndex($filext, $extlist, , 'i') > 0) { $file = "<curitem>"; }
       Else { msg "BIT testable files limited to<crlf>$extlist.<crlf>.$filext is not valid!";
              $file = Inputfile("<curpath>", $extlist, "Choose a valid file");
                $filext = ""; }
      if (readfile($file, 'b', 2, , 1) == "MZ") {
        $pntr = hexdump(readfile($file, 'b', 4, , 61), , 'r');
        $pntr = hextodec(gettoken($pntr, 2) . gettoken($pntr, 1));
        if ($pntr-8 <= filesize($file)) {
          $bitnum = hexdump(readfile($file, 'b', 6, , $pntr+1), , 'r');
           $byteme = $bitnum;

 // HI-Lo bits are inverted!

          if     (strpos($bitnum, '64 86') != -1) { msg "$file<crlf>is AMD64 WinPE+ Lite x64 bit $filext."; }
          elseif (strpos($bitnum, '02 00') != -1) { msg "$file<crlf>is IA64 WinPE+ x64 bit $filext."; }
          elseif (strpos($bitnum, '0B 00') != -1) { msg "$file<crlf>is Magic # x64 bit $filext."; }
          elseif (strpos($bitnum, '0B 01') != -1) { msg "$file<crlf>is Magic # 32 bit $filext."; }
          elseif (strpos($bitnum, '0B 02') != -1) { msg "$file<crlf>is Magic # 64 bit $filext."; }
          elseif (strpos($bitnum, '07 01') != -1) { msg "$file<crlf>is ROM non-bit $filext."; }
          elseif (strpos($bitnum, '00 4C') != -1) { msg "$file<crlf>is WinPE x86 32 bit $filext."; }
          elseif (strpos($bitnum, '01 4C') != -1) { msg "$file<crlf>is i386 WinPE 32 bit $filext."; }
          elseif (strpos($bitnum, '07 06') != -1) { msg "$file<crlf>is DOS Compiled 16 bit $filext."; }
          elseif (strpos($bitnum, '0C A5') != -1) { msg "$file<crlf>is DOS Executable 16 bit $filext."; }
          elseif (strpos($bitnum, '4E 45') != -1)
              || (strpos($bitnum, '4C 45') != -1) { msg "$file<crlf>is WinNE 16 bit $filext."; }
        }
        else { msg "$file<crlf>is probably a PACKED executable."; }
      }
      else { msg "Cannot detect bitness.<crlf>Probably a PACKED executable."; }

A lot more could be done, such as searching of UPX and .DATA blocks to indicate types of packed executables.

bdeshi
Posts: 4256
Joined: 12 Mar 2014 17:27
Location: Asteroid B-612
Contact:

Re: detect EXE/DLL bitness (x86 or x64)

Post by bdeshi »

That's so much better! thank you.
Icon Names | Onyx | Undocumented Commands | xypcre
[ this user is asleep ]

TheQwerty
Posts: 4373
Joined: 03 Aug 2007 22:30

Re: detect EXE/DLL bitness (x86 or x64)

Post by TheQwerty »

To keep the changes going...
BitnessDetector.xys
(4.04 KiB) Downloaded 290 times
This is a much bigger modification...
  1. Easier to use the script standalone or as a Custom Column Script.*
  2. Thus descriptions were reworded for better sorting in a column.
  3. Determines which item(s) to test in the following order:
    1. Tagged / Custom Column Item
    2. PFA/POM Item
    3. Dropped Item(s)
    4. Selected Item(s)
    5. Focused Item
  4. That's right items with an 's' it supports more than one.
  5. Moved the magic bits into a list - might be easier to update.
* To use this script for a custom column script you must first set the Global variable $G_INTERACTIVE to false.
This is because the <cc_*> variables persist outside of the Custom Column Script meaning there is no good way to detect when the script should be in interactive mode. In other words your custom column for this script should look like:

Code: Select all

Global $G_INTERACTIVE = false;Load 'BitnessDetector';
Here we go:

Code: Select all

/*#############################################################################\
BitnessDetector.xys

This script attempts to determine for which architecture binaries and executables
are compiled.

It can be used as-is or within a Custom Column Script, but note that due to
limitations in XY the Custom Column Script must set a Global variable
'$G_INTERACTIVE' to 'false' before calling the script. Example:
Global $G_INTERACTIVE = false;
Load 'BitnessDetector';


See also:
  http://www.xyplorer.com/xyfc/viewtopic.php?f=7&t=11574


[ABOUT]
Author       = SammaySarkar
Version      = 4.0
Date         = 2014-09-09 16:00z
Requires     = XYplorer v14.40.0300

Contributors = PeterH, Snail, TheQwerty

[]
\#############################################################################*/

"BitnessDetector"
  // Changed separator to semi-colon so it matches CC filter.
  $SUPPORTED_EXTENSIONS = 'exe;dll;ocx;cpl;sys;com';  // allowed extensions

  // Unfortunately the <cc_*> vars persist outside the scope of the CC script,
  // so there is no way to determine when running within a CC script.
  // Until Don makes this possible we'll use a global variable.
  // http://www.xyplorer.com/xyfc/viewtopic.php?f=3&t=11181&p=111509#p111509
  // Thus it is the responsibility of the CC script to set:
  // Global $G_INTERACTIVE = false;
  Global $G_INTERACTIVE;
  if ($G_INTERACTIVE == '') {
    $G_INTERACTIVE = true;
  }


  // If not interactive...
  if (! $G_INTERACTIVE) {
    // Assume we are in a Custom Column.
    $list = "<cc_item>";

  } else {
    // Determine items to work on.
    // <cc_item> is removed because of the above-mentioned issue with their scope.
    // If fixed it will probably be #3.
    $list = GetToken(FormatList("<taggeditem>|<pfaitem>|<get drop <crlf>>|<get SelectedItemsPathNames <crlf>>|<focitem>", 'ted'), 1, '|');
  }

  // These are the magic bits and descriptions.
  // Try to keep bitness first so it sorts better in a custom column.
  $magicBits = <<<#KNOWNBITS
    64 86|64-bit [AMD64 WinPE+ Lite]
    02 00|64-bit [IA64 WinPE+]
    0B 00|64-bit [Magic # x64]
    0B 01|32-bit [Magic # 32]
    0B 02|64-bit [Magic # 64]
    07 01|ROM non-bit
    00 4C|32-bit [WinPE x86]
    01 4C|32-bit [i386 WinPE]
    07 06|16-bit [DOS Compiled]
    0C A5|16-bit [DOS Executable]
    4[CE] 45|16-bit [WinNE]
  #KNOWNBITS;

  // Collection of all results.
  $allResults = '';

  foreach ($item, $list, "<crlf>") {
    if ($item == '') { continue; }

    $result = 'Unknown';

    // Not a file.
    if (exists($item) != 1) {
      $result = 'Not a file.';

    // Unsupported extension.
    } elseif (! GetTokenIndex(GetPathComponent($item, 'ext'), $SUPPORTED_EXTENSIONS, ';', 'i')) {
      $result = 'Extension not supported';

    // Missing MZ header.
    } elseif (ReadFile($item, 'b', 2, /*codepage*/, 1) != 'MZ') {
        $result = 'Maybe PACKED - Not MZ';

    // Contains MZ header.
    } else {
      $pntr = HexDump(ReadFile($item, 'b', 4, /*codepage*/, 61), 0, 'r');
      $pntr = HexToDec(GetToken($pntr, 2) . GetToken($pntr, 1));

      // Pointer out of range.
      if ($pntr-8 > FileSize($item)) {
        $result = 'Maybe PACKED';
      } else {
        $bitnum = HexDump(ReadFile($item, 'b', 6, /*codepage*/, $pntr+1), 0, 'r');

        foreach ($line, $magicBits, "<crlf>") {
          // Trim line & skip empties.
          $line = Trim($line, " <tab><crlf>");
          if ($line == '') { continue; }

          // Split line
          $pattern = GetToken($line, 1, '|', 't');
          $text = GetToken($line, 2, '|', 't', 2);

          // Check for match
          if ($bitnum LikeI "*$pattern*") {
            $result = $text;
            break;
          }
        } // foreach - knownBits
      } // valid pointer
    } // MZ header

    $allResults = $allResults . $item . "<crlf><tab>" . $result . "<crlf>";
  } // foreach - list

  // Display results when not in a Custom Column.
  if ($G_INTERACTIVE) {
    Text $allResults;
  } else {
    return $result;
  }
[/size]

klownboy
Posts: 4399
Joined: 28 Feb 2012 19:27
Location: Windows 11, 25H2 Build 26200.7171 at 100% 2560x1440

Re: detect EXE/DLL bitness (x86 or x64)

Post by klownboy »

TheQwerty wrote:To keep the changes going...
and they keep getting better. Thanks to all. :appl:

Snail
Posts: 22
Joined: 08 Sep 2014 17:05

Re: detect EXE/DLL bitness (x86 or x64)

Post by Snail »

A very nice update!

I have taken it and expanded a little more. Mainly, I've added more recognition for older/odd executables.

Code: Select all

/*#############################################################################\
BitnessDetector.xys

This script attempts to determine for which architecture binaries and executables
are compiled.

It can be used as-is or within a Custom Column Script, but note that due to
limitations in XY the Custom Column Script must set a Global variable
'$G_INTERACTIVE' to 'false' before calling the script. Example:
Global $G_INTERACTIVE = false;
Load 'BitnessDetector';


See also:
  http://www.xyplorer.com/xyfc/viewtopic.php?f=7&t=11574


[ABOUT]
Author       = SammaySarkar
Version      = 5.0
Date         = 2014-09-10 02:00z
Requires     = XYplorer v14.40.0300

Contributors = PeterH, Snail, TheQwerty

[]
\#############################################################################*/

"BitnessDetector"
  // Changed separator to semi-colon so it matches CC filter.
  $SUPPORTED_EXTENSIONS = 'exe;dll;ocx;cpl;sys;com;gem;app;elf';  // allowed extensions

  // Unfortunately the <cc_*> vars persist outside the scope of the CC script,
  // so there is no way to determine when running within a CC script.
  // Until Don makes this possible we'll use a global variable.
  // http://www.xyplorer.com/xyfc/viewtopic.php?f=3&t=11181&p=111509#p111509
  // Thus it is the responsibility of the CC script to set:
  // Global $G_INTERACTIVE = false;
  Global $G_INTERACTIVE;
  if ($G_INTERACTIVE == '') {
    $G_INTERACTIVE = true;
  }


  // If not interactive...
  if (! $G_INTERACTIVE) {
    // Assume we are in a Custom Column.
    $list = "<cc_item>";

  } else {
    // Determine items to work on.
    // <cc_item> is removed because of the above-mentioned issue with their scope.
    // If fixed it will probably be #3.
    $list = GetToken(FormatList("<taggeditem>|<pfaitem>|<get drop <crlf>>|<get SelectedItemsPathNames <crlf>>|<focitem>", 'ted'), 1, '|');
  }

  // These are the magic bits and descriptions.
  // Try to keep bitness first so it sorts better in a custom column.
  $magicBits = <<<#KNOWNBITS
    64 86|64-bit [AMD64 WinPE+ Lite]
    02 00|64-bit [IA64 WinPE+]
    0B 00|64-bit [Magic # x64]
    0B 01|32-bit [Magic # 32]
    0B 02|64-bit [Magic # 64]
    07 01|ROM non-bit
    00 4C|32-bit [WinPE x86]
    01 4C|32-bit [i386 WinPE]
    07 06|16-bit [DOS Compiled]
    0C A5|16-bit [DOS Executable]
    4[CE] 45|16-bit [WinNE]
  #KNOWNBITS;


  // Collection of all results.
  $allResults = '';

  foreach ($item, $list, "<crlf>") {
    if ($item == '') { continue; }

    // Set header MZ value
    $header = ReadFile($item, 'b', 2, /*codepage*/, 1);

    // Default responce if no other provided.
    $result = 'File may be PACKED (exe/com).';

    // Not a file.
    if (exists($item) != 1) {
      $result = 'Not a suported file.';
	  
    // Unsupported extension.
    } elseif (! GetTokenIndex(GetPathComponent($item, 'ext'), $SUPPORTED_EXTENSIONS, ';', 'i')) {
      $result = 'Extension not supported'<crlf>'Current support for > ' . $SUPPORTED_EXTENSIONS;

    // Missing MZ header.
    }   elseif ($header != 'MZ') {
        $result = 'File may be packed with UPX/PKLite/ASPack'<crlf>'or other protection.'<crlf>'Or, it may not be an executable file at all.'<crlf>' - Not MZ';

    // Old non-MZ executbles.
    }   elseif ($header == 'NE') {
        $result = 'File may be DOS4 8bit or Win3x 16bit.'<crlf>' - Not MZ';

    }   elseif ($header == 'LX') {
        $result = 'File may be OS/2 8bit.'<crlf>' - Not MZ';

    }   elseif ($header == 'PI') {
        $result = 'File may be PalmDOS 8bit.'<crlf>' - Not MZ';

    }   elseif ($header == 'XI') {
        $result = 'File may be PalmDOS Extended 16bit.'<crlf>' - Not MZ';

    }   elseif ($header == 'DL') {
        $result = 'File may be DOS Manager 8bit.'<crlf>' - Not MZ';

    }   elseif ($header == 'MP') {
        $result = 'File may be DOS Extender 8bit.'<crlf>' - Not MZ';

    }   elseif ($header == 'P2') {
        $result = 'File may be DOS Extender 16bit.'<crlf>' - Not MZ';

    }   elseif ($header == 'P3') {
        $result = 'File may be DOS Extender 32bit.'<crlf>' - Not MZ';

    // Contains MZ header.
    } else {
      $pntr = HexDump(ReadFile($item, 'b', 4, /*codepage*/, 61), 0, 'r');
      $pntr = HexToDec(GetToken($pntr, 2) . GetToken($pntr, 1));

      // Pointer out of range.
      if ($pntr-8 > FileSize($item)) {
        $result = 'Maybe PACKED';
      } else {
        $bitnum = HexDump(ReadFile($item, 'b', 6, /*codepage*/, $pntr+1), 0, 'r');

        foreach ($line, $magicBits, "<crlf>") {
          // Trim line & skip empties.
          $line = Trim($line, " <tab><crlf>");
          if ($line == '') { continue; }

          // Split line
          $pattern = GetToken($line, 1, '|', 't');
          $text = GetToken($line, 2, '|', 't', 2);

          // Check for match
          if ($bitnum LikeI "*$pattern*") {
            $result = $text;
            break;
          }
        } // foreach - knownBits
      } // valid pointer
    } // MZ header


    $allResults = $allResults . $item . "<crlf><tab>" . $result . "<crlf>";
  } // foreach - list

  // Display results when not in a Custom Column.
  if ($G_INTERACTIVE) {
    Text $allResults;
  } else {
    return $result;
  }
BitnessDetector.zip
(2.15 KiB) Downloaded 268 times

bdeshi
Posts: 4256
Joined: 12 Mar 2014 17:27
Location: Asteroid B-612
Contact:

Re: detect EXE/DLL bitness (x86 or x64)

Post by bdeshi »

Nice to see so much interest...
( if this goes on, I see this script becoming Ultimate File Detector... :biggrin: )

BTW, there's absolutely no reason now to have me as the only author. This intro note is better suited:

Code: Select all

...
[About]
Authors      = PeterH, SammaySarkar, Snail, TheQwerty
...
Icon Names | Onyx | Undocumented Commands | xypcre
[ this user is asleep ]

Post Reply