Thursday, August 27, 2009

Code 7 Contest - I'm coming for you, Windows 7

To finally jump on the multiprocessor bandwagon, I bought a new computer with AMD Phenom II X4 905e on Monday.

Since I didn't have enough time to install my favorite Gentoo, I decided to quickly give Windows 7 RC a try.

I'm quite impressed with the functionality offered out of the box. All the hardware is usable and I didn't even bothered to install any drivers (except for Catalyst), since I'm going to wipe the partition clean in couple of weeks.

But as I already have Windows 7 up and running, I decided to take part in code7contest. I do not expect to win or anything - I set my goals humbly and want to at least get full version of Windows 7 (hopefully they will give them out to all participants). That's how cheap I am :).

The first couple of milestones/prerequisites are already completed:

  1. Install ViM
  2. Install Visual C++ 2008 Express (for compiler :))
  3. Install Windows 7 SDK RC
  4. Compile program using Win32 API functions introduced in Windows 7

I am very aware about the shortcomings of following code - don't copy paste it - it's just something to test if I can call Windows 7 API functions without any LoadLibrary calls.

 //snip

 WCHAR *a = (WCHAR *) malloc(100);
 
 SetCurrentProcessExplicitAppUserModelID(L"Hello");
 GetCurrentProcessExplicitAppUserModelID((PWSTR *)&a);
 MessageBox(NULL, a, a, MB_OK);

 //snip

Next task is to prepare a plan and post a milestone overview with dates.

Hopefully regular work on the contest entry will force me into updating this blog more regularly.

Wednesday, February 11, 2009

Display clipboard formats

While researching an issue with how different versions of Citrix servers and Citrix clients handle copy pasting between remote and local applications I found myself in need of a little app, which would show me what data formats I have in clipboard right now.

So here goes another utility, which I can't imagine anyone will find usefull.

#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x0610
#define UNICODE
#include <windows.h>
#define IDI_MYICON 201

int main(void)
{
 wchar_t full[50000];
 wchar_t *index = full;
 wchar_t name[255];
 unsigned int format = 0;

 OpenClipboard(NULL);

 do {
  format = EnumClipboardFormats(format);
  GetClipboardFormatName(format, name, 255);
  index += wsprintf(index, L"%d : %ls\n", format, name);
 } while (format != 0);

 MessageBox(NULL, full, L"Clipboard formats", MB_OK);

 CloseClipboard();
 return 0;
}

The code quite naïvely assumes, that the output buffer won't be longer than 50 000 characters, so in case you have so many formats in clipboard, the code will overflow. :)

For convenience binary version follows clipview.zip (6.8 kB)

If you copy paste for example Excel data into clipboard and run this program, the output will look like this:

List of clipboard format IDs and descriptions

Obligatory thanks to Mark James for creating the amazing Silk icons.

Monday, February 2, 2009

Mplayer Mouse Volume Issue

Before reinstalling my Gentoo, I had this strange issue with my mouse when watching movies in MPlayer. Everytime I clicked my left mouse button, MPlayer would increase volume.

I could easily remap the functionality of mouse in MPlayer not to mess with volume, but whichever value I remapped the functionality to, it always unpaused movies and displayed the annoying volume status over the movie.

I was looking for solution for quite some time, but the problem magically disappeared after re-installation, so I quickly forgot about it. Until yesterday of course :)

Since I have new versions of pretty much everything, I concluded, it will be issue with my configuration and not a bug.

I'm using Microsoft SideWinder mouse

Microsoft SideWinder Mouse

so I decided to dig in the logs to find out, what is going on. dmesg and /var/log weren't very helpful, so I decided to look what's going on in MPlayer.

I started MPlayer in strace

$ strace mplayer movie.ogg 2>&1 | grep input
...
open("/dev/input/js0", O_RDONLY|O_NONBLOCK|O_LARGEFILE) = 3
...

MPlayer was opening some joystick for reading. But I didn't have any joystick plugged in, since I borrowed my gamepad to a friend two days ago.

Heuréka!

Looking in /sys/devices folder, I found out, that Microsoft SideWinder mouse registers itself as mouse device as well as joystick device. Before I unplugged my gamepad, MPlayer was attaching itself to my gamepad at /dev/input/js0 and since I don't have it connected anymore, mouse gets assigned to js0.

With this knowledge, the fix was extremely easy:

echo "input:js-dev=no" >> ~/.mplayer/config

And voilá. Everything works as expected.

Friday, January 30, 2009

Sending mail with multiple attachments from Perl

It always annoys me a whole lot, when I'm writing some Unix/Linux shell script and I need to send an email with attachments - there simply isn't an easy way.

Standard mail doesn't support any attachments whatsoever, in some versions of mailx one attachment is supported and mpack is generally not available at all.

Since I found out, that some of the servers, I need to deploy my script to, don't even have uuencode installed, I decided to write myself a small standalone utility in Perl for sending multi-attachment emails.

There are lots of existing solutions in CPAN for this, but I specifically needed something, that's using only core Perl modules and sendmail - things I can count to find on every server.

#!/usr/bin/perl
use strict;
use MIME::Base64;

if ($#ARGV < 2)
{
        print(STDERR "Not enough parameters\n\n");
        print(STDERR "Usage:\n");
        print(STDERR "\t./send.pl e\@mail \"Subject\" file1 file2 ...\n");
        print(STDERR "\t./send.pl \"e\@mail,a\@ddress\" \"Subject\" file1 file2 ...\n\n");
        exit -1;
}

#Sendmail requires email addresses to be separated by comma AND space
my $to = $ARGV[0];
$to =~ s/,/, /g;

open STDOUT, "|/usr/sbin/sendmail -t";

my $boundary = "_----------=_10167391557129230";

print("Content-Transfer-Encoding: 7bit\n");
print("Content-Type: multipart/mixed; boundary=\"$boundary\"\n");
print("MIME-Version: 1.0\n");
print("Date: ".`date`);
print("To: $to\n");
print("Subject: $ARGV[1]\n\n");

for (my $i = 2; $i <= $#ARGV; $i++)
{
        my $basename = `basename $ARGV[$i]`;
        $basename =~ s/\s//g;
        print("\n--".$boundary."\n");
        print("Content-Transfer-Encoding: base64\n");
        print("Content-Type: application/octet-stream; name=\"$basename\"\n\n");

        local $/=undef;
        open FILE, $ARGV[$i] or die "Couldn't open file $ARGV[$i]";
        binmode FILE;
        my $content = <FILE>;
        close FILE;

        print encode_base64($content)."\n\n";
}

print("--$boundary\n.\n");

The code depends on two things:

  1. sendmail being available in /usr/sbin
  2. Perl core module MIME::Base64 - every standard Perl installation has this.

There is a little issue in the code - the MIME boundary is hard coded and not checked for uniqueness, but since we're using Base64 there is not much possibility of a clash.

Sunday, January 11, 2009

Free Desktop At Last

When reinstalling my Gentoo, I decided to give the radeon - open source ATI driver - a try. I have Radeon 9600XT and I always had issues with the closed source fglrx driver from ATI.

I wasn't expecting much from the free driver, but the current functionality simply blew me away - dual monitors, 3D acceleration, video playback - everything works nicely. I can't honestly think of anything more I could ask for.

Thank you guys so much!!!

Currently the stable xorg-server is version 1.3 and xorg-x11 is at version 7.2, but since I like my software freshly build (plus I wanted to give the compiz fusing a try), I had to accept the unstable packages when compiling.

ACCEPT_KEYWORDS="~x86" emerge xorg-x11 xorg-server

Gentoo is a distribution for power users/developers, so I sometimes find the release process little too conservative. I would mark packages as stable much sooner, but that's probably just me :).

So now I'm just moving wobbly windows around my desktop and grinning :))

Freedom at last.

Tuesday, January 6, 2009

Bringing Gentoo into 2009

I was forced to use Windows exclusively for past couple of months due to various reasons and I was missing my Gentoo installation a lot. As a New Year's gift to my computer I decided to reinstall the whole thing, because the installation has been quite dated with lot of unused packages, many obsolete flags and still on gcc 3.4

I was thinking how to do the installation most conveniently, but eventually decided to wipe the whole installation away and keep only

  1. /etc/passwd
  2. /etc/shadow
  3. /etc/fstab
  4. /home/

Accidentally I managed to delete my /lib folder while doing the cleanup and was left with non working system :)

Because my computer doesn't have any working CD/DVD drives and can't boot from USB, I was really happy Grub can find kernel images on FAT32 partitions

So I downloaded the Gentoo LiveCD, unpacked it to my Windows harddrive and restarted the computer

 kernel (hd0,0)/gentoo_livecd/isolinux/gentoo
 initrd (hd0,0)/gentoo_livecd/isolinux/gentoo.igz
 boot

The kernel got loaded and to my extreme surprise the gentoo.igz ramdisk contains a minimal shell with busybox, so I was able to do all the mounting, deleting and copying files I needed. Yeey from Gentoo and Linux.

So guess what I'm doing now? Compiling... :)

Monday, December 29, 2008

List your HWNDs

For Win32 GUI debugging I'm usually using WinSpector (I highly recommend it), but as it turns out WinSpector doesn't display owner windows (or maybe I just can't find it).

I was debugging a foreground activation error when the application was running through Citrix. As it turns out in certain combinations of Citrix clients and Citrix server registry setting, the windows ownership on the client is different than on the desktop.

I highly doubt this will be useful to anyone else but me, but here it goes anyway: lshwnd - program for listing all HWNDs, their parents and their owners.

#define UNICODE

#include <windows.h>
#include <vector>

wchar_t name[1000];

BOOL CALLBACK myEnum(HWND hwnd, LPARAM lParam)
{
 std::vector<HWND> *windows = (std::vector<HWND>*)lParam;
 windows->push_back(hwnd);
}

void enumerate(HWND hwnd, int depth)
{
 std::vector<HWND> windows;
 EnumChildWindows(hwnd, myEnum, LPARAM(&windows));
 GetWindowText(hwnd, name, 1000);

 for (int i = 0; i < depth; i++)
  wprintf(L"    ");
 
 wprintf(L"%x:%x - %s\n", hwnd, GetAncestor(hwnd, GA_ROOTOWNER), name);

 for (int i = 0; i < windows.size(); i++)
 {
  enumerate(windows[i], depth+1);
 }
}

int main()
{
 enumerate(NULL, 0);

 return 0;
}

Usage is quite easy, you start

lshwnd.exe > hwnd.txt
and you will get a list of all your HWNDs in a tree structure according to parent child relationship. Every HWND is represented as

parent:parent_owner parent_window_title
 child:child_owner child_window_title

Relationship structure

Version for download lshwnd.zip - 11 kB

Friday, December 26, 2008

Snooping on TCP connections - Putting the MAN in the Middle

It's quite often when debugging a networking application, that you have to look at the underlaying data. You might say, this is very easy with existing tools like tcpdump and windump. But let's say you have to do it on a remote server without admin rights. Suddenly the task is not so easy.

You can usually get away with telnet in case you need to simulate the client or more preferably netcat (where you can simulate the server as well). However sometimes you just want to watch the communication between two endpoints.

You basically need a tunnel, that will forward all communication and simultaneously write all the data to file / screen.

I wrote a little program for that, it's called middleman and it saves all communication in files. New file is created for every connection and raw data from both endpoints are written into this one file. If the protocol, you will be monitoring is hard to understand, you can modify the program to split the communication into two files, the program is quite simple, so it shouldn't be much of a problem:

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;

class Client
{
 int id;
 TcpClient local;
 TcpClient remote;
 NetworkStream localStream;
 NetworkStream remoteStream;
 FileStream file;

 public Client(TcpClient newLocal, string remoteAddress, int remotePort, int nid)
 {
  local = newLocal;
  localStream = local.GetStream();
  remote = new TcpClient(remoteAddress, remotePort);
  remoteStream = remote.GetStream();
  id = nid;

  file = new FileStream("session_" + Convert.ToString(nid) + ".txt", FileMode.Create);
 }

 public void process()
 {
  int time = 0;
  int i;
  Byte[] bytes = new Byte[4096];
  while(true)
  {
   if (localStream.DataAvailable)
   {
    if ( (i = localStream.Read(bytes, 0, bytes.Length)) != 0)
    {
     try 
     {
      if (remoteStream.CanWrite)
      {
       remoteStream.Write(bytes, 0, i);
       file.Write(bytes, 0, i);
      }
     }
     catch (Exception)
     {
      break;
     }
    }
    time = 0;
   }

   if (remoteStream.DataAvailable)
   {
    if ( (i = remoteStream.Read(bytes, 0, bytes.Length)) != 0)
    {
     try
     {
      if (localStream.CanWrite)
      {
       localStream.Write(bytes, 0, i);
       file.Write(bytes, 0, i);
      }
     }
     catch (Exception)
     {
      break;
     }
    }
    time = 0;
   }

   time++;

   Thread.Sleep(1);

   if (time > 5000)
    break;
  }
  remote.Close();
  local.Close();
  file.Close();
 }
}

class ManInTheMiddle
{
 static int Main(string[] args)
 {
  int localPort, remotePort;
  string localAddress, remoteAddress;

  switch (args.Length)
  {
   case 2 :
    remoteAddress = args[0];
    remotePort = localPort = Int32.Parse(args[1]);
    localAddress = "127.0.0.1";
    break;

   case 3:
    remoteAddress = args[0];
    remotePort = Int32.Parse(args[1]);
    localAddress = "127.0.0.1";
    localPort = Int32.Parse(args[2]);
    break;
   case 4:
    remoteAddress = args[0];
    remotePort = Int32.Parse(args[1]);
    localAddress = args[2];
    localPort = Int32.Parse(args[2]);
    break;
   default:
    Console.WriteLine("MiddleMan - Tool for snooping on TCP/IP connections");
    Console.WriteLine("");
    Console.WriteLine("Usage: middleman remote_server port");
    Console.WriteLine("Usage: middleman remote_server remote_port local_port");
    Console.WriteLine("Usage: middleman remote_server remote_port local_ip_address local_port");
    Console.WriteLine("");
    Console.WriteLine("");
    Console.WriteLine("MiddleMan starts listening as a server on local_ip_address (default 127.0.0.1)");
    Console.WriteLine("on local_port. All incoming connections to this server are forwarded");
    Console.WriteLine("to remote_server:remote_port and logged into a file.");
    Console.WriteLine("");
    Console.WriteLine("");
    return 0;
  }
  
  TcpListener server = new TcpListener(IPAddress.Parse(localAddress), localPort);
  server.Start();

  int id = 0;

  while(true)
  {
   Client client = new Client(server.AcceptTcpClient(), remoteAddress, remotePort, id++);
   Thread w = new Thread(new ThreadStart(client.process));
   w.Start();
  }
 }
}

The usage is quite simple, you specify the IP address or hostname, which you want to connect your tunnel to and the port

middleman www.google.com 80

From now on, all the communication that goes to localhost:80 will be forwarded to google:80 and will be simultaneously written to a file

In case you specify only one port (as in the example above), middleman will start listening on the same port as is the remote server listening on (in this case 80). If for whatever reason you can't use the same port on the local machine, you can start middleman like this:

middleman www.google.com 80 81

which means - forward all requests from localhost:81 to google.com:80

Simple demonstration video follows:

Download middleman.zip - 6kB

Obligatory thanks to Mark James for creating the amazing Silk icons.

Wednesday, December 24, 2008

Ludum Dare 2008

The theme of this year's Ludum Dare competition was "Roads". So how did I do?

The game

Here is a video from my game

and the game itself Chopper vs Trucks 3 MB

The Backend

In the beginning I wanted to use Lua to define the game logic, but I found out, that it's not easy to integrate OPP with Lua, so I wrote the whole logic in C++. But I definitely want to investigate Lua integration with C++ further to use it in my following projects.

What really paid of was my one-click deployment system. I was running a webserver on my development PC and every time I wanted to test something I made a release:

7zip a -r -x!.\* /$(RELEASE_DIR)/angiine.release/angiine$(DATE).7z $(ANGIINE_DIR)
cp /$(RELEASE_DIR)/angiine.release/angiine$(DATE).7z /$(RELEASE_DIR)/angiine.release/angiine_current.7z

And on the target computer I had a batch file looking like this

wget http://server/angiine_current.7z
7z x angiine.current.7z
cd angiine/bin/
./angiine

The whole cycle "recompile, package, download, unpack and start" took about ten to fifteen seconds. I was able to test the game on two different computers almost seamlessly and I can't recommend this hard enough.

For real masochist you can check you all the versions of the game I managed to produce during the 48 hours - angiine.releases.7z 4 MB

The Progress

During the compo, I spent quite some time on loading 3D models to my C++ program. I should have prepared my base library and not waste my time with this during the competition time.

Here are some progress screenshots of the game:

Progress screenshot #1 Progress screenshot #2 Progress screenshot #3 Progress screenshot #4 Final screenshot #1 Final screenshot #2

For more information, you can look at my almost award winning journal :) here

Statistics

For anyone interested, here is my timelapse

This is an overview of which programs I used the most during the competition:

Results

Overall32/59
Fun39/59
Innovation28/59
Theme42/59
Polish40/59
Graphics20/59
Audio42/59
Humor28/59
Technical12/59
Food28/59
Journal5/59
Towlr29/59
My best scores were in categories Journal (5th place - link) and Technical (12th place). I'm very happy about that, but I will definitely try to do better next time :).

So that was my Ludum Dare compo overview - I had extreme fun, I slept very little and after turning my game in, I got amazing sense of accomplishment. Kudos to the organizers, I'm already looking forward to the next one.

Tuesday, December 2, 2008

Preparing for Ludum Dare 2008 - Take multimonitor screenshots

It's part of the whole Ludum Dare experience to record your desktop every few minutes and create a movie afterwords which overviews your progress.

Since I recently became a proud owner of a second monitor, I found myself in need for a multi-monitor screenshot making tool. There are probably some utilities, which do exactly that, but I'm too lazy to look for them and decided to write my own tool.

This is just a very stupid prototype, which I will be using/testing during the competition. It doesn't save the files into one image but one image per monitor. That's kind of unfortunate, but composing picture from different DCs is no fun.

The other thing the program does is that it records which program was in foreground while you took the screenshot and records the data into sqlite database

So afterwards you can just start sqlite3 data.db and type in following command:

SELECT process, count(*) AS sum FROM work GROUP BY process ORDER BY sum;

You'll receive a nice overview about which application you used the most during the competition / monitoring time.

Here you can see my relative application use in the past 10 months on my work computer:

I spend more than 50% of my time in firefox

I guess I'm researching a lot :)

So for anyone interested, the download is - logger-0.1.zip (300 kB)

Thanks to Mark James for creating the amazing Silk icons.