Saturday, September 30, 2017

PHP error spews may lead to bogus data being passed around

Today I was debugging a web page wherein a JavaScript function uploaded data to an API endpoint written in PHP and then received data from that endpoint to use in a page redirection. After adding a feature to the endpoint but making only small changes to the client-side script, I was puzzled to receive this error in the Chrome console:

[Deprecation] Resource requests whose URLs contained both removed whitespace (`\n`, `\r`, `\t`) characters and less-than characters (`<`) are blocked. Please remove newlines and encode less-than characters from places like element attribute values in order to load these resources. See https://www.chromestatus.com/feature/5735596811091968 for more details.

It was logged, as far as I could tell, after the sending of an AJAX request, but I was very confused because the URL that request was POSTed to definitely didn't have any whitespace or less-than characters. When I tried the request in Postman, however, I found that I received some errors from the PHP script that my JavaScript was interpreting as part of the URL to redirect to after the action completed. Sure enough, the HTML tags used to format the notices had less-than characters, and there were newlines in the spew. I had forgotten to step through the callback's setting of window.location.href. Fixing the PHP script led to the return of valid data for a URL fragment, which fixed the problem.

Wednesday, September 27, 2017

gpedit.msc only edits the GPOs, which might not actually get applied

Today I tested a pretty neat-looking method of getting the Local Group Policy Editor onto Home editions of Windows. It uses only DISM and package files that come with the Home edition. Sure enough, gpedit.msc exists and runs after using it. Changing the Administrative Templates settings persisted across runs of the LGPE, so it was clearly saving them somewhere, but they never wound up in the Registry and therefore had no effect. Therefore, installing the LGPE correctly isn't enough; you also need to have the infrastructure that transcribes the POL contents into the Registry. (Policy Plus does the transcription itself if necessary.)

This DISM approach does work nicely, though, for the things outside the Administrative Templates branch that I tested. Therefore, it's a great complementary strategy to Policy Plus, which currently has no support for anything outside Administrative Templates. The only disadvantage is that it also installs secpol.msc, which is what Policy Plus checks for to determine whether it's on a Pro edition, so that's something I should probably change for users' convenience.

Tuesday, September 26, 2017

Setting an HKCU Registry setting for all users on the machine

Suppose there's a per-user Registry setting that, for your users' convenience, you'd like to set for everyone on the machine. If there's no policy for it, the standard Group Policy tools won't do the job. Nevertheless, the Group Policy infrastructure will be happy to set any Registry setting you specify, with the caveat that if it's not in a policy branch, it won't go away if you change your mind and unset it in the GPO.

Normal tools won't let you set arbitrary settings, but Policy Plus will. You can use the Import REG option (either the menu item under Share or the button in the POL editor) to apply a REG file to the GPO. Alternatively, you can skip the file and use File | Edit Raw POL directly. If you have a Group Policy-enabled edition of Windows, the change will be applied to your user account and to all others when they next log on.

Unfortunately, on Home editions, there's no way to disseminate user settings except by manually loading each user hive and changing them individually, but Policy Plus will happily apply them to your account when you click Save Policies.

Sunday, September 24, 2017

Internet Explorer has to be run before Invoke-WebRequest will work

While testing a web API endpoint with PowerShell's Invoke-WebRequest, I encountered this interesting error message:

The response content cannot be parsed because the Internet Explorer engine is not available, or Internet Explorer's first-launch configuration is not complete. Specify the UseBasicParsing parameter and try again.

Sure enough, supplying -UseBasicParsing made the request work, but the parts of the response object that required Internet Explorer components were expectedly absent. Apparently, this happens because I had never run Internet Explorer on this computer (I used Edge, not IE, once to download Chrome). Launching it, answering its question about security settings, and closing it made Invoke-WebRequest work as normal.

Saturday, September 23, 2017

Checking a phpBB login from a new page

Suppose you want to use a phpBB forum's database of users as an authentication method for some other service. It might be possible to figure out the database format and connect directly, but then you miss out on the automatic tracking of failed logins and checking that the account is enabled. So, you might instead create a new PHP script in the existing phpBB site to take advantage of the phpBB infrastructure:
define('IN_PHPBB', true);
$phpbb_root_path = './';
$phpEx = 'php';
include('common.php');
include('includes/functions_user.php');
include('phpbb/passwords/manager.php');
$provider_collection = $phpbb_container->get('auth.provider_collection');
$provider = $provider_collection->get_provider();
$result = $provider->login($username, $password);
if ($result['status'] === 3) {
 echo 'Login successful.';
} else {
 echo 'Login failed!';
}

The first three lines are important even if they don't immediately appear to do anything - the included phpBB files check them. Also note that if you're getting the username and password to verify from GET or POST parameters, you'll need to extract them into variables before including the phpBB files because phpBB seems to somehow disable superglobals; attempting to use them results in an error page.

Some of the above script is from this forum post.

Friday, September 22, 2017

Notification icons need an icon if they are to appear

While helping this user, I briefly worked with notification icons (NotifyIcon) from PowerShell. It's possible to load the icon image from an ICO file, but this is suboptimal for that user because there weren't any desirable icons in a consistent place on all machines. Omitting the line that sets the Icon property's setting results in no notification at all - apparently there has to be an icon. Fortunately, there is a SystemIcons class that provides a handful of normal system icon objects. Applying one of these makes the notification work and removes the need to keep a loose ICO file around.

Thursday, September 21, 2017

Apparently there can be multiple nameserver sets for a domain

I recently tried to get the Public Commander Keen Forum back to its classic pckf.com domain after one user noticed that the redirect wasn't working. (Background: the previous owner of the forum didn't own the pckf.com domain, so we couldn't get it transferred during the migration, so a redirect page was placed on the old server instead.) I found that the nameservers had been updated to point to my hosting, so I flipped a couple switches to make the forum available at pckf.com. That appeared to work, but intermittently accessing it would go into redirect loops or throw certificate errors. When there were problems, the domain was resolving to the old server. Some investigation with Google's DNS lookup tool revealed that sometimes the old set of nameservers was returned (so the browser went to the old server), but sometimes the new set was provided (so the browser found the right place). Evidently, there's somehow two differing opinions on what the correct list of nameservers is. I'm not sure how exactly that works, but it's causing problems - I'll contact the domain owner to see if we can get it resolved.

Wednesday, September 20, 2017

Converting embedded images in PowerPoint to JPG

One user wanted to know how to convert a bunch of PNG images already embedded in a PowerPoint presentation to JPG so that lossy compression could be used to reduce the file size of the overall presentation. I'm not aware of a way to do that in VBA, but I know that PPTX files (like all modern Office documents) are actually ZIP archives, so I took advantage of that fact to write a script that opens a PPTX, converts all PNG files in /ppt/media to JPG, and puts them back into the archive. Interestingly, PowerPoint doesn't seem to care that the extension doesn't match the image format, so that made the job easier. I also included an optional -Quality parameter that specifies how good the resulting images need to look. The full script can be seen in my answer.

Monday, September 18, 2017

Unplugging extra devices might help the system boot

This morning after getting the main machine partially back up and running, I found that it again declined to boot properly. However, after unplugging both the 3.5mm headphones and the webcam, it passed POST and then came all the way up. It even allowed me to plug the headphones back in without causing a power failure, though I haven't tried the webcam yet. I'm quite sure there are PSU problems, but for now I can limp along by minimizing the power draw at POST time.

The official repair shop on campus apparently only services Apple devices (?), so I'll need to find some other place to get a new PSU acquired and installed.

Sunday, September 17, 2017

Mostly back up and running

Last night, my computer suddenly stopped working. Today I fiddled with it some more, first by removing an old parallel port card that was installed quite a while back in an attempt to get an old printer working. After pulling that out, the system actually made a beep shortly after boot-up, and turned the screen on when I plugged in an HDMI cable! It wanted to run a disk check, so I let it, which only took a moment since it was only concerned about the EFI system partition. With excitement, I shut the machine back down to plug in all the rest of the peripherals, then brought it back up. It failed to boot (spun the disks a bit then reset itself) once or twice, but soon it came up to the logon screen. The keyboard didn't work at all despite Num Lock being lit, so I unplugged an unnecessary peripheral (the webcam) and rebooted. After another boot failure or two, I managed to get logged in. Everything now appears to be normal.

It's unclear how much of the fault lies with the parallel port card, but considering that it never accomplished anything other than blue-screening my computer, I decided to discard it. There are clearly remaining issues, though, which I am pretty certain are with the power supply. Alas, I have neither the tools nor the ability to make a definite diagnosis of which part of the PSU is problematic. For now, I'm trying to avoid strenuous workloads for the machine (no VMs for a while). Hopefully soon I'll be able to take the machine to someone more qualified to double-check that the PSU is indeed the problem and get a new one installed if so.

Sudden failure

Tonight I was firing up a virtual machine when the physical computer suddenly froze one screen, switched to mostly black on the other, power-cycled itself, and refused to boot. The hard drive is active for a little while, then all activity ceases; the monitors report "no signal" and no beeps are emitted. I tried various things for no improvement: rebooting again, holding down the power button with no power connected, inserting a bootable USB, and reseating the RAM.

I'm pretty sure the RAM is fine, since there are no beeps. The hard drives are probably OK as well; even if the OS one had completely died while the system was up, it should have shown a bugcheck upon detection or an error upon rebooting. There does not appear to be any physical damage to any components. Currently I suspect a failed graphics card or CPU. Alas, I have no VGA cable to test the integrated graphics, but the graphical artifacts shown on-screen at the first failure make me suspicious of the GPU. I'm concerned about the CPU because the computer seemed to feel slower as of late, though that might just be my getting used to the speed.

My next thing to try is to gently remove the graphics card to see if the boot process will continue with only the integrated graphics. I won't be able to see anything for lack of an appropriate cable, but I'll be able to tell from the hard drive activity. If the problem persists, the CPU is probably at fault. In any case, I'll be sharper at investigating things in the morning.

Friday, September 15, 2017

Delete slots in the P/Invoke tool

My P/Invoke command-line tool previously had no way to remove or redefine a slot once it was created. There currently isn't much use for that since scripts proceed only directly forward, but eventually I'd like it to be possible to write loops and branches. If there's looping going on, it might be necessary to reallocate a buffer. Also, in interactive mode, it would be nice to be able to redefine a slot with a different type if a mistake was made in creating it. So, I recently added the deleteslot instruction, which removes a given slot from the current workspace and frees the shred of memory used to store its data.

Figured out the EGAHEAD problem

Last time, I found a set of Galaxy graphics files that Abiathar had trouble dealing with. Today I had time to dig a little deeper. It turns out that though the EGAHEAD had real markers until its end, it ended too soon - the last mark was not the end/length of the EGAGRAPH file. The final two foreground tiles' ending points were simply absent. Therefore, there's no conceivable way any tool could be expected to bring that data into existence, so it's not an Abiathar/FleexCore2 bug.

I ran the game and went to the place where I expected the missing tiles to cause problems. To my surprise, there were no display issues! Then I checked with the Tile Property Modifier and found that the last two Keen Dreams tiles (part of the animation cycle for the left edge of the flames), are not actually an animation target of anything, nor are they placed in any level, so they are never called on and their absence has no visible effect.

Wednesday, September 13, 2017

When EGAHEADs end too early

Today I helped someone get a tricky set of files opened with Abiathar. The graphics failed to load, even when using the graphics files specified by the patch file and the correct EGADICT. Some debugging revealed that the search for the next real EGAHEAD entry (to calculate the length of the chunk) was reaching the end of the the marks array without finding a non-placeholder entry. Looking at the EGAHEAD in a hex editor, I'm confused as to why that is, since there are real entries all the way to the end of the file. Perhaps there's something wrong with the optimization intended to reduce the number of chunk decompressions - I will need to investigate further.

Reducing the reported number of foreground tiles made the load work. I don't know whether the game is able to access those last two, but if it is, that's definitely a FleexCore2 problem. I'll have to check.

Sunday, September 10, 2017

Using multiple packages in JavaScript DOSBox

There exists a JavaScript port of DOSBox, suitable for running DOS applications and games in a web browser. The file system is delivered to the client browser as one big file with the filenames and offsets included in the page as a JSON object. I thought it would be neat if the data package could be split into multiple files so that levels could be easily swapped out without needing to duplicate the other files.

That turned to not be super difficult. I think I spent the most time just trying to get the build to work on Windows and then in WSL, but then I decided it would be easier just to work with an existing JS compilation. I wrote my own minimal packager, which was very easy since it just has to bolt one file on after the previous and keep track of where each starts, 31 lines of PowerShell in all. Then I went to work adjusting the loadPackage function and its associates to deal with multiple packages. I just stripped out some unnecessary stuff (mostly the enormous embedded SVG), added a filename parameter to loadPackage, and sprinkled in some PHP to fetch different packages based on the query string.

Sure enough, changing one part of the query string leaves the game the same except for replacing one level, which has its own package.

Print block slots somewhat helpfully

I noticed today that if my P/Invoke command line tool is instructed to print the value of a slot (readslot) that is a custom kind (i.e. defined with newslot block), it spews an error message that's almost certainly 100% incomprehensible and useless to most users. So today, I added a check for block slots in the readslot implementation to mention the length of the slot instead of attempting to marshal and stringify the value. The architecture is not currently set up such that the fields of a block can be printed; the information on each field's kind is not preserved, only the .NET Framework type, so it couldn't tell the difference between some arbitrary pointer-sized field and a string. Nevertheless, not spewing strange errors is an improvement.

Friday, September 8, 2017

More units for the P/Invoke tool

In a handful of places, my P/Invoke command line tool accepts a unit for a size, so allocslot can take a size measured in chars rather than bytes. It might be helpful, though, to measure size using any kind, e.g. when allocating an array. To allow that, I added two keywords to the unit parser function. sizesof takes the name of a kind (e.g. native). This makes chars somewhat unnecessary since sizesof short will work the same, but chars is more memorable and one of the more common expected units, so it's reasonable to have a shortcut. blockssizedlike takes the name of a slot and looks at its kind; this is helpful for working custom structures defined with block.

Tuesday, September 5, 2017

Explorer has trouble copying symlinks across volumes

While testing my answer to this question, I noticed that Explorer's copy/move operation ground to a halt when copying a symbolic link from one drive to another. It pegged one CPU core and wedged itself so severely that I had to terminate the process. This happened multiple times, even when I just moved the symlink without the surrounding directory hierarchy. My workaround was to perform the move of the directory structure using the robocopy tool:

robocopy C:\source\root E:\dest\root /e /move /sl

Monday, September 4, 2017

Controlling "Animate windows when minimizing and maximizing" from script

One user wanted to know how to configure the "Animate windows when minimizing and maximizing" performance setting from the command line. There is a Registry entry that directly represents that checkbox, but tweaking that value doesn't cause a behavior change until after a logon/logoff cycle. The correct way to programmatically adjust the setting is via the SystemParametersInfo function, so this calls for some PowerShell and P/Invoke. (It would be a great opportunity to showcase my P/Invoke command-line tool, but it's not ready for release yet.) The call is made somewhat tricky by the need for a special structure, so jamming the entire thing into one PowerShell run would be unwieldy, but it's fine as a script:
Add-Type -TypeDefinition @"
    using System;
    using System.Runtime.InteropServices;
    [StructLayout(LayoutKind.Sequential)] public struct ANIMATIONINFO {
        public uint cbSize;
        public bool iMinAnimate;
    }
    public class PInvoke { 
        [DllImport("user32.dll")] public static extern bool SystemParametersInfoW(uint uiAction, uint uiParam, ref ANIMATIONINFO pvParam, uint fWinIni);
    }
"@
$animInfo = New-Object ANIMATIONINFO
$animInfo.cbSize = 8
$animInfo.iMinAnimate = $args[0]
[PInvoke]::SystemParametersInfoW(0x49, 0, [ref]$animInfo, 3)

It takes a Boolean value specifying whether to enable window minimize/restore animations.

Sunday, September 3, 2017

Scripts and interactivity in the P/Invoke tool

For some complex operations, it might be unwieldy to place all the necessary P/Invoke instructions in the command line of my tool. It would be preferable to write out such things in an external script file and then simply run that script. Recently, I added a command that does exactly this. The currently executing script is tracked in a stack, so error messages can specify which script file contained the instruction that caused the problem.

Also in complicated scripts, it might be helpful to have an interactive environment to poke around the current execution state. There's now an interactive command that enters interactive mode, in which instructions are read from the console one line at a time and errors are nonfatal (since it would be inconvenient to have to restart the program every time one mistyped a command).

Saturday, September 2, 2017

Adding custom Visual Effects performance options to the Performance Options dialog

The Performance Options dialog (accessible from the Advanced tab of the System Properties dialog) loads the list of visual effects from the Registry, specifically from here:

HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VisualEffects

Each subkey is one option in the dialog. It's possible and fairly simple to add new entries. Most of the default ones use the SPIActionGet and SPIActionSet values to specify the uiAction parameter to SystemParametersInfo. A couple, however, are backed by Registry values, so new checkboxes can be added to control Registry values elsewhere.

These values are necessary to define a Registry-backed checkbox:

  • HKeyRoot, a DWord that specifies the common Registry handle to use as a root. This should probably be 0x80000001 (for HKCU).
  • RegPath, a string specifying the key path under the root hive.
  • ValueName, a string specifying the name of the value in the specified key to control with the setting.
  • CheckedValue, a DWord containing the data to set into the specified value when the box is checked.
  • UncheckedValue, likewise if the box is unchecked.
  • DefaultValue, a DWord with the default data for the backing Registry value if it does not exist.
  • Type, a string set to checkbox.
  • Text, a string holding the display name of the setting. This can be the literal setting title or, if it starts with @, a resource from a DLL.
Configuration for a new setting
The resulting setting
Checking and unchecking that box does indeed set the corresponding Registry value.

Friday, September 1, 2017

Error reporting in the P/Invoke tool

Previously, if my P/Invoke command line tool encountered an error (like bad syntax from the user), the entire program would crash and exit, giving no feedback about what caused the problem other than the exception stack spew to the standard error stream.

In the interest of user-friendly error messages, today I added an exception handler that prints the current instruction number, current instruction text, and exception message when an exception is thrown as a result of processing an instruction. For parse errors, the parser also supplies the fragment currently being parsed (which can be smaller than the current instruction) and prints a caret pointing at the current position within that fragment.

Wacom tablet pen clicking when it shouldn't

Yesterday, the Bamboo tablet that's worked fine for years suddenly developed a critical problem: simply hovering the pen above the tablet causes a click after a second or so. This makes the device basically impossible to use, but fortunately I have a wireless mouse around for back-up. Some research reveals that the issue is probably caused by the pressure sensor in the pen being somehow stuck or out of position. Removing the tip with tweezers and blowing any dust out has worked for other people, so I will try that when I find tweezers or some other instrument that can remove the pen tip.