Jan 242018
 

The InternetIt hasn’t happened for a while, but here’s another one: Due to my internet service provider having to do maintenance in the local automatic exchange hub, XIN will go offline for a tiny bit. The time window during which all *.xin.at services will briefly become unreachable will range from 01:00 am to 06:00 am UTC+1 on the 31st of January 2018. According to UPC (my ISP), the total downtime should not exceed 20 minutes per internet access, and is being used to do “infrastucture maintenance” and “network optimization”, whatever that’s supposed to mean.

I guess this shouldn’t really hurt XIN.at’s 99% availability too much though (yeah, I’m still aiming for that with that 23 year old tank of a server).

Jan 162018
 

The Red Solstice logo1.) Introduction

Yes, it’s another one of “those” posts. Reason for this is, that Humble Bundle is currently [giving away] the crowdfunded title “The Red Solstice” for free, so I picked up a copy to see whether I could get it to work on Windows XP x64 (and also 32-bit XP). Why not, right? Ah, you need Steam for this by the way.

This game is the first one I’ve seen on the Desktop which is actually using OpenGL ES instead of OpenGL or just Direct3D. Typically, that API is more widespread on mobile devices running Android or something, as it’s slimmer and brings a reduced feature set of the “real” OpenGL to the table. The bundled version is OpenGL ES 2.0, and instead of some modern GPGPU language like HLSL it uses nVidias’ old Cg library, which is luckily compatible with XP. The game developer [Ironward] seems to claim that this game, which is based on something called the “TRSEngine” needs Windows 7 or newer to run however.

2.) Required tools

To be able to reproduce the hack described in this post you will need the following tools:

3.) Fixing the platform target

The game has been compiled for a NT 6.0 or Windows Vista platform target, so launching it as-is will result in the dreaded “not a Win32 application” error:

The Red Solstice is "not a valid Win32 application" on XP

Hey, it’s not a Win32 application! Pfh, as if…

The fact that the program was built with an NT 6.0 platform target doesn’t necessarily mean that it actually needs any modern functions of Vista/7/8/10, so the first step is usually to fix the binary headers and change that platform level to something lower, usually 5.1 (XP) for 32-bit code or 5.2 (XP x64 / Server 2003) for 64-bit code. The Red Solstice is a 32-bit game, so it’s going to be 5.1. Sometimes, this can be enough.

As an example, launch CFF Explorer and open the Game.exe from the games’ installation folder, then click on Nt Headers -> Optional Header. I’ve marked the important parts in red for you:

The Red Solstice stock Game.exe

The Red Solstice stock Game.exe (click to enlarge)

To fix this, change the values from 0006 and 0000 to 0005 and 0001, this corresponds to changing the required platform from NT 6.0 to 5.1.

Game.exe with modified binary header

Game.exe with modified binary header (click to enlarge)

After the change, save and overwrite the existing file, but create a backup first, if you wish to be able to revert from the change quickly.

Fixing that one file won’t be enough though. In total, you’ll need to apply the hack seen above to the following files:

  • Game.exe
  • icudt51.dll (Unicode library)
  • icuin51.dll (Unicode library)
  • icuuc51.dll (Unicode library)
  • libEGL.dll (Platform-specific glue layer for OpenGL ES on Windows)
  • libGLESv2.dll (OpenGL ES 2.0)
  • libogg.dll (OGG vorbis audio decoder)
  • libtheoraplayer.dll (Theora audio decoder)
  • OpenAL32.dll (OpenAL audio API)
  • Qt5Core.dll (Qt5 2D GUI library)
  • Qt5Gui.dll (Qt5 2D GUI library)
  • Qt5Widgets.dll (Qt5 2D GUI library)
  • platforms\qwindows.dll (Platform-specific glue layer for Qt5 on Windows)

It’ll take about 1-2 minutes to fix all of them I guess. However, if you attempt to run the game after that, it’ll still fall on its face with a different error:

The XP kernel API doesn't provide GetTickCount64()

Ah, GetTickCount64() is actually an [old acquaintance] of mine by now…

Inspecting the Game.exe with Steve Millers’ Dependency Walker shows, that the problem is actually limited to GetTickCount64(), so it’s the one and only missing kernel API function call we’ll have to deal with:

Tracking the dependencies of Game.exe brings up a missing GetTickCount64() call in kernel32.dll

Tracking the dependencies of Game.exe brings up a missing GetTickCount64() call to kernel32.dll, but no other problems. (Click to enlarge)

Alright, let’s get to it!

4.) Fixing the GetTickCount64() call

This is a bit trickier, as we need to present a GetTickCount64() function to the game, that will do something useful. For this we’ll use Oleg Ovcharenkos’ Stellaris hack, which allows us to redirect that missing call to the legacy GetTickCount() that Windows XP does have.

Unpack the software into some directory of your choice and copy the Game.exe of “The Red Solstice” into that directory as well. Olegs’ hack isn’t prepared for this game yet, so copy one of the existing scripts such as xp_Stellaris_1.6.cmd to a new script file, e.g. xp_TheRedSolstice_1.6.cmd. Open the file in your favorite text editor, and make sure it contains exactly and only the following lines:

@ECHO OFF
rundll32 zernel32.dll,PatchFile Game.exe

Save the file, and run it by double-clicking on it or by launching it directly from a command line terminal. It’ll patch the game so it calls the stub DLL zernel32.dll and some other z* libraries, which fixes some missing calls and redirect the rest to the platforms kernel API as-is. It’ll also create a backup copy of Game.exe for you. Now you have to copy the following files from the folder containing Olegs’ hack back to the actual game folder:

  • Game.exe
  • zernel32.dll
  • zs2_32.dll

That’s it!

5.) Finally: Running the game on XP

With the platform target hack done with CFF Explorer and the GetTickCount64() => GetTickCount() redirection done by Olegs’ Stellaris hack we can finally launch the game:

The Red Solstice fired up on Windows XP x64

The Red Solstice fired up on Windows XP x64 (click to enlarge)

I have to say that I haven’t tested this extensively so far, but a few brief gameplay tests have been conducted:

Gameplay test

Gameplay test (click to enlarge)

There you go, another modern game hacked to run on ancient Windows XP & XP x64! Beer Smilie

Jan 112018
 

AMI logo1.) Introduction

This is something I’ve been wanting do do years ago, but the recent outcry regarding the Meltdown and Spectre hardware security holes have reminded me of this. Since fixing at least parts of the exploits also requires CPU microcode support (from here on: “µcode”), and not all operating systems and mainboards/machines might get them, this might be useful for the current situation as well. It can also be helpful if you wish to patch Intel Xeon support into a slightly older platform, where the manufacturer hasn’t done so already. This article does however not apply to modern UEFI-based systems.

So, instead of getting the required CPU µcodes from a donor BIOS, why not obtain the latest version from Intels’ [µcode package for Linux]? Oh, and it’s not really Linux-specific anyway.

I will show you how to extract and prepare the Intel µcodes and how to patch them so you can embed them into pretty much any somewhat modern AMI BIOS. AMI BIOSes are pretty widespread, but tools similar to the AMI-specific ones shown here might of course also exist for other BIOS brands.

The steps of this guide will be shown for both Linux/UNIX as well as Microsoft Windows.

All the tools used in this post can be found at the end of the article. You can also get all the currently released µcodes in one package there, so you don’t need to download all the archives from Intel (not all archives contain all µcodes…).

2.) Fetch and extract/convert Intels’ µcode package

You can get the µcodes directly from Intel, again, here’s the [link]. To unpack the .tgz archive on MS Windows, you may want to use [7-zip] (It’s a 2-step process with 7-zip, from .tgz to .tar and from .tar to the final files). For older releases, all you’ll get by doing this is a microcode.dat file, sometimes the file name will also contain a date. That’s all the µcodes assembled in one file in a text format. This is useless for patching the data into BIOS images, so we’ll need to extract the individual CPU µcodes and convert them into the proper binary format.

Newer releases might contain pre-built binary versions as well, but we’ll just continue to work with microcode.dat.

2a.) On Linux or UNIX

We’ll use iucode_tool for that, as at least most Linux systems should have a package ready for that program. If you can by no means get or compile iucode_tool, you might compile microdecode from source on Linux or UNIX instead, see 2b.) and 8.)! I have tested this on CentOS 6.9 Linux, and microdecode compiles just fine. But let’s continue with iucode_tool:

To extract the µcodes, switch to the directory containing microcode.dat (after unpacking the .tgz file with tar -xzf) and run the following commands:

$ mkdir ./µcodes/
$ iucode_tool -t d -L --write-named-to="./µcodes/" "microcode.dat"; done

With that, you’ll get a lot of *.fw binary files in ./µcodes/. Those are in the regular Intel µcode format and come in different sizes depending on the CPU. The file names look similar to e.g. this: s000206C2_m00000003_r00000013.fw. The first “s” part contains the CPUID, the second “m” part shows the platform ID, and the “r” part denotes the µcode revision, all of it in hexadecimal notation.

2b.) On Windows

On Windows, we’ll use the microdecode command line tool. It’s a bit easier to use than iucode_tool, as it’s only purpose is really just µcode extraction and nothing else. Switch to the directory containing the unpacked microcode.dat, make sure microdecode.exe is in your search path (or in the same directory), and run the following command:

microdecode.exe microcodes.dat

This will result in a lot of *.bin files that are identical to the .fw files the *nix tool extracts. The file names will be similar to this: cpu000206c2_plat00000003_ver00000013_date20100907.bin. The first “cpu” part contains the CPUID like above, the second “plat” part contains the platform ID, and the “ver” part shows the µcode revision. Additionally, we also get the release date in the final “date” part.

3.) Identifying your CPU

You’ll likely know your CPU model if you’re reading this. But what you’ll need to know above that is your exact CPUID, stepping and the revision of CPU µcode you’re currently running. You can look up some of the information on cpu-worlds’ [CPUID database], but ultimately, you’ll need to fetch it from your local machine anyway.

Important background information: The CPUID is a 32-bit value structured as follows:

CPUID structure

The binary structure of Intels’ 32-bit CPUID, 4 bits equal one hexadecimal character

The binary matrix is usually expressed as 4-bit hexadecimal characters. e.g. the binary CPUID 0000:0000:0000:0010:0000:0110:1100:0010bin would result in 000206C2hex.

3a.) On Linux/UNIX

On Linux, the required information can be grabbed from procfs. Like this, for example:

$ cat /proc/cpuinfo | grep -e "model" -e "stepping" -e "microcode" -e "cpu family" | sort | uniq

cpu family	: 6
microcode	: 15
model		: 44
model name	: Intel(R) Core(TM) i7 CPU       X 980  @ 3.33GHz
stepping	: 2

You have to be careful interpreting this information however, as it’s mostly decoded in decimal form. Modern kernels might show some of the data in hexadecimal, so be careful here!

But first, convert the decimals from /proc/cpuinfo to hexadecimal, where necessary, in this case we’ll do it for the µcode revision and the model number:

$ printf '%X\n' 15
F
$ printf'%X\n' 44
2C

So, the model number is 2Chex. Here, the right part or Chex is the actual model number (CPUID bits 4..7) and 2hex is the extended family number (CPUID bits 16..19).

The µcode version here would be Fhex. Note that µcode versions can be wider than just 1 hexadecimal character as well. The stepping 2 is a number lower than 15, so we don’t need to convert it to hexadecimal.

To assemble our final string which is 8 hexadecimal characters wide, we walk through the bit mask on the image shown above step by step! All “reserved” parts are just filled with blanks:

  1. 0 (Bits 31..28, reserved)
  2. 0 (Bits 27..24, extended CPU family, zero for family 6)
  3. 0 (Bits 23..20, extended CPU family, zero for family 6)
  4. 2 (Bits 19..16, extended CPU model number)
  5. 0 (Bits 15..12, two reserved and two platform type bits, typically zero)
  6. 6 (Bits 11..8, CPU family code)
  7. C (Bits 7..4, CPU model number)
  8. 2 (Bits 3..0, CPU stepping ID)

As a result of this, our CPUID string looks as follows:

  • 000206C2hex, currently running µcode revision Fhex.

Please note that information down, it’s needed in the next step.

Of course, if you’re running some other UNIX, you’d be needing different tools. On FreeBSD you may be able to work with the “cpuflags” tool, like this:

$ cpuflags x 2>& | grep "Origin"

For other UNICES, you’re on your own though.

3b.) On Windows

On Windows I’d recommend Ray Hinchcliffes’ [System Information Viewer], or “SIV” in short. It’s a pretty powerful freeware system information tool that will read out the stuff we need for the next steps (You can also use something like CPU-Z of course). See the following screenshot to learn what you need to look for:

System Information Viewer (SIV)

System Information Viewer (click to enlarge)

From left to right, we need the following data as pointed out with those arrows: CPU family 6hex, CPU model 2Chex (you can ignore the decimal value “44”), stepping 2hex and µcode revision 13hex. Again, 2Chex is a combination of model number Chex and extended model number 2hex!

Just like on Linux, the final identification string needs to be assembled first. Luckily, SIV already does the decimal -> hexadecimal conversion for us. To assemble the entire CPUID, put everything together like this: 

  1. 0 (Bits 31..28, reserved)
  2. 0 (Bits 27..24, extended CPU family, zero for family 6)
  3. 0 (Bits 23..20, extended CPU family, zero for family 6)
  4. 2 (Bits 19..16, extended CPU model number)
  5. 0 (Bits 15..12, two reserved and two platform type bits, usually zero)
  6. 6 (Bits 11..8, CPU family code)
  7. C (Bits 7..4, CPU model number)
  8. 2 (Bits 3..0, CPU stepping ID)

As a result of this, our CPUID string looks as follows:

  • 000206C2hex, currently running µcode revision 13hex.

The revision is the µcode version you’re currently running. Newer version will just have higher numbers, so that’s how you can compare them with what you extracted from Intels’ package.

Note that information down, as you’ll need it in the next step.

4.) Locating the correct µcodes

4a.) On Linux/Unix

Let’s continue to assume your CPUID string is 000206C2hex. Switch to the directory where you extracted the Intel µcode package for Linux and look for the correct µcode binaries (in my case I have them grouped in folders by date as well):

$ find . -iname "*000206C2*"
./20100914/µcodes/s000206C2_m00000003_r00000013.fw
./20100826/µcodes/s000206C2_m00000003_r0000000F.fw

Two versions are available: The newer 13hex and the older Fhex (in decimal that would amount to 19 vs. 15, higher is always newer).

4b.) On Windows

Like on Linux, let’s assume your CPUID string is 000206C2hex. Switch to the directory where your extracted Intel µcodes are, and look for the corresponding files:

DIR /B /S "*000206C2*"
X:\BIOSMOD\AMI\µCodes\20100826\cpu000206c2_plat00000003_ver0000000f_date20100618.bin
X:\BIOSMOD\AMI\µCodes\20100914\cpu000206c2_plat00000003_ver00000013_date20100907.bin

There you go, the newer 13hex and the older Fhex µcodes.

5.) What’s wrong with AMI MMTool: A detailed explanation

To embed the µcodes into an actual AMI BIOS image, AMIs’ MMTool “CPU Patch” function is required. It’s a Windows program, but given its simple nature, it will run fine with Wine on Linux and FreeBSD UNIX as well:

 

 But if you attempt to embed Intels’ original binaries, it’ll fail right away:

MMTool failing to import Intel µcodes directly

MMTool failing to import Intel µcodes directly

If you extract existing µcodes from a given BIOS image and compare them with the same µcode revision in Intels’ format, you’ll notice a size difference:

$ ls -al ./06C2-Rev13.bin 20100914/µcodes/s000206C2_m00000003_r00000013.fw
-rw-rw-r-- 1 thrawn users 8192 Jan 10 14:04 ./06C2-Rev13.bin
-rw-r--r-- 1 thrawn users 7168 Jan 10 14:26 20100914/out/s000206C2_m00000003_r00000013.fw

Intels’ µcode file in this case is 7168 bytes or 7kiB in size, but the stuff we extracted from that AMI BIOS is 8192 bytes or 8kiB in size. So what’s the deal here? At first I had no idea at all and thought that they’d just be encoded differently in the AMI BIOS or something. But it turns out that that is not the case. If you open both files in a hex editor of your choice, you’ll notice something at the end of the file that came from the AMI BIOS:

 

The final 1kiB is just binary zeroes! So how do we fix that? In essence, the entire procedure is like this:

  1. Extract µcodes from the target AMI BIOS image using MMTool.
  2. Look at how large that file is (in bytes).
  3. Look at how large the desired Intel µcode file “for Linux” is for your exact CPU.
  4. Calculate the difference in bytes.
  5. Fill the end of the Intel file with as many binary zeroes as there are missing bytes.
  6. Save that file and try to load it into your BIOS image using MMTools’ “CPU Patch” function.

Alright, let’s do it!

6.) Patching those µcodes for AMI MMTool and patching the BIOS itself

First, extract some random µcode from your BIOS using AMI MMTools’ “CPU Patch” function. Look at the file and note down its’ size in bytes. Also, you may want to look at the extracted µcode to see whether it has a lot of zeroes at the end. In my case, as said, the µcodes in that AMI BIOS are 8192 bytes, or 8kiB large, while Intel’s µcode is 7kiB in size. 8192 – 7168 = 1024, so again, the difference is 1024 bytes or 1kiB.

Please triple-check this stuff, as a wrong padding will break the µcode! Of course MMTool should warn you if something’s wrong, but it doesn’t hurt to make sure it’s safe from the start.

6a.) On Linux/UNIX

Let’s make this easy, generate a 1kiB zero padding file for future use on similar µcode files:

$ dd bs=1 count=1024 if=/dev/zero of=./1kiB-zeropadding.bin
1024+0 records in
1024+0 records out
1024 bytes (1.0 kB) copied, 0.00383825 s, 267 kB/s

And now, append the zeroes to the end of the file, generating a new file in the process, so we don’t touch the originals:

$ cat ./20100914/µcodes/s000206C2_m00000003_r00000013.fw ./1kiB-zeropadding.bin > ./0206C2-rev13.bin

That file 0206C2-rev13.bin is now the final µcode file for patching into the target BIOS. As an example, I’ll patch those µcodes for Xeon X5600 processors into an ancient BIOS version 0402 of an ASUS P6T Deluxe mainboard:

 

Save that file, and you’re done modifying your BIOS with µcodes from Intels’ Linux package!

6b.) On Windows

On MS Windows there is no dd command by default, but we have a another preinstalled utility for creating our 1kiB zero padding file: fsutil! Like this:

fsutil File CreateNew .\1kiB-zeropadding.bin 1024

We don’t have a cat command on Windows either, but we can use a binary copy for file concatenation, no need to install any additional tools. We’ll attach the zero padding to the end of the Intel µcode and write the result to a new file, so we’re not altering the originals:

COPY /B .\20100914\cpu000206c2_plat00000003_ver00000013_date20100907.bin + .\1kiB-zeropadding.bin .\0206C2-rev13.bin
.\20100914\cpu000206c2_plat00000003_ver00000013_date20100907.bin
.\1kiB-zeropadding.bin
        1 file(s) copied.

That file 0206C2-rev13.bin is now the final µcode file for patching into the target BIOS. As an example, I’ll patch those µcodes for Xeon X5600 processors into an ancient BIOS version 0402 of an ASUS P6T Deluxe mainboard:

 

Save that file, and you’re done modifying your BIOS with µcodes from Intels’ Linux package!

7.) Flashing the modified BIOS

This step depends on your system. You may be able to flash from within the BIOS itself (e.g. from floppy disk or USB pen drive), or from within MS Windows or by using some bootable medium.

In any case, your BIOS image is ready now, and can be flashed at your convenience. After the update, re-check your µcode revision as shown in 3.). Your CPU should now be running the updated µcode!

8.) Downloads

Some of the programs used in this article can be downloaded here:

  • [AMI MMTool v3.22]
  • [microdecode], compiled by myself, contains 32-bit and 64-bit versions of the tool as well as the source code and license file. Compiles on Linux/UNIX as well.
  • [Intel µcodes], everything from 2009-03-30 up to 2018-01-08 as available on the Intel web site at the moment.

9.) Hopefully you haven’t bricked your mainboard

…all of this without any kind of guarantees of course! :roll:

Dec 212017
 

Oxenfree logoThanks to GOG giving Oxenfree away for free recently, I had the opportunity to test this game for its compatibility with Windows XP and Windows XP x64 Edition. So I can’t vouch for the Steam version, but I do assume that it’s the same as for the GOG version, as the Steam API itself is still compatible with XP and XP x64. Oxenfree itself is using the Unity 5.3.6.19923 engine, which is typically highly compatible when it comes to different operating system platforms. On Windows XP and Vista, Oxenfree still breaks though, so let’s take a closer look!

For this test, the 64-bit version of the game was used on XP x64, while the regular Windows XP machine got the 32-bit version of course.

1.) Installation

If you get/got the game from GOG, please do not download the Galaxy version, but the regular one, as the GOG Galaxy client really won’t run on XP.

Now, the first thing you might encounter are some installer errors, if you’re using the GOG installer. These might ring a bell for some users of Wine on Linux, as they can happen there as well. I’ve seen those on one of the two XP x64 machines that I’ve been using for testing, so they don’t always pop up, but they may appear for you:

 

Error 2/3 actually just appears twice, but at a slightly different address. Luckily, all of those can be safely ignored. I have no idea what the GOG installer is doing that some Windows boxes just don’t like, but it won’t mess up the installation!

Now let’s try to run it:

2.) Windows XP 32-bit

Hint: Note that the trick shown here may also help for XP x64!

Running the game as-is on XP 32-bit resulted in the following error on my system:

Oxenfree Direct3D error

Oxenfrees’ Unity Engine 5 failing to render to Direct3D 9

The reason for this seems to be the bundled d3d9.dll, which is actually compiled for NT 6.0 (Vista), and won’t load on XP. Even when hacking that librarys’ header to support NT 5.2 (XP x64) or NT 5.1 (XP) with CFF Explorer, the same error would pop up (why? No idea). Instead of hacking it, just rename the file to make Oxenfree use the systems’ own Direct3D 9.0c library in %WINDIR%\system32\. Launching the game after that resulted in this:

Oxenfree running on Windows XP 32-bit

Oxenfree running on a German Windows XP 32-bit (click to enlarge)

There we go! Just in case this doesn’t help, and the game isn’t even launching at all, try to rename the dxgi.dll as well, an explanation follows below.

3.) Windows XP Professional x64 Edition

On XP x64, the game didn’t even show any errors for me at all, it would just instantly terminate, even if you patch all the libraries to NT 5.2 headers with CFF Explorer (this isn’t required actually, as you’ll see).

The primary problem on XP x64 is the DirectX Graphics Infrastructure library, so dxgi.dll. I don’t even understand why it was bundled with the game, as Oxenfree uses Direct3D 9, but DXGI is meant to work as a kind of glue layer between Direct3D 10, 11 and 12. More information [here] and [here]. DXGI can do some interesting things like making simple and faster full screen / windowed switches by calling SetFullscreenState() or like resizing windows with ResizeTarget(). The idea is probably that everything works the same way, no matter whether you’re using D3D 10, 11 or 12.

However, DXGI has nothing to do with Direct3D 9?! So just rename the dxgi.dll to something else and give it a shot, it should work just like that:

A 64-bit Oxenfree running on Windows XP x64

A 64-bit Oxenfree running on Windows XP x64 (click to enlarge)

Clearly, Oxenfree isn’t using DXGI for switching to its windowed mode or for window resizing. Everything works just as intended without that DLL.

In case you now get the Direct3D error shown for the XP 32-bit solution above, just rename the bundled d3d9.dll as well. I’ve seen the error appear on one of two XP x64 machines tested, and renaming the DLL worked just like it did for 32-bit XP too.

4.) Windows Vista

I have no real idea about Vista. There was one Steam user who reported the game breaking in a similar way to what I’ve seen on XP x64 however. You can read the thread [on the Steam forums], I’ve replied there yesterday as well.

I assume that the fixes described above with help with that as well though. I just can’t test it, as I don’t have a physical Windows Vista machine at the moment.

5.) What else?

I’m not sure what exactly the bundled xinput9_1_0.dll is for. Probably some DirectInput component of DirectX handling game controllers or something? No idea. Anyway, this can be safely renamed just like the others. You should have that library installed system-wide anyway, in %WINDIR%\system32\. There are more libraries that you’ll likely never need for the regular GOG version however. If you want, you can experiment with renaming or removing the following as well (at your own risk of course):

  • All files in Oxenfree_Data\Plugins\, but leave the Steam libraries alone if you have the Steam version of the game. Also, the 64-bit version puts an sqlite3.dll there. I’m not sure if the removal of that database DLL is safe, it’s untested.
  • GogGalaxyHooks.dll, as we don’t have the Galaxy client anyway.
  • steam_api.dll or steam_api64.dll for the 64-bit version. Again, leave those alone if you’re using the Steam version.

Never touch Oxenfree_Data\Mono\mono.dll though. That’s a critical part of the Unity3D engine itself, as it’s mostly written in .Net/Mono.

And with that, just play the game! :)

Oct 162017
 

Fraps logoDoes anyone still remember [Fraps]? It seems development has come to a halt in 2013, but it was once the standard tool for measuring frame rates in 3D games and programs under Windows. Also, of course, for recording in-game video footage. All that up to Direct3D 11 and any version of OpenGL. And while the latest (and probably last) version 3.5.99 still officially supports Windows XP, it was [recently brought to my attention]German flag that it throws the “not a valid Win32 application” error.

Since I’ve been using Fraps myself, I thought I’d take a quick look at this. After confirming the error, I looked at its binary files fraps32.dll, fraps64.dat, fraps64.dll, frapslcd.dll and fraps.exe with NTCores’ [CFF Explorer]. It was as expected, its platform target was set to Windows NT 6.0 (Windows Vista), which was why it refused to start on older operating systems.

So I patched the headers of the 32-bit files to a NT 5.1 target (Windows XP) and of the 64-bit files to a NT 5.2 target (XP x64, Server 2003):

Patching Fraps with CFF Explorer

Patching Fraps to a NT 5.1 platform target with CFF Explorer

And that’s all, because Fraps 3.5.99 is still fully API compatible to Windows XP. This basically proves, that choosing that NT 6.0 platform target was either a wrong decision on the developers’ side, or just a slip-up that went unnoticed because nobody’s testing this on XP any longer:

Running the binary-patched Fraps 3.5.99 on XP x64

Running the binary-patched Fraps 3.5.99 on XP x64 (Click to enlarge)

So much for that.

If you want to run Fraps 3.5.99 on XP, please install the [official version] first, and then unpack the following archive into your Fraps installation folder, overwriting all of the files there:

  • [Fraps 3.5.99], patched for Windows XP / XP x64 compatibility.

And no, I’m not going to build a complete installer with the patched files inside, because I’m far too lazy to do that! :roll:

I tested this briefly with 3DMark 2001 SE b330 on XP and XP x64 (I didn’t have anything better / more modern on the machine at hand right now), and it did indeed work, showing its fps counter just fine!

Fraps 3.5.99 measuring the frame rate in 3DMark 2001 SE under XP

Fraps 3.5.99 measuring the frame rate in 3DMark 2001 SE under XP. And no, I didn’t pick a good scene to snap, I know… (click to enlarge)

So that’s it, cheers! :)

Oct 092017
 

Visual Basic 6.0 logoA long, long time ago, there was a pretty useful little IRC bot for Windows called the [AnGeL] bot. It seems like nobody remembers it anymore, but it was born from the Anime / Sailor Moon scene back in the late 90s to early 2000s and developed by a German software engineer going by the name of [Benedikt Hübschen]. The bot was pretty widespread for a while, at least in the German speaking parts of the Internet, and it was extensible by writing VBScript code using Microsofts’ Windows Script Host.

So, essentially, it was what you’d have used if you couldn’t run UNIX or Linux with an eggdrop bot. And I sure couldn’t, because back then I barely even knew about the existence of such systems.

Recently, I ran into a small little problem though; I wanted the bot to create and maintain an SSL/TLS-only channel. So, an IRC channel that would let users join and chat with each other only if they’re connecting to the IRC server via an encrypted connection. This is usually done by setting the +z flag on the channel, which might be followed by the IRC server itself also setting the encryption indicator mode +Z automatically.

However, I found that the bot wouldn’t enforce +z at all. It wouldn’t even set the mode when asked to do so explicitly. It was possible to add it to the list of enforced modes, but it just wouldn’t work, with the same being true for +P (protect channel modes even when nobody is in the channel).

Luckily, Mr. Hübschen made the source code available under the GPL license (that’s what he told me personally) [here]! And yes, that is VisualBasic 6 code. And yes, VB6 is a part of the infamous Visual Studio 6, you might know the abbreviation “VC6” from C/C++ programs compiled with it. So I though I’d inspect the source code and attempt to fix this issue.

I fired up my Windows 2000 Pro SP4 virtual machine for that, installed Visual Studio 6 (thank you, MSDNAA/Dreamspark/Imagine) and its service pack 6, and then loaded the project file:

The AnGeL IRC bot source code loaded in VB6

That development environment is ancient, and it sure looks the part… what a mess.

I identified the part of the code that would need changing, it’s in the public function ChangeMode() in SourceCode/Modules/Server/Server_Functions.bas. I simply copied some code and adapted it for my purpose, adding just +z and +P support for now:

Server_Functions.bas, expand/collapse source code
  1. Public Function ChangeMode(Should As String, Current As String) ' : AddStack "Routines_ChangeMode(" & Should & ", " & Current & ")"
  2. Dim u As Long, CurMode As Long, Changes As String, InsertWhat As String
  3. Dim CurPos As Long, LimitPos As Long, KeyPos As Long
  4.   ' Added by GrandAdmiralThrawn (http://wp.xin.at/archives/4343):
  5.   ' modes +z (SSL/TLS enforce) and +P (permanent channel with
  6.   ' modes preservation even when empty):
  7.   CurMode = GetModeChar(Current, "z")
  8.   Select Case GetModeChar(Should, "z")
  9.     Case -1: If CurMode = 1 Then Changes = Changes & "-z"
  10.     Case 1: If CurMode = 0 Then Changes = Changes & "+z"
  11.   End Select
  12.   CurMode = GetModeChar(Current, "P")
  13.   Select Case GetModeChar(Should, "P")
  14.     Case -1: If CurMode = 1 Then Changes = Changes & "-P"
  15.     Case 1: If CurMode = 0 Then Changes = Changes & "+P"
  16.   End Select
  17.   ' End of modification by GAT.
  18.   CurMode = GetModeChar(Current, "p")
  19.   Select Case GetModeChar(Should, "p")
  20.     Case -1: If CurMode = 1 Then Changes = Changes & "-p"
  21.     Case 1: If CurMode = 0 Then Changes = Changes & "+p"
  22.   End Select
  23.   CurMode = GetModeChar(Current, "s")
  24.   Select Case GetModeChar(Should, "s")
  25.     Case -1: If CurMode = 1 Then Changes = Changes & "-s"
  26.     Case 1: If CurMode = 0 Then Changes = Changes & "+s"
  27.   End Select
  28.   CurMode = GetModeChar(Current, "m")
  29.   Select Case GetModeChar(Should, "m")
  30.     Case -1: If CurMode = 1 Then Changes = Changes & "-m"
  31.     Case 1: If CurMode = 0 Then Changes = Changes & "+m"
  32.   End Select
  33.   CurMode = GetModeChar(Current, "t")
  34.   Select Case GetModeChar(Should, "t")
  35.     Case -1: If CurMode = 1 Then Changes = Changes & "-t"
  36.     Case 1: If CurMode = 0 Then Changes = Changes & "+t"
  37.   End Select
  38.   CurMode = GetModeChar(Current, "i")
  39.   Select Case GetModeChar(Should, "i")
  40.     Case -1: If CurMode = 1 Then Changes = Changes & "-i"
  41.     Case 1: If CurMode = 0 Then Changes = Changes & "+i"
  42.   End Select
  43.   CurMode = GetModeChar(Current, "n")
  44.   Select Case GetModeChar(Should, "n")
  45.     Case -1: If CurMode = 1 Then Changes = Changes & "-n"
  46.     Case 1: If CurMode = 0 Then Changes = Changes & "+n"
  47.   End Select
  48.   If InStr(ServerChannelModes, "c") Then
  49.     CurMode = GetModeChar(Current, "c")
  50.     Select Case GetModeChar(Should, "c")
  51.       Case -1: If CurMode = 1 Then Changes = Changes & "-c"
  52.       Case 1: If CurMode = 0 Then Changes = Changes & "+c"
  53.     End Select
  54.   End If
  55.   If InStr(ServerChannelModes, "C") Then
  56.     CurMode = GetModeChar(Current, "C")
  57.     Select Case GetModeChar(Should, "C")
  58.       Case -1: If CurMode = 1 Then Changes = Changes & "-C"
  59.       Case 1: If CurMode = 0 Then Changes = Changes & "+C"
  60.     End Select
  61.   End If
  62.  
  63.   For u = 1 To Len(Should)
  64.     Select Case Mid(Should, u, 1)
  65.       Case "l": If GetModeChar(Should, "l") = 1 Then CurPos = CurPos + 1: LimitPos = CurPos + 1
  66.       Case "k": CurPos = CurPos + 1: KeyPos = CurPos + 1
  67.       Case " ": Exit For
  68.     End Select
  69.   Next u
  70.  
  71.   CurMode = GetModeChar(Current, "l")
  72.   Select Case GetModeChar(Should, "l")
  73.     Case -1: If CurMode = 1 Then Changes = Changes & "-l"
  74.     Case 1
  75.       If CurMode = 0 Then Changes = Changes & "+l": InsertWhat = " " & Param(Should, LimitPos)
  76.       If CurMode = 1 Then If Param(Current, 2) <> Param(Should, LimitPos) Then Changes = Changes & "+l": InsertWhat = " " & Param(Should, LimitPos)
  77.   End Select
  78.   CurMode = GetModeChar(Current, "k")
  79.   Select Case GetModeChar(Should, "k")
  80.     Case -1: If CurMode = 1 Then Changes = Changes & "-k" & InsertWhat & " " & Param(Current, ParamCount(Current)): InsertWhat = ""
  81.     Case 1: If CurMode = 0 Then Changes = Changes & "+k" & InsertWhat & " " & Param(Should, KeyPos): InsertWhat = ""
  82.   End Select
  83.  
  84.   Changes = CleanModes(Changes)
  85.   ChangeMode = Changes & InsertWhat
  86. End Function

Honestly, I didn’t think it would actually compile at all. But just hit File \ Make AnGeL.exe, and it all builds just fine! And it’s fast as well. At least the building process is.

I chose to have VB6 “Optimize for fast code” and to have it “favor Pentium Pro(tm)”, whatever that means. But I assume it’s faster on P6 / i686 architectures now (Pentium Pro, Pentium II/III and other more modern chips). Probably also requires such a processor now, breaking compatibility with 586 and earlier chips, but I’m not sure whether that’s true.

I gave it the version number 1.6.3, with the latest I could ever find on the web before having been 1.6.2. You can download this version together with the source code here:

If you just want to run it instead of an existing one, all you need to do is to copy the AnGeL.exe over the one you have now, and that’s it. To edit the code, you need VisualBasic 6, just load the project file ANGEL.VBP and you can start to modify and recompile it.

Hah, changing the AnGeL bot and building its source code after so many years… felt a little bit like touching the holy grail or something. ;)

My thanks fly out for Benedikt Hübschen for developing the AnGeL bot, and for open-sourcing it! Also, I would like to thank all the contributors to the project as well! I’ll continue to use the bot, probably for a long time to come. :)

Sep 222017
 

Changeicon logo[1] 1. Introduction

Note: A more step-by-step guide is to be found farther below, see point 5.!

Recently, [Umlüx] has reminded me of his idea to be able to (visually) tag folders on Windows for specific purposes. For convenience, it’s supposed to work by right-clicking a folder in Windows Explorer, opening a submenu from the context menu, and then by picking the proper tag. After that, the folder icon should change, indicating that something’s special about this one. Windows can actually do the “tagging” part by itself using desktop.ini files, but manually writing them is a pain of course, hence the right-click idea.

The thing is, there already are tools to address folder tagging on Windows, but they’re often not feature complete, have limited XP compatibility or they lack very important features like timestamp preservation. Others have that last part, but only in paid versions of their software. So, time to do it by ourselves!

I picked his Powershell code up, and while it would run on my ancient XP x64 machines, implementing the required menu structure proved to be impossible, especially the cascading part. Ah, let me just show you the final product first, so you know what it was that I wanted (in my case, it’s meant for tagging media folders):

Changeicon context menu

“Changeicon” context menu (click to enlarge)

2. Creating the menu structure (XP + Vista compatible)

Starting with Windows 7, Microsoft introduced a new way to create submenus in the context menu, including icons, all in the Windows Registry. Older versions of Windows like Vista or XP however can’t do that, and I wanted a solution that works on all of them, from XP to Win10. So how can programs like 7-zip create such Explorer submenus with icons on legacy systems? They do so by injecting a COM .dll into the graphical shell, extending its capabilities. Typically, those are written in C++, and that’s not something I want to or can even do.

Luckily, we don’t have to develop that by ourselves, as somebody has already done it: Meet the [KuShellExtension]!

KuShellExtension – or KuShellExt in short – is a set of two library files, KuShellExtension.dll as well as KuShellExtension64.dll, the latter being meant for 64-bit Vista machines. It’s compiled for NT 5.2 though, so it’ll also work on XP x64 and Server 2003 x64. On top of that, it still works even on Windows 10! With the libraries comes an XML configuration file and some simple installer/uninstaller shell scripts.

In the example we’ve seen in the screenshot above, the respective configuration in config.xml would look like this:

expand/collapse source code
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <config version="1">
  3.  
  4.   <!-- Gobal variables -->
  5.   <var name="LEGACY_STYLE">false</var>
  6.   <var name="HIDE_MISSING">false</var>
  7.   <var name="ICON_DIR">${var:APPDATA}\changeicon\icons\</var>
  8.   <var name="INSTALL_DIR">${var:APPDATA}\changeicon\bin\</var>
  9.  
  10.   <!-- Menu -->
  11.  
  12.   <menu name="Tag Folder" class="folder" icon="${var:ICON_DIR}MainIcon.ico">
  13.     <!-- Submenus -->
  14.     <menuitem name="Tag as &quot;Currently watching&quot;" class="folder" icon="${var:ICON_DIR}CurrentlyWatching.ico" action="execute" console="false" multiple="N" workdir="C:\">
  15.       wscript &quot;//B&quot; &quot;//Nologo&quot; &quot;${var:INSTALL_DIR}changeicon.vbs&quot; &quot;%1&quot; &quot;CurrentlyWatching&quot;
  16.     </menuitem>
  17.     <menuitem name="Tag as &quot;Ongoing release&quot;" class="folder" icon="${var:ICON_DIR}WorkInProgress.ico" action="execute" console="false" multiple="N" workdir="C:\">
  18.       wscript &quot;//B&quot; &quot;//Nologo&quot; &quot;${var:INSTALL_DIR}changeicon.vbs&quot; &quot;%1&quot; &quot;WorkInProgress&quot;
  19.     </menuitem>
  20.     <menuitem name="Tag as &quot;Freshly completed&quot;" class="folder" icon="${var:ICON_DIR}NewlyCompleted.ico" action="execute" console="false" multiple="N" workdir="C:\">
  21.       wscript &quot;//B&quot; &quot;//Nologo&quot; &quot;${var:INSTALL_DIR}changeicon.vbs&quot; &quot;%1&quot; &quot;NewlyCompleted&quot;
  22.     </menuitem>
  23.     <menuitem name="----"></menuitem> <!-- Separator -->
  24.     <menuitem name="Tag as &quot;Favorite&quot;" class="folder" icon="${var:ICON_DIR}Favorite.ico" action="execute" console="false" multiple="N" workdir="C:\">
  25.       wscript &quot;//B&quot; &quot;//Nologo&quot; &quot;${var:INSTALL_DIR}changeicon.vbs&quot; &quot;%1&quot; &quot;Favorite&quot;
  26.     </menuitem>
  27.     <menuitem name="Tag as &quot;Top series&quot;" class="folder" icon="${var:ICON_DIR}Star.ico" action="execute" console="false" multiple="N" workdir="C:\">
  28.       wscript &quot;//B&quot; &quot;//Nologo&quot; &quot;${var:INSTALL_DIR}changeicon.vbs&quot; &quot;%1&quot; &quot;Star&quot;
  29.     </menuitem>
  30.     <menuitem name="Tag as &quot;Keep an Eye on for later (High priority)&quot;" class="folder" icon="${var:ICON_DIR}KeepAnEyeOnHighPrio.ico" action="execute" console="false" multiple="N" workdir="C:\">
  31.       wscript &quot;//B&quot; &quot;//Nologo&quot; &quot;${var:INSTALL_DIR}changeicon.vbs&quot; &quot;%1&quot; &quot;KeepAnEyeOnHighPrio&quot;
  32.     </menuitem>
  33.     <menuitem name="Tag as &quot;Keep an Eye on for later&quot;" class="folder" icon="${var:ICON_DIR}KeepAnEyeOn.ico" action="execute" console="false" multiple="N" workdir="C:\">
  34.       wscript &quot;//B&quot; &quot;//Nologo&quot; &quot;${var:INSTALL_DIR}changeicon.vbs&quot; &quot;%1&quot; &quot;KeepAnEyeOn&quot;
  35.     </menuitem>
  36.     <menuitem name="Tag as &quot;Keep an Eye on for later (Low priority)&quot;" class="folder" icon="${var:ICON_DIR}KeepAnEyeOnLowPrio.ico" action="execute" console="false" multiple="N" workdir="C:\">
  37.       wscript &quot;//B&quot; &quot;//Nologo&quot; &quot;${var:INSTALL_DIR}changeicon.vbs&quot; &quot;%1&quot; &quot;KeepAnEyeOnLowPrio&quot;
  38.     </menuitem>
  39.     <menuitem name="Tag as &quot;Not interested&quot;" class="folder" icon="${var:ICON_DIR}NotInterested.ico" action="execute" console="false" multiple="N" workdir="C:\">
  40.       wscript &quot;//B&quot; &quot;//Nologo&quot; &quot;${var:INSTALL_DIR}changeicon.vbs&quot; &quot;%1&quot; &quot;NotInterested&quot;
  41.     </menuitem>
  42.     <menuitem name="----"></menuitem> <!-- Separator -->
  43.     <menuitem name="Tag as &quot;Fluff&quot;" class="folder" icon="${var:ICON_DIR}SweetFluff.ico" action="execute" console="false" multiple="N" workdir="C:\">
  44.       wscript &quot;//B&quot; &quot;//Nologo&quot; &quot;${var:INSTALL_DIR}changeicon.vbs&quot; &quot;%1&quot; &quot;SweetFluff&quot;
  45.     </menuitem>
  46.     <menuitem name="Tag as &quot;Sweet, sweet Yuri!&quot;" class="folder" icon="${var:ICON_DIR}Yuri.ico" action="execute" console="false" multiple="N" workdir="C:\">
  47.       wscript &quot;//B&quot; &quot;//Nologo&quot; &quot;${var:INSTALL_DIR}changeicon.vbs&quot; &quot;%1&quot; &quot;Yuri&quot;
  48.     </menuitem>
  49.     <menuitem name="----"></menuitem> <!-- Separator -->
  50.     <menuitem name="Tag as &quot;A/V main folder&quot;" class="folder" icon="${var:ICON_DIR}AVMain.ico" action="execute" console="false" multiple="N" workdir="C:\">
  51.       wscript &quot;//B&quot; &quot;//Nologo&quot; &quot;${var:INSTALL_DIR}changeicon.vbs&quot; &quot;%1&quot; &quot;AVMain&quot;
  52.     </menuitem>
  53.     <menuitem name="----"></menuitem>
  54.     <menuitem name="Remove tag" class="folder" icon="X:\icons\Trash.ico" action="execute" console="false" multiple="N" workdir="C:\">
  55.       wscript &quot;//B&quot; &quot;//Nologo&quot; &quot;${var:INSTALL_DIR}changeicon.vbs&quot; &quot;%1&quot; &quot;del&quot;
  56.     </menuitem>
  57.   </menu>
  58. </config>

As you can see, it defines the main menu with its icon and then several submenu entries with their own icons. Also, it’s not calling my modified version of Umlüx’ Powershell script, but a Visual Basic Script instead. The reason for this shall be explained in point 4., for now we only care about the menu structure.

Looking at the variables defined on top of the XML data, ICON_DIR and INSTALL_DIR, they reference an icon folder and a program folder, both in %APPDATA%\changeicon\, so I put that into the current users’ profile folder. The icons to be used have to be put into the ICON_DIR, the scripts and an unlocker program are to be put into INSTALL_DIR. That doesn’t affect KuShellExt itself though, you can install that anywhere.

Note that while KuShellExt is loaded, you can edit its configuration on the fly. The library will detect changes made to it, and reload the updated configuration automatically, so you don’t have to unload and load the .dll when making changes to the menus or icon names.

Now, we still need the scripts and [Unlocker 1.9.2] (this is just the .exe, without the adware that usually comes with version 1.9.2). As to why Unlocker is required, well, let’s talk about that and also give you the first script:

3. The timestamp issue and the Powershell script that does the tagging

Note: Windows XP or Vista users may have to install the Windows Management Framework Core package (including Powershell 2.0) first.

This whole solution will alter folder appearances by placing hidden desktop.ini files into them. Writing such a file will alter the folders’ modification time though, or in short it’s “mtime”. And that’s bad if you have software that relies on that piece of meta data. One typical example would be backup software, that decides whether files have to be backupped based on the mtime.

In my own case, the backup problem applies to my rsync backup system, but there’s even more; I’ve written myself a Perl script that walks through my entire video folder, generating an HTML report out of the data, sorted by “latest first”. That way, I can see what movies or series have been added or modified recently. That script also depends on the mtime, so having it change when tagging folders is not acceptable!

Time to look at Umlüx’ script, or rather my modified version of it, changeicon.ps1:

changeicon.ps1, expand/collapse source code
  1. # Change Icon v0.815 Karl Veratschnig 2017
  2. # Modified by Michael Lackner
  3. #
  4. # Licensed under the GNU General Public license version 3.0 with express
  5. # permission by Karl Veratschnig.
  6. #
  7. # usage: 
  8. # .\changeicon.ps1 *dir_path* *icon*
  9. # i.e. ./changeicon.ps1 c:\testfolder Favorite
  10. #
  11. # run from anywhere:
  12. # Powershell.exe set-executionpolicy remotesigned -File "path to ps1"
  13. #
  14. # use "del" icon to revert folder to normal
  15.  
  16. ###
  17. # Update-ExplorerIcon refreshes icons in Windows Explorer by rebuilding its icon cache
  18. # Written by Idera,
  19. # http://community.idera.com/powershell/powertips/b/tips/posts/refreshing-icon-cache
  20. ###
  21. function Update-ExplorerIcon {
  22.   [CmdletBinding()]
  23.   param()
  24.  
  25.   $code = @'
  26.   private static readonly IntPtr HWND_BROADCAST = new IntPtr(0xffff); 
  27.   private const int WM_SETTINGCHANGE = 0x1a; 
  28.   private const int SMTO_ABORTIFHUNG = 0x0002; 
  29.  
  30.   [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
  31.   static extern bool SendNotifyMessage(IntPtr hWnd, uint Msg, UIntPtr wParam,IntPtr lParam);
  32.  
  33.   [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)] 
  34.   private static extern IntPtr SendMessageTimeout ( IntPtr hWnd, int Msg, IntPtr wParam, string lParam, uint fuFlags, uint uTimeout, IntPtr lpdwResult ); 
  35.  
  36.   [System.Runtime.InteropServices.DllImport("Shell32.dll")] 
  37.   private static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2);
  38.  
  39.   public static void Refresh() {
  40.     SHChangeNotify(0x8000000, 0x1000, IntPtr.Zero, IntPtr.Zero);
  41.     SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, IntPtr.Zero, null, SMTO_ABORTIFHUNG, 100, IntPtr.Zero); 
  42.   }
  43. '@
  44.   Add-Type -MemberDefinition $code -Namespace MyWinAPI -Name Explorer 
  45.   [MyWinAPI.Explorer]::Refresh()
  46. }
  47.  
  48. ###
  49. # User-configurable block
  50. ###
  51. $iconpath = "$env:APPDATA\icons\"           # Where icon files reside
  52. $installpath = "$env:APPDATA\bin\"          # Where scripts & binaries reside
  53. $unlocker = "unlocker.exe"                  # Name of the handle unlocker to use
  54. $ulparams = "/S"                            # Unlock parameter to supply to the unlocker
  55.  
  56. ###
  57. # Non-user-configurable block / main program
  58. ###
  59. $folder = Get-Item $args[0]                 # Get folder from arguments
  60. & $installpath$unlocker "$folder" $ulparams # Remove open handles from folder
  61.                                             # WARNING: If files inside *are* open in
  62.                                             # other programs, their behavior might
  63.                                             # become unstable. Data loss is possible!
  64. $icon = $args[1]                            # Get icon name from arguments
  65. $olddate = $folder.LastWriteTime            # Get modification time stamp (mtime)
  66. $folder.attributes="Normal"                 # Reset folder attributes
  67. if (Test-Path "$folder\desktop.ini") {      # Check for existing desktop.ini
  68.   & $installpath$unlocker "$folder\desktop.ini" $ulparams # Unlock it, just to make sure
  69.   Remove-Item "$folder\desktop.ini" -Force    # Delete it if present
  70. }
  71. if($icon -ne "del") {                       # If op is to tag, not to delete...
  72.   $stream = [System.IO.StreamWriter] "$folder\desktop.ini" #... build new desktop.ini
  73.   $stream.WriteLine("[.ShellClassInfo]")            # Category
  74.   $stream.WriteLine("IconFile=$iconpath\$icon.ico") # Icon file
  75.   $stream.WriteLine("IconIndex=0")                  # Icon #0 in file
  76.   $stream.WriteLine("IconResource=$iconpath\$icon.ico,0") # Icon #0 in file (for modern OS)
  77.   $stream.WriteLine("Infotip=$icon")                # Info tip set to icon name
  78.   $stream.WriteLine("ConfirmFileOp=0")              # Disable special folder handling
  79.   $stream.WriteLine("TimeStamp=$olddate")           # Remark time stamp in the file for
  80.                                                     # safety/recovery purposes
  81.   $stream.close()                                   # Close file
  82.   $folder.attributes="ReadOnly"                     # Set folder to RO to enable special
  83.                                                     # desktop.ini handling
  84.   (Get-Item "$folder\desktop.ini").attributes = "Hidden,System" # Set desktop.ini
  85.                                                     # attributes to Hidden+System, also
  86.                                                     # to enable special folder handling
  87. } else {                                    # If op is to delete, not to tag...
  88.   if (Test-Path "$folder\desktop.ini") {      # Check whether desktop.ini really exists
  89.     & $installpath$unlocker "$folder\desktop.ini" $ulparams # Unlock it, just to make sure
  90.     Remove-Item "$folder\desktop.ini" -Force    # Delete it if present
  91.   }
  92. }
  93.  
  94. Update-ExplorerIcon # Rebuild Windows Explorers' icon cache
  95.  
  96. Start-Sleep -s 2    # This is to work around a race condition against writes/flushes on
  97.                     # some systems, so we give the system a little bit of time for its
  98.                     # "beauty sleep" before resetting the mtime.
  99.  
  100. $folder.LastWriteTime = Get-Date $olddate   # Reset original mtime stamp

 

As you can see, the mtime is first being read from the folder by using $folder.LastWriteTime, and then reset to that value after writing the desktop.ini to the target directory. Also, it calls unlocker.exe /S on that folder to unlock it first, no matter whether there are open files within that folder or anything. This is done to avoid the dangerous situation, where the code would write the desktop.ini, but would then fail to update the folders’ timestamp due to open handles on the directory. Often this would also be caused by Windows Explorer itself, especially if you have open subfolders when tagging.

Forcefully unlocking the folder first deals with that problem. Please keep in mind that doing this may make programs relying on their open handles to behave in an undefined way however. Loss of data in that folder could be possible, e.g. if a text editor loses its handle for writing to a file in that folder.

In case something still goes wrong, the mtime is also being remarked in the desktop.ini file, in the value TimeStamp.

Here’s a sample .ini, as generated by changeicon, the format of the timestamp depends on your locale:

  1. [.ShellClassInfo]
  2. IconFile=C:\Documents and Settings\USERNAME\Application Data\changeicon\icons\WorkInProgress.ico
  3. IconIndex=0
  4. IconResource=C:\Documents and Settings\USERNAME\Application Data\changeicon\icons\WorkInProgress.ico,0
  5. Infotip=WorkInProgress
  6. ConfirmFileOp=0
  7. TimeStamp=09/22/2017 08:59:08

Now, there is one cosmetic issue left here…

4. Hiding that ugly terminal window

You can try to hide the window that pops up when calling a Powershell script, but it never really works reliably. So, are we going to tolerate that thing popping up every time we tag a folder? As if! That’s where the VBScript code comes in. This is an old trick I’ve used to run cmd batch scripts in a hidden way before, and this also works for calling Powershell scripts. I call this changeicon.vbs:

changeicon.vbs, expand/collapse source code
  1. ' Declare variables and create shell object:
  2. Dim AppData, WinDir, PowerShell, arg0, arg1
  3. Set WshShell = Wscript.CreateObject("WScript.Shell")
  4.  
  5. '''
  6. ' User-configurable part (file/folder locations)
  7. '''
  8. AppData = wshShell.ExpandEnvironmentStrings("%APPDATA%")
  9. WinDir = wshShell.ExpandEnvironmentStrings("%WINDIR%")
  10. PowerShell = WinDir & "\system32\WindowsPowerShell\v1.0\powershell.exe"
  11.  
  12. '''
  13. ' Non-user-configurable part
  14. '''
  15. ' Pull command line arguments into variables:
  16. arg0 = WScript.Arguments.Item(0)
  17. arg1 = WScript.Arguments.Item(1)
  18. ' Execute program:
  19. WshShell.Run """" & PowerShell & """ """ & "-File" & """ """ & AppData & "\changeicon\bin\changeicon.ps1" & """ """ & arg0 & """ """ & arg1 & """", 0
  20. Set WshShell = Nothing

 

5. Actually running that Frankenstein solution

In essence, you need to do the following:

  1. Pick a folder for changeicon.ps1, changeicon.vbs and unlocker.exe, and put those three files into it.
  2. Pick a folder for your icons, and place all your desired icons into it, no subfolders!
  3. Edit changeicon.ps1 and changeicon.vbs and change the install/icon paths.
  4. Install KuShellExtension and run its DLL hook script install.cmd.
  5. Edit KuShellExts’ settings.xml to reflect your menu structure and the corresponding menu icons and commands to execute. Better don’t delete all the comments in that file, the documentation can be pretty helpful at times.

Unfortunately I can’t share the icons I’ve created because they’re based on Microsofts’ icons, but you can easily find icons online or make your own with Microangelo or IcoFX. Both are commercial software for Windows, but you could also use the Gimp for that.

6. Enjoy tagging folders

Folders tagged with changeicon

Folders tagged with changeicon

With that, it’s much, much easier to keep track of things and to not forget what kind of stuff (*cough* tons of Anime *cough*) I still need to watch or keep an eye on for later.

But it’s not limited to that; You could use tagged folders for pretty much anything, like designating them to specific purposes or use them for document or work classification, whatever.

It’s interesting that even Windows 10 still can’t do that via the GUI by default by now…

Anyway, thanks fly out to [Umlüx] for writing the most important part at the core of this mess, the Powershell script, and also to [Idera] for the icon refreshing code I grabbed from their site! Also, if you want Umlüx’ modern solution for Windows 7+, which is based on pure Powershell code and Registry entries, you’d need to contact him directly. You may wish to do so, if you don’t need XP or Vista, because then you wouldn’t need to rely on the KuShellExtension anymore.

Happy tagging!

 

[1] Logo based on the Windows 10 Custom Folder Icons Pack made by Terraromaster

Aug 182017
 

Adobe Photoshop CS6 logo1. Introduction

While I’ve been a Corel Photopaint user for about 20 years now (!), I’ve recently bought myself a license for Adobe Photoshop CS6 Extended, simply because I’ve hit some memory and stability limitations with Corel’s solution when working with very large files (A0 @ 300dpi) and lots of objects (=”layers”), sometimes hundreds of them. Generally, Photopaint tends to become unstable as you keep working with very large files, and things like masks or object copies start failing silently even well before its 32-bit address space is exhausted. Well, Adobe Photoshop CS6 was the last standalone version without relying on the “Creative Cloud” and the last that would work on Windows XP / XP x64, even in its 64-bit version on the latter. So there you have it. I was thinking of migrating.

2. Licensing woes

The first thing that really got on my nerves was Adobes’ licensing system. In my version of CS6, Adobes’ application manager just wouldn’t talk to the activation servers anymore and offline activation is broken as well, as the tool won’t generate any request codes for you (the option just isn’t there anymore). Why is this? During testing I found that Microsofts’ ancient Internet Explorer 8 – the latest on XP – can’t talk to certain activation servers via encrypted connections any longer. I guess Adobe upgraded SSL on some of their servers.

My assumption is that the Adobe application manager uses IEs’ browsing engine to connect to those servers via HTTPS, which fails on anything that isn’t Vista+ with a more modern version of Internet Explorer.

So? I was sitting there with a valid license, but unable to activate the software with it. It’s sad, but in the end, I had to crack Photoshop, which is the one thing I didn’t want to do. Even though Photoshop CS6 officially supported XP, it can no longer be activated on such old operating systems, and nobody cares as it’s all deprecated anyway. It’s annoying, but there was no other choice but to remove the copy protection. But hey, my conscience is clean, I did buy it after all.

3. Language woes

Well, I bought a German version of Photoshop. Which I thought was ok, as Adobe would never do something as stupid as to region-lock their licenses, right? Riiight? [Wrong]. You have to download the [correct version] for your region, or the license won’t work. I mean, German is my native language, but I’m using operating systems and software almost exclusively in English, so that was unacceptable. Thankfully, there is an easy fix for that.

First: Close Photoshop. Then, let’s assume you’ve installed it in the default location. If so, enter the folder %PROGRAMFILES%\Adobe\Adobe Photoshop CS6 (64 Bit)\Locales\de_DE\Support Files\ (swap the de_DE\ part with your locale, you’ll find it in that Locales\ folder). There you’ll find a .dat file, in my case it was called tw10428.dat. Rename it to something like tw10428.dat-backup. Relaunch Photoshop. It’ll be English from now on[1]!

4. The hardware I used for testing

This is important, as some features do depend on certain hardware specifications, like 512MiB of VRAM on the graphics card or certain levels of OpenGL and OpenCL support, those kinds of things. So here’s the hardware, which should be modern enough for CS6:

  • Intel Xeon X5690 3.46GHz hexcore with HT (Westmere architecture, think “Core i7 990X”)
  • 48GiB of RAM
  • nVidia GeForce GTX Titan Black 6GiB (Kepler architecture, somewhat similar to a GeForce GTX 780Ti)

Also, the driver used for the Titan Black is the latest and last one available for XP, 368.81. It even gives you modern things like OpenGL 4.5, OpenCL 1.2 and CUDA 8.0:

nVidia control panel for driver 368.81 on XP x64

nVidia control panel for driver 368.81 on XP x64

5. What it looks like without any compatibility hacks

However, even though the 64-bit version of Photoshop CS6 runs on Windows XP x64 (when cracked :( ), a few things are missing regarding GPU support and 2D/3D acceleration. Let’s launch the application:

Photoshop CS6 Extended on Windows XP x64 without any modifications

Photoshop CS6 Extended on Windows XP x64 without any modifications (click to enlarge)

What we can see immediately is that the 3D menu is missing from the menu bar. This is because Adobe generally forbids the use of extended 3D features (import and rendering of 3D models) on all XP systems. There was an explanation about that on the Adobe labs pages, but that link is dead by now, so I can’t be sure why it was originally disabled. I’ll talk about that stuff later. First, we’ll look at the hardware we do get to use for now, this can be found under Edit \ Preferences \ Performance...:

 

Well, we do get to use a ton of memory, but as you can see, my relatively powerful GTX Titan Black is not being used. Strangely, it says it’s because of me not running the Extended version of Photoshop CS6, but that’s not quite correct:

Photoshop CS6 Extended splash screen

Photoshop CS6 Extended splash screen

I’m not actually sure whether it always said that, as I’ve been messing with Photoshop for a while now, so maybe there was a different message there at first. But it doesn’t matter. The bottom line is, we’re not getting anything out of that GPU!

And we’re gonna fix that.

6. Getting 2D and OpenCL GPU acceleration to work

This is actually easy. We’ll fool Photoshop CS6 into thinking that my GTX Titan Black (which is newer than the software) is an “old GPU”. You can tell Photoshop to still do its stuff on older, slower GPUs despite them not being officially supported. And when that switch is flipped, it seems to apply to all unknown GPUs and graphics drivers, no matter what. Check out the following registry hack:

  1. Windows Registry Editor Version 5.00
  2.  
  3. [HKEY_CURRENT_USER\Software\Adobe\Photoshop\60.0]
  4. "AllowOldGPUS"=dword:00000001

Save that text into a .reg file, for instance AllowOldGPUS-in-Photoshop-CS6.reg. Close Photoshop, then double-click on that file, and it’ll create that dword value AllowOldGPUS for you and set it to 1[2].

Note that the registry path will be different for older versions of Photoshop, so the last part might not be 60.0 but something else, like 11.0 in such a case. Just check first if you have to, by launching Windows’ Regedit tool and navigating to that part of your user registry.

After that, launch Photoshop, and again look at Edit \ Preferences \ Performance...:

Graphics settings when "AllowOldGPUS" is enabled

Graphics settings when “AllowOldGPUS” is enabled

Aha! Looking better. But if you click on that “Advanced Settings…” button, you get this:

Advanced gaphics settings with "AllowOldGPUS" enabled

Advanced gaphics settings with “AllowOldGPUS” enabled

Almost everything checks out – even OpenCL – but we still don’t get to use the advanced OpenGL rendering mode that is supposed to make things even faster. But most of the GPU accelerated 2D functionality is there now, it’s just not working at maximum performance, at least according to Adobe. You’ll get to use stuff like Oil Paint and Scrubby Zoom etc. now though.

But, the 3D stuff that’s been disabled on XP is still missing entirely. And we’ll get to that final part now!

7. Getting 3D and the advanced level of OpenGL 2D acceleration to work

This is a bit more tricky. This stuff is blocked by Photoshops’ operating system detection routines. You can check their results by clicking on Help \ System Info... and looking at the top part of that report:

Adobe Photoshop Version: 13.0.1 (13.0.1.3 20131024.r.34 2013/10/24:21:00:00) x64
Operating System: Windows XP Professional 64-bit
Version: 5.2 Service Pack 2

So we have to fool it into thinking that it’s sitting on a more modern operating system. The tool for the job is Microsofts’ own [Application Verifier]. It’s a software testing tool meant to be used during testing phases of a software development process. It’ll do just what we need though. Download the 64-bit edition (32-bit one is included in that as well, you can ignore that for our purpose), and run it.

Microsofts' Application Verifier

Microsofts’ Application Verifier

Right click into its Applications pane, and add two applications that you can find in your Photoshop installation directory, Photoshop.exe and sniffer_gpu.exe. The latter is a command line tool that detects GPU VRAM, driver version, OpenGL / OpenCL versions etc. You can launch that on a terminal window as well, it outputs everything right to stdout, so you can see what it’s reporting right on the terminal. This program is launched by Photoshop every time during startup to determine GPU and graphics driver+API capabilities.

Well, uncheck everything in the Tests pane, and check just Compatibility \ HighVersionLie. Right-click it, and pick Properties and enter the following[3]:

Faking Windows 7 x64 SP2

Faking Windows 7 SP2

So we’re reporting an NT 6.1 kernel (Windows 7) with build number 7601 and service pack 2, which would be current as of today. Keep it like that, and launch Photoshop. You’ll see this:

Photoshop CS6s' full functionality, ready to be used?

Photoshop CS6s’ full functionality, ready to be used? (Click to enlarge)

And there we go, our 3D menu is active on top, right between the “Filter” and “View” menus. But that doesn’t mean that it’s tools are really working… Anyway, the System Info will now report a different operating system:

Adobe Photoshop Version: 13.0.1 (13.0.1.3 20131024.r.34 2013/10/24:21:00:00) x64
Operating System: Windows 7 64-bit
Version: 6.1

Oddly enough, the service pack 2 part is missing, but who cares. Let’s take a look at the graphics settings!

Advanced graphics settings, revisited

Advanced graphics settings, revisited

Alright, we can use advanced OpenGL effects after applying our Windows 7 fake! Very good. That means all 2D OpenGL / OpenCL accelerated parts are working at maximum performance now! And as a first indicator of 3D also working, we can now access the 3D settings as well, look at this:

3D settings

3D settings, even the full 6GB VRAM minus some 32MiB of reserved memory have been detected (click to enlarge)

For the 3D test, I decided to download a 3DStudioMax sample model from GrabCAD, [here] (that website requires registration). A complete render of that model can also be seen there, looks like this:

"Chainmail maelstrom"

It’s called “Chainmail maelstrom unit”

So, let’s create a new document, import that model via 3D \ New 3D Layer from File... and switch to Photoshops’ 3D view! And…

OpenGL accelerated 3D preview

OpenGL accelerated 3D preview (click to enlarge)

It’s totally working! Strangely you don’t get anti-aliasing even though the card can do it, but at least it’s something. I’m almost feeling like sitting in front of some kind of CAD software now, with all that realtime 3D rendering. Photoshop does interpret the material properties a bit weirdly however, so it’s not glossy enough and the color is wrong for something that’s supposed to be “steel”. I didn’t fix it up though, just left it as-is and clicked “render”! Then, after lots of waiting, you get some nicer output:

Final render

Final render (click to enlarge)

Please note that the above screenshots are 8-bit PNG, so they’re not true representations of the source at all. Still, should be good enough.

One disappointing part is, that the final render – or rather raytracing output – isn’t being crunched on the GPU. Instead, it’s using a lot of CPU cores. In this case, my hexcore Xeon with 12 threads was loaded up to 70-90%. But it would still be a lot faster if done by an OpenCL or CUDA raytracer on the GPU. I will need to check whether there are any plugins for that.

Anyway, this means that the full potential of Adobe Photoshop CS6 Extended can be unlocked on Windows XP Professional x64 Edition SP2! Cheers! Beer Smilie

8. What about Windows XP 32-bit?

No idea. I haven’t tested it. According to users on the web, the OpenCL part wouldn’t work on 32-bit at all, no matter which operating system. It’s supposed to be “by design” for whatever reason. I’m not sure if its just disabled like with 3D, or whether the libraries using it are really not there for the 32-bit version of Photoshop CS6. You would need to test that by yourself, but I wouldn’t get my hopes up with that. At least the other parts should be doable, including 3D.

Now, all that remains is to learn how to actually use Photoshop CS6. :roll: It’s probably going to be a bit painful coming from the Corel side of things…

 

[1] Adobe Photoshop CS6 – Change language to English, Tim Barrett, 2014-08-17 on Youtube

[2] Enable GPU Acceleration in x64 XP, op2rules, 2009-12-11 on Youtube

[3] A comment, Schlaubstar, 2012 on Youtube

Jul 282017
 

Mail.ru logo1.) Introduction

Of course you could say: “If you’re going to use Russian software, that’s what you’d have to expect!”. But yeah. I’ve actually used tools written by Russian developers before, and they used to be very slim and fast, so I thought, why not give it a shot. Background is that I’ve finally ditched my ancient Nokia E72 “smart phone” based on Symbian 9.2 / S60 3rd, which has become almost unusable because of its lack of modern SSL ciphers (most websites won’t let you connect anymore) and because of its Skype and ICQ clients being banned from their respective servers.

So I finally went ahead and got myself an Android 7.1.1 device, the Blackberry KEYone, my second attempt at using the OS (first was a Motorola Milestone 2 with Android 2.1, a failure because of many reasons).

Anyway, I had to find an eMail app that would let me do two things:

  1. Display and send everything as plain text (I hate HTML mails and find them pretty insulting to be honest)
  2. Allow me to connect to mail servers which support only older SSL/TLS protocols and ciphers (I’ve got no choice here)

2.) The Mail.ru email client on Android

2a.) The app itself

So, I tested a lot of clients, one of which was [Mail.ru], a pretty high-ranked email app (4.6/5) with more than 10 million installs out there. Superficially, it looks just like pretty much any other email client, because there are likely readily available Android libraries for implementing email clients:

Mail.ru client ad

An image directly from the Google play store, showing the apps’ GUI (click to enlarge)

So they advertise it with slogans like “ideal application for any mail” and “add all your email boxes in one application”. Actually, it’s ideal for just one thing: To hand over all your email accounts and emails to a Russian company and with it the Russian government – because in Russia, companies have to yield to the government and grant it full access to user accounts and data by default.

I guess free Russian developers and actual Russian software companies have to be treated very differently!

What I did was to enter my own email account credentials in the Mail.ru app to be able to fetch my emails via IMAP. I found that the client does not meet my personal requirements (no way to force plain text email), so after my quick test, I just uninstalled the app.

2b.) What the app does without you noticing

However, by that time, the Mail.ru app had already leaked my account credentials to certain mail.ru and my.com servers (my.com is a part of the bigger Mail.ru group), which had now started to log into my account from Russia – periodically checking all my email boxes and downloading every single message stored on my own server. Let’s have a look at the logs!

Here is their first connection attempt, coming from 5.61.237.44 (sapif30.m.smailru.net) as well as the second one from 94.100.185.215 (rimap21.i.mail.ru):

Tue 2017-07-25 14:59:27: Session 5554; child 3; thread 1232
Tue 2017-07-25 14:59:26: Accepting IMAP connection from [5.61.237.44:42273]
Tue 2017-07-25 14:59:27: SSL negotiation successful (♡)
Tue 2017-07-25 14:59:27: --> * OK ♡ IMAP4rev1 ♡ ready
Tue 2017-07-25 14:59:27:  1 OK LOGIN completed
Tue 2017-07-25 14:59:27:  1 OK LIST completed
Tue 2017-07-25 14:59:27:  * BYE IMAP engine signing off (no errors)
Tue 2017-07-25 14:59:27: --> . OK LOGOUT completed
Tue 2017-07-25 14:59:27: IMAP session complete, (2654 bytes)
Tue 2017-07-25 14:59:27: ----------
Tue 2017-07-25 15:00:04: ---------- Partial transcript, remainder will follow.
Tue 2017-07-25 15:00:04: Session 5556; child 4; thread 3588
Tue 2017-07-25 14:59:28: Accepting IMAP connection from [94.100.185.215:53424]
Tue 2017-07-25 14:59:28: SSL negotiation successful (♡)
Tue 2017-07-25 14:59:28: --> * OK ♡ IMAP4rev1 ♡ ready
Tue 2017-07-25 14:59:28:  1 OK LOGIN completed
Tue 2017-07-25 14:59:28:  * CAPABILITY ♡
Tue 2017-07-25 14:59:28: --> 2 OK CAPABILITY completed

You might have guessed it, the ♡ marks things I cut from the logs for privacy reasons. Guess I got a bit too creative. ;) Anyway, this was only the beginning. Later, some mail collector servers from the IP range 185.30.17*.** (collector*.my.com) started to log in and download all my emails from all my folders! Here’s just a small excerpt from the commands issued with one of my archive folders serving as an example – most of the stuff has been cut out to make it more concise:

Tue 2017-07-25 14:59:29:

All of those are just the remote commands issued to my server. Note that in IMAP4, UID FETCH <UID> BODY.PEEK[] at the bottom is an actual message download. Needless to say, there were thousands of those going unchecked, because it took me 3 days to discover the leak. And I only discovered it coincidentally too. So by that time they had long downloaded all my emails from my own server to Russia. If you’re not running your own mail server, you wouldn’t even notice this.

So if you just happened to enter your AOL, Yahoo, gmail or Hotmail accounts, you’d never see those Russian servers accessing those accounts remotely!

3.) This can’t be ok, can it?

This behavior is completely unacceptable and has been reported to Google as it is borderline regarding Googles’ own privacy policy:

Privacy Policy & Secure Transmission

If your app handles personal or sensitive user data (including personally identifiable information, financial and payment information, authentication information, phonebook or contact data, microphone and camera sensor data, and sensitive device data) then your app must:

  • Post a privacy policy in both the designated field in the Play Console and from within the Play distributed app itself.
  • Handle the user data securely, including transmitting it using modern cryptography (for example, over HTTPS).

The privacy policy must, together with any in-app disclosures, comprehensively disclose how your app collects, uses and shares user data, including the types of parties with whom it’s shared.

Prominent Disclosure Requirement

If your app collects and transmits personal or sensitive user data unrelated to functionality described prominently in the app’s listing on Google Play or in the app interface, then prior to the collection and transmission, it must prominently highlight how the user data will be used and have the user provide affirmative consent for such use.

First of all, the mail collectors drop down to cryptographic ciphers even I wouldn’t use anymore when asked to do so. I mean, it sounds hypocritical coming from me (because I’m actually using very old ciphers too, as I’m out of options on my ancient server), but they do fall back to what’s by no means “modern cryptography”. Also, the leaking of account credentials and data to Russian servers and the continuous use of said data even after the user has stopped using Mail.ru services is not mentioned anywhere while installing or using the app, not that I could see at least.

I most definitely didn’t give my consent to having the app use my data like this – I wasn’t presented with an EULA during the installation or use of the software. Also, the (Russian…) email they had sent me after accounts were set up in the app didn’t show an EULA or privacy statement either. It’s even worse considering [Mail.ru’s history] in terms of handling that information.

None of this is new either, see e.g. [this Reddit] (MyMail is from my.com – as said, a part of the Mail.ru Group).

Well, I started to look around and found a Mail.ru [user agreement] online. The interesting part is point 4.1.3:

4.1.3 In addition to the registration procedure on the Internet Service specified in clause 4.1. the user may be granted the right to register through using its data (login and password) of the e-mail box registered at the third person’s resource.

Irrespective of using any method of registration on the Internet Service the User’s password used to visit the Internet Service shall be beyond the reach of Mail.Ru.

Now that part is a bit problematic. The “third person’s resource” is clearly your own mail account on some other server. So like my email account on my own server. The question is, what exactly does it mean when they say that the users’ password shall be “beyond the reach of Mail.Ru”? Guess they’d mean my actual plain text password, right?

Well, no matter if they use hashes with <-- 2 authenticate CRAM-MD5, or instead just plain text <-- 1 LOGIN ♡@♡.♡ ♡♡♡♡♡♡, they do have my password stored away on their servers as clear text (probably on some encrypted file system? But still.). I wouldn’t call that “beyond the reach of Mail.ru” anymore.

I guess I could have misread the user agreement (that I wasn’t even presented with!) somewhere, but it doesn’t seem to me as if they’d be following their own rules regarding privacy?!

If you’re using the Mail.ru app I can only advise you uninstall it if you haven’t done so already and to change all account passwords ever entered in the application to stop the Russian collector servers from logging into your accounts and “stealing” your email even after app deinstallation.

On a side note: Since K-9 Mail isn’t exactly right for me either, I settled with [R2Mail2], which is being developed in Austria by the company [RundQuadrat]. I’ve been talking with its developer over the last few days, and he seems a like a nice family guy. I do like the client, as it has an impressive feature list, let’s just name a few:

  • Manually configurable SSL/TLS cipher list, you can pick which ciphers you want or don’t want to use, including the option to support a few deprecated ciphers.
  • Data oriented encryption with either S/MIME, or even PGP and PGP/MIME for emails and also arbitrary files (a small tool for file encryption is embedded in the client).
  • Support for Microsoft Exchange servers
  • Option to stop syncing in the background, so a full shutdown of the app is possible with ease.
  • Full plain text support, so you can force all messages to be displayed and sent in plain text only.
  • The client itself can be password protected and can be instructed to store all local data in encrypted form.
  • Extremely configurable: Reply/Forward Prefixes, host name use in EHLO command, notification LED color ( :roll: ), IPv4/IPv6 preference, Certificate store access & configuration, peak day/time option to boost synchronization, sync grouping with other apps to save battery, local email pruning and many, many other things.

It does come at a price though, as it costs 4.80€. But if you want a seriously powerful and I’d say more trustworthy email application for Android, you might give this a shot. Otherwise, maybe just go with the free K-9 mail app if you want plain text and don’t need to rely on mail servers with antiquated SSL/TLS implementations.

But no matter what, stay away from Mail.ru and MyMail!

Update, 2017-12-30:

Thanks to a notification from [Bier.jpg]German flag I have now learned, that the testing password used to probe the Mail.ru and MyMail services (in context of writing this article) has been leaked to the Internet!

The corresponding data has been presented to the public on the Chaos Communication Congress (34C3) of the corresponding Chaos Computer Club (CCC), in the context of its [Can I Haz Passw0rds?] project. The leak website will be offline soon enough, but you can continue to access the password database on the [Tor network] after the Congress has ended (Open that link in the [Tor Browser]). Since my original, former true password has not been leaked, this must have happened some time after 2017-07-25.

Additionally to the two leaks that I attribute to Mail.ru and MyMail, there was also a third one with the same, temporary password. I’ve used it to continue my tests of all kinds of Android eMail applications, but unfortunately, I can’t be sure who the third culprit might have been. :( The only two Apps I’m sure couldn’t have been responsible are [K-9 Mail] and the Austrian program [R2Mail2], as those have only been fed real passwords, and they’re not supposed to leak them off-device anyway.

So much for that! :roll:

PS.: I cannot exactly prove, that two of the three leaks are from Mail.ru and MyMail, but given their handling of passwords and their history of repeated, massive password database leaks, I’m pretty sure that they were involved in this as well.