Botting Helena? Fake Russian Facebook accounts… Why?

Well, this is odd. I noticed last night that I had a bunch of Facebook posts liked by someone who isn’t a friend (friend of a friend), but the activity looks highly suspicious…

image

Immediately that looks off because

  • They happened very quickly in succession. In fact they’re the top few posts if you go directly to my page, the last things I posted before my current ban.
  • They’re only “like” reactions… no laughs or more specific reacts. Actual humans tend to choose the more specific reactions.

That aside… the second one “she” liked is this:
image

That’s right… “She” liked a post that can’t even be seen anymore. It’s a share of something that has by now been set to private or removed. Why like it if you can’t even read it? (Because you’re a bot.)

So this looks like a bot. No friend request though. How odd. Going to the Facebook wall of this stranger, this gets even stranger… Her posts are nothing but leftist US political links and profile pics.

Here’s the thing… You can normally reverse image search the profile pictures of fake accounts and find their source fairly quickly, be it an Instagram model, porn star, escort, or maybe a picture regularly associated with scammy dating sites. They’re very easy to find. Normally.

But not this one. I get nothing. All the images are obviously of the same person. The profile is 100% fake – I guarantee it. And the model used even has a very prominent tattoo with “Life is beautiful” on her right shoulder blade. Yet I find nothing when I search these images.

So this is a carefully created fake account, with images that I couldn’t trace. I wonder why that is? Why go to such trouble to create a fake account? I can only guess the like reacts were made to generate “real” looking account activity.

Here’s a copy of one of the images where you can clearly see the tattoo… although this is image is so heavily airbrushed, she could be one of millions of models, so this is a bad sample for searching anyway.
May be an image of 1 person

I’ve linked to the Facebook image but that might get removed at some point. Probably no point in reporting it because Facebook never takes down the fake profiles – they only seem to go after real people who post stuff that isn’t popular.

The search engine that’s generally the most reliable for finding scammers returns no exact matches this time. The closest ones, but I can’t say for certain because I don’t see any with that tattoo, appear to come from Russian escort sites. So I’m guessing that this is a Russian propaganda bot of some sort. But what for? Seems somewhat pointless, don’t you think?

Here are a some more images… Note that the tattoo is reversed because they are mirror images, but clearly the same model. I get zero results for any of these images, even on Yandex which tends to be very good for finding the prostitutes and other dodgy sources of Facebook scammer profile photos.

…Update. See? They never take down fake profiles…

A simple app I’m using to share the number of days since I quit smoking cigarettes

This is something of a conundrum for me… It’s getting annoying to work out how many days have passed since I quit smoking, but I also want to share it on Facebook every day, as I have been. The conundrum is: I’m lazy, but to avoid having to look at a calendar every day, and this is only going to get worse, I must do some work.

So here it is, a silly little application to work it out and allow me to copy an image to the clipboard before sharing. It looks like this:

SNAGHTML2a830a49

It’s quite crude, and calculates the size of the font to be used by dynamically measuring text programmatically in a loop before doing the actual drawing, onto an image I created by drawing a gradient. So an obvious limitation is that the first line won’t be cantered… because I measure the text using a rectangle, and when I have tried centering the text it fucks it up completely, and I am after all lazy.

I could probably also allow choosing the gradient start and end colours, or maybe allow the user to load an image instead.

But still, I like it. The shadow is achieved simply by drawing twice… i.e. calculate where to draw, and then draw once with x+5, y+5, in black, and then draw again at the proper X and Y coordinate, in white… I draw the shadow first because I’m drawing directly onto the bitmap, so drawing the white first would land up with the black drawing over it.

For anyone interested, the source code is pretty elementary… main form is this:

using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace SmokeFree
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnCopy_Click(object sender, EventArgs e)
        {
            Clipboard.SetImage(pictureBox1.Image);
        }

        private void btnRefresh_Click(object sender, EventArgs e)
        {
            RefreshText();
        }

        private void dtStart_ValueChanged(object sender, EventArgs e)
        {
            Properties.Settings.Default.StartDate = dtStart.Value;
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            Properties.Settings.Default.Save();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            dtStart.Value = Properties.Settings.Default.StartDate;

            var lines = new List<string>();

            foreach (var line in Properties.Settings.Default.Template)
            {
                lines.Add(line);
            }

            richTextBox1.Lines = lines.ToArray();

            RefreshText();
        }

        private void RefreshText()
        {
            var days = DateTime.Today.Subtract(dtStart.Value).Days.ToString();
            pictureBox1.Image = ImageUtilities.ModifyImage(ImageUtilities.OutputGradientImage(), richTextBox1.Text.Replace("[N]", days));
        }

        private void richTextBox1_TextChanged(object sender, EventArgs e)
        {
            var lines = new System.Collections.Specialized.StringCollection();
            lines.AddRange(richTextBox1.Lines);
            Properties.Settings.Default.Template = lines;
        }
    }
}

And the code that plays with the images is this:

using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

namespace SmokeFree
{
    internal class ImageUtilities
    {
        public static Image ModifyImage(Image image, string text)
        {
            bool indexPixelFormat = image.PixelFormat == PixelFormat.Format8bppIndexed;

            // if indexPixelFormat, this must be explicitly disposed.
            Image tempImage = indexPixelFormat ? new Bitmap(image.Width, image.Height) : image;

            try
            {
                using (Graphics graphics = Graphics.FromImage(tempImage))
                {
                    if (indexPixelFormat)
                        graphics.DrawImage(image, 0, 0);

                    graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
                    graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

                    float fontSize = 100;
                    Font font = new Font("Segoe UI Emoji", fontSize, FontStyle.Bold);
                    try
                    {
                        // Measure string to figure out the width needed, starting with font size 100 loop down until it will fit.
                        SizeF stringSize = graphics.MeasureString(text, font);

                        while (stringSize.Width > image.Width || stringSize.Height > image.Height)
                        {
                            font.Dispose();

                            fontSize -= 2;
                            font = new Font("Segoe UI Emoji", fontSize, FontStyle.Bold);
                            stringSize = graphics.MeasureString(text, font);
                        }

                        /* Draw twice, first in transparent black and then
                         * transparent white, so we have a shadow effect. */
                        using (SolidBrush shadowBrush = new SolidBrush(Color.FromArgb(255, 0, 0, 0)),
                            textBrush = new SolidBrush(Color.FromArgb(255, 255, 255, 255)))
                        {
                            float x = (image.Width - stringSize.Width) / 2F;
                            float y = (image.Height - stringSize.Height) / 2F;

                            graphics.DrawString(text, font, shadowBrush, new PointF(x + 5, y + 5));
                            graphics.DrawString(text, font, textBrush, new PointF(x, y));
                        }
                    }
                    finally
                    {
                        font.Dispose();
                    }
                }
            }
            finally
            {
                if (indexPixelFormat)
                    tempImage.Dispose();
            }

            return image;
        }

        public static Bitmap OutputGradientImage()
        {
            Bitmap bitmap = new Bitmap(640, 480);
            using (Graphics graphics = Graphics.FromImage(bitmap))
            using (LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, 640, 480), Color.Blue, Color.Red, LinearGradientMode.Vertical))
            {
                graphics.FillRectangle(brush, new Rectangle(0, 0, 640, 480));
                return bitmap;
            }
        }
    }
}

Learning Windows programming–part 2

Last time I mentioned that I want to teach my son how to write a simple Windows program, an auto-clicker to help him level up in Roblox. Today I’ll define what tools we will use. Actually it’s just one really… The IDE. We don’t need a database for this first program.

Microsoft have a free edition of their full IDE called Visual Studio Community Edition. That’s what I use for personal projects outside of work. It’s nearly identical to their expensive professional edition – at least I can’t see any differences. Since they move their downloads around from time to time, your best bet is to Google Visual Studio 2019 Community Edition Offline download. At the moment, this page tells you how to get it. Older versions had ISO downloads where you could get a DVD image, but these days you run their installation bootstrapper with a /layout parameter and give it a path where it must download the installation files, and optionally select which components you want. I always just get everything. It’s largish, around 40GB, but then again, although that was large in the old days, these are the days when a brand new Xbox game requires an immediate 80GB update if you buy the disk, so I suggest getting it this way. (That is, download the bootstrapper, then run it with /layout so that it installs the full offline installer; then install it from your drive.) If you don’t install all the components and then later discover you want to write a project that isn’t supported with the tools you have, you can always run the installer again and add the missing components (and you have to run it every time there’s an update anyway), but I prefer to have all components installed, and suggest the same for anyone who doesn’t know what components they might need.

Granted this is overkill for the first little program we will write, but at least with it, we then have scope to write all kinds of programs, create web applications, backend services… whatever.

It takes a while to install… maybe 20 minutes or so on a SDD, but on my older computer with a HDD, more than four hours, so I left it to install overnight while I slept. And thus I will end part 2 of this series here.


Although this is a programming series, I’m not posting it on my programming blog because this is really about me trying to figure out how to teach programming to my 12 year old son. It’s an experiment that might fail because I can’t teach for shit… But I may republish it there if it goes well.

Want to learn some simple Windows programming?

I’ve been thinking of teaching my son some programming skills for a while, and it wasn’t until recently that an opportunity presented itself. So I tried to introduce him to the basics this weekend, but it didn’t go so well. I have decided on a change of tactic, and will instead teach him in a way that will be very similar to the way I taught myself.

I learned programming years ago from a book – I think it was Mastering Delphi 3 – and starting in the middle of the book because that chapter dealt with a task that I wanted to try, which happened to be writing a program to store telephone numbers in a database. I do not recommend that book because Delphi is a dead language; that’s just how I started. In my son’s case, he has a different task that he needs to perform, but one that’s also suitable (in my mind) for a beginner. These days I am a c# programmer so that’s the language I’ll use.

So what I’m going to try is laying the foundation for my lessons to him here. They won’t be exactly as I’ll teach him, but it will be a sort of plan of what I intend to teach him. He’s 12 but I’m not writing for a target audience of 12 years old… just the basics of what I will present to him.

First, the reason this came about is that he loves playing this Roblox Anime Fighting Simulator game. He doesn’t really use it to fight, and instead is fascinated with grinding to level up his character.It has an interesting skill levelling system, in the game referred to as “training”, where you level up a particular skill simply by clicking the screen. I end up playing for him by loading the game, and when I go to sleep, selecting the sword skill (if that’s the one he is working on) and then using an auto-clicking application to simulate mouse clicks so that it can level up his skills while he is AFK.

The problem is, the auto-clicker I found for him is quite shitty. It allows you to choose the type of mouse message and so on, and the timer interval, but it just sends mouse input to whatever the active window might be. That’s great if the active window is the Roblox game, but it’s not so great if this is running on my computer at 3AM and some other window, such as a notification, steals focus just as the click is sent. Then the focus changes to that random window, and eventually his game will detect he is idle and log him out. So what I really want is a program that sends mouse clicks to a specific window. And that’s not difficult to do. I’ve never done it but I know it is easy. For me. For him that will be a different story.

I’m not going to start the lesson in this post. I’ll end off by putting down the requirements for his first program. This is how I learned. Bugger knowing what computer programming is about… just define a simple program and know what it must do. Then, learn how to program in order to write that simple program. Learn as you go along – it worked for me.

So the program needs to do the following. (Some of this is optional.)

  1. It’s going to be a standard Windows application, with a single simple dialog.
  2. (Optional). Allow choosing the target window to which we will send mouse messages, and storing this (window handle) somewhere.
  3. Define and understand the structures needed for sending the input involved. (I already know I want to use PostMessage and the good old Windows API.)
  4. Create a simple first version of the application that posts a single mouse click to the target window. This will be achieved via a button click. This might already be too much for a first lesson, but going on with the requirements…
  5. Introduce a timer. Replace the button click with a timer event that, on a regular interval, sends mouse clicks to the target window. Must be able to stop and start the timer with a button click.
  6. Probably only the next lesson, but… Introduce hotkeys. A real world program that I wrote would have configurable hotkeys, but for the beginner, it should be enough to create system wide hotkeys and use them to start and stop the timer.
  7. Clean up the user interface and allow the user to set some options. How much really depends on some combination of my patience and the student’s ability. For example, the timer duration, the type of mouse click, and so on. Another configuration dialog for the hotkey maybe… This adds some other concepts though, such as where to persist the settings.

Now that I’ve written it… that’s a lot. I could write a such a program in a few minutes – every programmer can. But that’s not the point. Teaching is something I’m not good at – I have no patience. Hell, I struggle to explain shit to adults at work. So this is going to be difficult for me.

Next time I’ll define the tools needed to write this first Windows program. I’ll only use free tools.

There’s more to parenting than fucking biology

It’s easy to make a kid; everybody can fuck. (And to be clear I’m only considering cases where this is something you both wanted.) If you’re a guy, just stick in your penis and wriggle it around until you cum. Wham bam, thank you man! Your work here is done! If you’re a gal, let him stick it in there. Admittedly, you get the bulk of the biological work and get to blow up like a balloon and go through literal Hell for nine months, get sore feet, get weird cravings and wild mood swings, then get to stretch a tiny little hole into a not so tiny one and go through some excruciating pain to shit out the little shit, but… Hey, you signed up for this!

After that, the real work of parenting begins. And thanks to the wonders of modern bottled milk, anyone, even a new mother, can ditch the kid and the other parent, and leave them to it.

I wasn’t the best dad at the start. In fact, I was terrible. But I did my best even when I was an addict, and did a lot better the last few years, raising kiddo by myself. I think of life like having to cross an endless series of treacherous roads. At first, kiddo needs to be carried. Then he or she can crawl. Then they walk, with you holding their hand all the way, teaching them about the racing cars that will mow them down, the tanks that will squash them to bits, and the weird old men with their trucks that they pull over to slide open the door and say, “Welcome to the joy mobile where the ice cream is free and the fun never ends! Come on in.” Then one day they will be able to walk by themselves, but always with you to help them as long as you’re still alive.

Seriously, parenting is hard work, much harder than the brief bit of pleasure it took to make the child. That why messages like this make no sense:

No

“No, I’m still the mother of your child”. Biologically, yes. But was she ever his parent? I don’t fucking think so.


I should probably delete this horrible post.

 

 

 

My other blog is now private, until further notice

My programming blog is now private, and will remain as such until I can review its content.

This is due to a new confidentiality agreement sent to everyone by my employer. The terms used to describe intellectual property are ambiguous, and while its concept of proprietary information does exclude “generic knowledge that I would have learned in the course of similar employment elsewhere”, the clauses about source code are ambiguous enough to warrant a concern.

While I feel that the source code and programming examples I shared were generic, and were written at home to describe solutions for programming problems I solved at work, coded into examples that referred to no proprietary information from my employer, I can’t be certain that the content doesn’t contravene their definition of intellectual property.

My apologies to anyone who found this looking for the other blog, and to my followers of the other blog.

It’s too easy to judge addicts, but we shouldn’t.

Every so often I’m reminded how we judge addicts. We all do it – look down on them because it makes us feel a little better. Even I did it last week; shared a meme with an image that was trending on Facebook, of a girl with a trolley more or less attached to her, and some condescending text about meth. Now I’m sorry I shared it.

People used to judge me too, and write me off, but last night I was reminded of some stuff I achieved on meth. I was looking around on my hard drive because it’s getting full and I need to delete some old files, when I found a backup directory, a backup of my old drive from a few years ago, because I gave the drive to my ex…

It contained a lot of evidence, not of my drug use, but of the results of my tweaking on the computer. Besides the movies and downloads, there was also some source code I’d forgotten about.

I’ll try to make this as simple as possible, but that isn’t easy. I’d written my own video player, in c# using DirectShow. It’s not great, but it works, and it works pretty well. But it only plays video files directly. At some point, I was interested in playing DVDs too. So I found source code that I could use, a tutorial with some sample code on playing DVDs from c#. The only problem was, my video player code was “tightly coupled” to the form that uses it. So the form, which should just be the user interface (with the buttons to play and so on) included all the code for playing videos. Not only that, but it does some funky stuff with background threads, for example so that if you click “next”, it already knows all the files in the directory. Plus it has features like frame stepping and player speed that aren’t necessarily implemented in the DVD player code.

So, to change my player so that it could play files or DVDs, I had two options:

  1. Use inheritance. This would involve defining a base “player” class, and having two derived classes. One would be the file player, with all the existing code moved to it, and another would be a DVD player class.
  2. Define a “player” interface. This interface would contain the definitions for all the stuff the player did, but only the definitions. Then I’d have two implementations of this interface, one with my existing code, and another for DVDs. (The DVD player would then not implement the methods or properties that were specific to the file player, or at least fail gracefully at those things.)

Apparently I decided on option two. “Apparently” is quoted because I was so high, I don’t remember any of that. But it’s there – I found that I went as far as defining the interface. Then I stopped there, because it would be a couple more days work to refactor my code, and then implement the DVD playing code, as well as having some way (an “abstract factory” probably) of deciding an runtime which implementation to use based on what was being played. The bulk of the work would be the refactoring… There’s a lot more that I’m not mentioning, such as the peripheral details around the two kinds of players. The file player has a concept of play lists, which involves relative paths to the locations of files on disk, and it can also persist the starting position (and ending position which allows for playback loops because I was tweaking) within files, while a DVD player would need to be able to navigate a menu system, and switch between different tracks. The code for the file player to “know” the difference between playing files in a list verses playing whatever is in the directory, is messy. Not to mention repeat modes… on reaching the end of a file, it must decide, based on the repeat mode, whether to go to the next file, or repeat the file, or if set to repeat the whole list/directory, decide what to do then based on the index within the list/directory (and lastly if super-duper tweaker pervert porno repeat cumshot loop is engaged, repeat that part of the file when it gets to the end of the section, or check if there is a loop to repeat when loading a new file. Sigh… Tweaking leads to strange complications). That shit would be complicated to refactor, and even on meth I was too lazy to do all that.

The point is, I did some hard-core programming shit on meth. This is unfinished code, but I have had the dubious “pleasure” of working with some less talented programmers over the years, programmers who were incapable of doing what I could do when I was on meth.

Don’t judge people just because they’re on drugs. Being an addict doesn’t make anyone stupid, although it certainly does lead to them doing some stupid things. (For example, writing video players when you’re tweaking on porn – then not actually watching the porn but rather going off on a tangent writing a fairly feature-rich video player.) While you’re laughing at people and putting them down, there are some good people out there who just made some bad choices. Some of them are more clever or gifted than you can imagine, and a little empathy goes a long way.

Another way addicts are often judged, and sorry if you’ve read what I’ve written about this before, is the so called “faces of meth”, photos shared online with the pretence of it being about deterring others from using meth. It’s never about that. It’s about laughing at people less fortunate than yourself. It’s also about missing the point.

I won’t share such images myself, but I will state an example. I remember seeing one of those images of a girl who supposedly used meth for ten years. She was a pretty girl, probably about seventeen in the first image, then more or less a year older in every subsequent image. But here’s the problem: The first image, where she looked pretty, was a police mug shot. She was arrested for drug possession and prostitution, and was probably already living on the street. Do you see where I’m going with this? In the before image, she was probably already using meth for at least five years, maybe longer. And as for the rest, they were pictures of a woman living on the street, most likely using multiple drugs, including but not limited to meth. Once you get to the point of living on the street, meth is soon out of range of what you can afford, unless of course you happen to be a career criminal. And of course, career criminals and long time prostitutes have more factors affecting their appearance than the number of years they use meth.

Edit: This needs to be expanded on… Career criminals and the people associated with them, who are committing crimes for their drugs, don’t have normal lives. Contrast this with normal people who happen to be addicts… who still go home to their houses where they shower, brush their teeth, get dressed and go to work every day. (And then maybe party all night and every weekend, sometimes disappearing for a day or two each month after they get paid.) They’re nothing like those pitiful looking photos you see in mug shots online.

So while you look at those photos and laugh at the subjects in them, you miss that most addicts look nothing like those people. Most addicts are working normal jobs, and you would never guess they’re using drugs. People might work while using for up to twenty years, before they reach that point where they can’t work any more. And it’s all too easy to judge them while you have a drink every day, or do cocaine occasionally. You might find yourself judging them even after you’ve already become one of them. And when that happens, you might realize as I did, that those “photos of meth” are not a deterrent at all. They’re one of many ways to misunderstand how widespread and dangerous addiction really is, allowing you to see addicts in terms of stereotypes rather than reality.

More good code I wrote when I was high

Again I was surprised to find some good code that I wrote way back when I was high. I might post this one to my programming blog tomorrow as well, slightly repurposed without the mention of drugs, and a title “How to load a cursor from embedded resources in C#”.

Anyway, that’s what it does. Via some code that I found and then modified, my image viewer, when viewing an image that’s larger than the viewable area, allows you to use the mouse to drag around and pan to different parts of the image. When doing this, the program changes the mouse cursor, to one of two cursor images that I designed myself and drew pixel-by-pixel (I was indeed tweaking my ass off), one for a hand that’s up and one for a hand that’s down.

Here’s what it looks like when the hand down cursor is displayed. (Main mouse button is pressed so you can pan the image… in the application – not here because this is just a fucking screenshot.)

Viewer

And here’s the code (that I took ages to figure out) that loads the cursor, which is saved as a file resource, from the applications resources:

using System;
using System.Runtime.InteropServices;
using System.Security;
using System.Windows.Forms;

namespace Romy.Core
{
    public static class CursorResourceLoader
    {
        #region Methods

        public static Cursor LoadEmbeddedCursor(byte[] cursorResource, int imageIndex = 0)
        {
            var resourceHandle = GCHandle.Alloc(cursorResource, GCHandleType.Pinned);
            var iconImage = IntPtr.Zero;
            var cursorHandle = IntPtr.Zero;

            try
            {
                var header = (IconHeader)Marshal.PtrToStructure(resourceHandle.AddrOfPinnedObject(), typeof(IconHeader));

                if (imageIndex >= header.count)
                    throw new ArgumentOutOfRangeException("imageIndex");

                var iconInfoPtr = resourceHandle.AddrOfPinnedObject() + Marshal.SizeOf(typeof(IconHeader)) + imageIndex * Marshal.SizeOf(typeof(IconInfo));
                var info = (IconInfo)Marshal.PtrToStructure(iconInfoPtr, typeof(IconInfo));

                iconImage = Marshal.AllocHGlobal(info.size + 4);
                Marshal.WriteInt16(iconImage + 0, info.hotspot_x);
                Marshal.WriteInt16(iconImage + 2, info.hotspot_y);
                Marshal.Copy(cursorResource, info.offset, iconImage + 4, info.size);

                cursorHandle = NativeMethods.CreateIconFromResource(iconImage, info.size + 4, false, 0x30000);
                return new Cursor(cursorHandle);
            }
            finally
            {
                if (cursorHandle != IntPtr.Zero)
                    NativeMethods.DestroyIcon(cursorHandle);

                if (iconImage != IntPtr.Zero)
                    Marshal.FreeHGlobal(iconImage);

                if (resourceHandle.IsAllocated)
                    resourceHandle.Free();
            }
        }

        #endregion Methods

        #region Native Methods

        [SuppressUnmanagedCodeSecurity]
        static class NativeMethods
        {
            [DllImportAttribute("user32.dll", CharSet = CharSet.Unicode)]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool DestroyIcon(IntPtr hIcon);

            [DllImport("user32.dll", SetLastError = true)]
            public static extern IntPtr CreateIconFromResource(IntPtr pbIconBits, int dwResSize, bool fIcon, int dwVer);
        }

        #endregion Native Methods

        #region Native Structures

        [StructLayout(LayoutKind.Explicit, Pack = 1)]
        struct IconHeader
        {
            [FieldOffset(0)]
            public short reserved;

            [FieldOffset(2)]
            public short type;

            [FieldOffset(4)]
            public short count;
        }

        /// <summary>Union structure for icons and cursors.</summary>
        /// <remarks>For icons, field offset 4 is used for planes and field offset 6 for 
        /// bits-per-pixel, while for cursors field offset 4 is used for the x coordinate 
        /// of the hotspot, and field offset 6 is used for the y coordinate.</remarks>
        [StructLayout(LayoutKind.Explicit, Pack = 1)]
        struct IconInfo
        {
            [FieldOffset(0)]
            public byte width;

            [FieldOffset(1)]
            public byte height;

            [FieldOffset(2)]
            public byte colors;

            [FieldOffset(3)]
            public byte reserved;

            [FieldOffset(4)]
            public short planes;

            [FieldOffset(6)]
            public short bpp;

            [FieldOffset(4)]
            public short hotspot_x;

            [FieldOffset(6)]
            public short hotspot_y;

            [FieldOffset(8)]
            public int size;

            [FieldOffset(12)]
            public int offset;
        }

        #endregion Native Structures
    }
}

The code that uses it, in another class, is just this:

        /// <summary>Loads the two hand cursors from project resources.</summary>
        private static void InitializePanBoxCursors()
        {
            if (handUpCursor == null && handDownCursor == null)
            {
                handUpCursor = CursorResourceLoader.LoadEmbeddedCursor(Properties.Resources.Hand_up);
                handDownCursor = CursorResourceLoader.LoadEmbeddedCursor(Properties.Resources.Hand_down);
            }
        }

It still amazes me that I wrote some more than decent code back when I was tweaking my stupid head off.

This will be the last late night post for a while. My son gets back tomorrow, and since we share a room, I normally go to bed the same time he does. Actually I’m tired and am going to sleep right after posting this. Good night…

I’m still baffled by source code I wrote when I was on meth

Apologies to most people reading this who are not programmers. This post won’t make much sense. But I try to avoid drug references on my programming blog, so this belongs here… And also an apology to anyone who saw this post published by mistake the first time, before I added the image.

I still use this monstrosity of a program I wrote a few years ago. I shouldn’t, because it tries to do too many different things in that it was my scratchpad for all new code I learned for a few years, but it works well for some of them, so I use it even though I know it has its quirks. It’s more or less a file browser, image viewer, video and audio player (via Direct Show which is now obsolete), and can do some minor image editing. But mostly it’s an image viewer. It builds and maintains its own cache of thumbnails, which looks kind of like the large icons view in Windows Explorer. Then double-clicking those thumbnails opens the program’s built in image viewer.

Here’s what it looks like:

RomyView

Anyway, one of its quirks is that there’s a bug somewhere in the custom TaskScheduler (I think) and that can have weird effects like hanging the whole application after deleting a directory. (Sometimes.) So while looking at all the code that references my own TaskSchedulers, I came across this code, written while I was super duper high…

/// <summary>Load a Shell thumbnail image and add it to the cache.</summary>
public static async Task<ThumbnailCacheItem> LoadAndCacheThumbnailAsync(string path, CancellationToken token, bool requiresCurrentDirectory = false)
{
    var item = ThumbnailCacheItem.Invalid;
    var tcs = new TaskCompletionSource<ThumbnailCacheItem>();
    var isSmallImage = false;
    var failed = false;

    try
    {
        using (CancellationTokenSource cts = new CancellationTokenSource(),
            linked = CancellationTokenSource.CreateLinkedTokenSource(token, cts.Token))
        {
            Action checkCancelled = () =>
            {
                if (requiresCurrentDirectory && !Path.GetDirectoryName(path).EqualsIgnoreCultureAndCase(IO.CurrentDirectory))
                    linked.Cancel();

                linked.Token.ThrowIfCancellationRequested();
            };

            await Tasks.Run(() =>
            {
                checkCancelled();
                var fileSystemInfo = IO.Exists(path);

                if (!fileSystemInfo.Item1)
                {
                    /* Neither a file nor a directory exists. This is possible if it was deleted after this 
                        * method was called but before we got here, and just means we have nothing to do here. */
                    linked.Cancel();
                    linked.Token.ThrowIfCancellationRequested();
                }

                var isDirectory = fileSystemInfo.Item2;
                var isFile = fileSystemInfo.Item3;

                var fileSystemType = isDirectory ? FileSystemType.Directory : FileSystemType.File;

                var isMedia = isFile && IO.IsMediaFile(path);
                var isImage = isFile && IO.IsImageFile(path);
                var isPng = isImage && IO.IsPng(path);
                var isZip = isFile && IO.IsZip(path);
                var isPsd = isFile && IO.IsPsdFile(path);
                var isTextFile = IO.IsTextFile(path);

                Bitmap cacheBitmap = null;
                Bitmap fullsizeImage = null;
                try
                {
                    // For simplicity, we define a small bitmap as one with file size less than 1MB.
                    var isBitmapGlyph = IO.IsBmp(path) && new FileInfo(path).Length < 1024L * 1024L;

                    /* Don't use the shell for icon images. It will
                        * display them with shadows and looks like shit. */
                    if (isFile && IO.IsIcon(path))
                    {
                        // Load the largest icon.
                        using (var iconImage = (new IconFileReader { Filename = path }.FirstIcon).ToBitmap())
                        {
                            if (iconImage == null)
                                throw new FileReadException(string.Format("Error reading '{0}'", path));

                            fullsizeImage = iconImage.Clone() as Bitmap;
                            isSmallImage = true;
                        }
                    }
                    else if (isPng || isBitmapGlyph || isPsd)
                    {
                        /* Also don't use the shell for png images, or gifs, for similar reasons as for icons. */
                        fullsizeImage = ImageFile.OpenBitmap(path);

                        if (isBitmapGlyph)
                            isSmallImage = true;

                        if (fullsizeImage == null)
                            throw new FileReadException(string.Format("Error reading '{0}'", path));
                    }
                    checkCancelled();

                    isSmallImage |= IO.IsGif(path);

                    if (fullsizeImage != null && (isSmallImage || isPng || isPsd))
                    {
                        /* If this is a small image, or if it is likely that conversion to jpeg will
                            * produce a thumbnail of inferior quality, we store the actual image in the
                            * cache, instead of a thumbnail.
                            *
                            * Also, the method to get the thumbnail from the shell below will lose the
                            * transparency for small png images, whereas this way, we will display them
                            * with transparency, even in the thumbnails. */
                        cacheBitmap = new Bitmap(fullsizeImage);

                        if (cacheBitmap.Width > 256 || cacheBitmap.Height > 256)
                            cacheBitmap = cacheBitmap.Resize(256, 256) as Bitmap;
                    }
                    else
                    {
                        cacheBitmap = !isZip ? ShellItemImageFactory.GetImage(path) : Icon.ExtractAssociatedIcon(path).ToBitmap();

                        if (cacheBitmap == null)
                            throw new FileReadException(string.Format("Error reading '{0}'", path));
                    }

                    checkCancelled();

                    if (cacheBitmap != null)
                        item = ThumbnailCache.AddNewCacheItem(path, cacheBitmap, fileSystemType, isSmallImage);
                }
                catch (Exception ex)
                {
                    /* An exception here is not necesarily an error. e.g. It will throw 
                        * if you deliberately delete images as they're being cached. */
                    ex.Log();
                    failed = tcs.TrySetException(ex);
                }
                finally
                {
                    if (fullsizeImage != null)
                        fullsizeImage.Dispose();
                }
                return Task.FromResult(item);
            }, token, TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness).ConfigureAwait(false);

            /* The TaskCreationOptions are critically important here.
                * We do not want to be running on the main thread. */

            if (!failed)
                tcs.TrySetResult(item);
        }
    }
    catch (OperationCanceledException) { tcs.TrySetCanceled(); }

    // Prevent the UI from becoming unresponsive when adding many thumbnails.
    await tcs.Task.YieldTo(uiScheduler);

    return await tcs.Task;
}

That’s the code that adds a new thumbnail object to the thumbnail cache, which is a special kind of object cache where the objects are reused once the configurable size is exceeded, and is also persisted to disk, in my own bastardized binary format.

This code showed up in my search results because I was looking for all references to Tasks.Run, which is not standard code, but that calls my own TaskScheduler instead of the built in one.

And yet, this is good code. It’s not verbose, which is surprising. The code is easy to read and it calls out to loads of extension methods and other complex code. So depending on the file type that it finds, it might decide to cache the actual image directly for small files, use my custom icon reader that reads all icons from an ICO file directly, use my custom image reader that can read all kinds of image files, including PSD (Photoshop files), or invoke the Windows shell interfaces, in code that I also managed to figure out myself (because that shit is not implemented in the dot net Framework), which then uses different interfaces depending on the version of Windows. All in all, this is really good code… better than what I write at work nowadays.

I’m baffled.


Also, I found that the bug has nothing to do with my custom TaskScheduler, because it still happens after all references to it are removed. I’ve given up looking for the bug for now.

Found some source code I wrote while high that I don’t understand

I have a long and difficult post in mind… It’s been in the back of my head for over a week now and still not getting anywhere. I haven’t had time to write lately, but I did think this code I just found, which baffles me, might be worth sharing.

I’m doing something at work where I need to decrement a counter from multiple threads, and I knew I did something like this before, so I decided to search through my project of old code… Believe it or not, I wrote a lot of good code around 2011 to 2012, while I was very very high. I also wrote plenty bad code too, some of it bad because, well, it’s just fucking bad, some of it bad because it is so complicated that I can no longer understand it, although it works and does what it was designed to do, and some of it that leaves me wondering what the fuck I was thinking.

This is one of the latter examples… It wraps some Windows API code to suspend or resume the drawing of a window (I don’t remember why I would do this), and was written in such a way that this could be called from multiple threads… Enjoy.

Of interest here is the comment in the remarks section of the comment block describing the class:

Calls may be nested, but should not be made from any other than the GUI thread. (This code tries to work around such an error,  but is not guaranteed to succeed.)

Also, the way it works around the issue is, um… creative.
 

using System;
using System.Runtime.InteropServices;
using System.Security;
using System.Threading;
using System.Windows.Forms;

namespace Romy.Controls
{
    /// <summary>Allows suspending and resuming redrawing a Windows Forms window via the <b>WM_SETREDRAW</b> 
    /// Windows message.</summary>
    /// <remarks>Usage: The window for which drawing will be suspended and resumed needs to instantiate this type, 
    /// passing a reference to itself to the constructor, then call either of the public methods. For each call to 
    /// <b>SuspendDrawing</b>, a corresponding <b>ResumeDrawing</b> call must be made. Calls may be nested, but
    /// should not be made from any other than the GUI thread. (This code tries to work around such an error, but 
    /// is not guaranteed to succeed.)</remarks>
    public class DrawingHelper
    {
        #region Fields

        private int suspendCounter;

        private const int WM_SETREDRAW = 11;

        private IWin32Window owner;

        private SynchronizationContext synchronizationContext = SynchronizationContext.Current;

        #endregion Fields

        #region Constructors

        public DrawingHelper(IWin32Window owner)
        {
            this.owner = owner;
        }

        #endregion Constructors

        #region Methods

        /// <summary>This overload allows you to specify whether the optimal flags for a container 
        /// or child control should be used. To specify custom flags, use the overload that accepts 
        /// a <see cref="Romy.Controls.RedrawWindowFlags"/> parameter.</summary>
        /// <param name="isContainer">When <b>true</b>, the optimal flags for redrawing a container 
        /// control are used; otherwise the optimal flags for a child control are used.</param>
        public void ResumeDrawing(bool isContainer = false)
        {
            ResumeDrawing(isContainer ? RedrawWindowFlags.Erase | RedrawWindowFlags.Frame | RedrawWindowFlags.Invalidate | RedrawWindowFlags.AllChildren :
                RedrawWindowFlags.NoErase | RedrawWindowFlags.Invalidate | RedrawWindowFlags.InternalPaint);
        }

        [CLSCompliant(false)]
        public void ResumeDrawing(RedrawWindowFlags flags)
        {
            Interlocked.Decrement(ref suspendCounter);

            if (suspendCounter == 0)
            {
                Action resume = new Action(() =>
                {
                    NativeMethods.SendMessage(owner.Handle, WM_SETREDRAW, new IntPtr(1), IntPtr.Zero);
                    NativeMethods.RedrawWindow(owner.Handle, IntPtr.Zero, IntPtr.Zero, flags);
                });
                try { resume(); }
                catch (InvalidOperationException)
                {
                    synchronizationContext.Post(s => ((Action)s)(), resume);
                }
            }
        }

        public void SuspendDrawing()
        {
            try
            {
                if (suspendCounter == 0)
                {
                    Action suspend = new Action(() => NativeMethods.SendMessage(owner.Handle, WM_SETREDRAW, IntPtr.Zero, IntPtr.Zero));
                    try { suspend(); }

                    catch (InvalidOperationException)
                    {
                        synchronizationContext.Post(s => ((Action)s)(), suspend);
                    }
                }
            }
            finally { Interlocked.Increment(ref suspendCounter); }
        }

        #endregion Methods

        #region NativeMethods

        [SuppressUnmanagedCodeSecurity]
        internal static class NativeMethods
        {
            [DllImport("user32.dll")]
            public static extern bool RedrawWindow(IntPtr hWnd, IntPtr lprcUpdate, IntPtr hrgnUpdate, RedrawWindowFlags flags);

            [DllImport("user32.dll")]
            public static extern IntPtr SendMessage(IntPtr hWnd, Int32 wMsg, IntPtr wParam, IntPtr lParam);
        }

        #endregion NativeMethods
    }

    #region RedrawWindowFlags

    [Flags(), CLSCompliant(false)]
    public enum RedrawWindowFlags : uint
    {
        ///<summary>Invalidates lprcUpdate or hrgnUpdate (only one may be non-NULL). 
        ///If both are NULL, the entire window is invalidated.</summary>
        Invalidate = 0x1,

        ///<summary>Causes a WM_PAINT message to be posted to the window regardless of 
        ///whether any portion of the window is invalid.</summary>
        InternalPaint = 0x2,

        ///<summary>Causes the window to receive a WM_ERASEBKGND message when the window 
        ///is repainted. The <b>Invalidate</b> flag must also be specified; otherwise, 
        ///<b>Erase</b> has no effect.</summary>
        Erase = 0x4,

        ///<summary>Validates lprcUpdate or hrgnUpdate (only one may be non-NULL). If both 
        ///are NULL, the entire window is validated. This flag does not affect internal 
        ///WM_PAINT messages.</summary>
        Validate = 0x8,

        ///<summary>Suppresses any pending internal WM_PAINT messages. This flag does not 
        ///affect WM_PAINT messages resulting from a non-NULL update area.</summary>
        NoInternalPaint = 0x10,

        ///<summary>Suppresses any pending WM_ERASEBKGND messages.</summary>
        NoErase = 0x20,

        ///<summary>Excludes child windows, if any, from the repainting operation.</summary>
        NoChildren = 0x40,

        ///<summary>Includes child windows, if any, in the repainting operation.</summary>
        AllChildren = 0x80,

        ///<summary>Causes the affected windows (as specified by the <b>AllChildren</b> and <b>NoChildren</b> flags) to 
        ///receive WM_NCPAINT, WM_ERASEBKGND, and WM_PAINT messages, if necessary, before the function returns.</summary>
        UpdateNow = 0x100,

        ///<summary>Causes the affected windows (as specified by the <b>AllChildren</b> and <b>NoChildren</b> flags) 
        ///to receive WM_NCPAINT and WM_ERASEBKGND messages, if necessary, before the function returns. 
        ///WM_PAINT messages are received at the ordinary time.</summary>
        EraseNow = 0x200,

        ///<summary>Causes any part of the nonclient area of the window that intersects the update region 
        ///to receive a WM_NCPAINT message. The <b>Invalidate</b> flag must also be specified; otherwise, 
        ///<b>Frame</b> has no effect. The WM_NCPAINT message is typically not sent during the execution of 
        ///RedrawWindow unless either <b>UpdateNow</b> or <b>EraseNow</b> is specified.</summary>
        Frame = 0x400,

        ///<summary>Suppresses any pending WM_NCPAINT messages. This flag must be used with <b>Validate</b> and 
        ///is typically used with <b>NoChildren</b>. <b>NoFrame</b> should be used with care, as it could cause parts 
        ///of a window to be painted improperly.</summary>
        NoFrame = 0x800
    }

    #endregion RedrawWindowFlags
}