Tag Archives: troubleshooting

This post is a collection of some of the more commonly used command line utilities when doing basic troubleshooting in a Windows domain environment.

To open a command window within a directory from Windows Explorer, hold the Shift key and right-click on the directory, then choose “Open command window here”.

cd

Displays the name of the current directory or changes the current folder.
http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/ntcmds.mspx?mfr=true

Used within a command window to change the current active directory, allowing navigation through the computer’s mapped drives and their directory structures.

Usage:

cd
Displays the current directory path.

cd
Moves to the root of the current drive.

cd /d e:
Moves to the E: drive from another drive. It’s also possible to move to a different drive by typing only the drive letter followed by a colon, ex: D:

cd..
Moves to the parent directory of the current directory (move up one directory toward the root).

cd “People to sue next”
Moves from the current directory into the subdirectory named “People to sue next”. A handy trick is to just type the first few characters of the directory name, and then hit the tab key to auto-complete the rest of the directory name from the first alphabetical match found, and even wrap it in double quotes if it contains spaces. For example, the same command as above can by typed: cd peop <tab>

If the current directory contains multiple matches for the characters typed, hitting tab again will cycle to the next match.

The tab method can be used more than once, to chain together a series of directories. For example, to move to the C:UsersPublicDocuments directory from a command prompt at the root of C:, one can type: cd u <tab> p <tab> d <tab> <tab> <enter>

dir

Displays a list of a directory’s files and subdirectories.
http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/dir.mspx?mfr=true

Usage:

dir
Displays the directories and files in the current directory.

dir /s
Displays the directories and files in the current directory and all sub directories.

Dir can also be used to search for a file, and in many cases it works better than the Windows Explorer search.

dir c:findme.txt /s
Displays a list of all instances of a file named “findme.txt” on the C: drive. It’s also possible to navigate to a location, such as the root of C:, and type: dir /s findme.txt to search that location and all subdirectories for a file named “findme.txt”.

Wildcards are allowed in the form of an asterisk. For example, type: dir c:*.doc /s to search the C: drive for all files with a .doc or .docx extension (I’m not sure why it also locates .docx files, but it does).

Another command line utility for searching for files is where, but the syntax is slightly more complicated.

gpupdate

Refreshes local and Active Directory-based Group Policy settings, including security settings.
http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/refrgp.mspx?mfr=true

After reading about the difference between gupdate and gpupdate /force, I now feel that gupdate is sufficient to reapply group policy nearly all of the time, and the /force switch shouldn’t automatically be used.

Usage:

gpupdate
Reapplies group policy.

gpresult

Displays Group Policy settings and Resultant Set of Policy (RSOP) for a user or a computer.
http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/ntcmds.mspx?mfr=true

Usage:

gpresult /r
Displays RSoP summary data, which includes the last time group policy was applied, from which server group policy was applied, and the groups for which the current user is a member.

gpresult /h gpreport.html
Generates a report of the applied group policy settings and saves it in HTML format as a file named gpreport.html. When generating a report as a user that is not a local administrator, either supply a full path to a valid location for gpreport.html, or navigate to a location (like the Public Documents directory) before running the command, or else the utility may be unable to create the report due to insufficient rights to the current directory.

ipconfig

Displays all current TCP/IP network configuration values and refreshes Dynamic Host Configuration Protocol (DHCP) and Domain Name System (DNS) settings. Used without parameters, ipconfig displays the IP address, subnet mask, and default gateway for all adapters.
http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/ipconfig.mspx?mfr=true

Usage:

ipconfig
Display the computer’s IP address and default gateway, for each network adapter.

ipconfig /all
Displays full TCP/IP information, including the MAC address, DHCP server, and DNS servers, for each network adapter.

net use

Connects a computer to or disconnects a computer from a shared resource, or displays information about computer connections. The command also controls persistent net connections. Used without parameters, net use retrieves a list of network connections.
http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/net_use.mspx?mfr=true

Usage:

net use
Lists all of the computer’s connections (mapped network drives).

net use e: \ComputerNameShareName
Maps the E: drive to the ShareName shared resource on the ComputerName computer. To map the local E: drive to the C: drive (which is a hidden share) of a remote machine named Loomer, type: net use e: \loomerc$

net use e: /delete
Removes the connection currently mapped to the local E: drive.

If you are connecting to a network share that your regular account does not have rights to access, you will be prompted for a username. You will need to also supply the domain, ex: domainusername

nslookup

Displays information that you can use to diagnose Domain Name System (DNS) infrastructure.
http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/nslookup.mspx?mfr=true

Usage:

nslookup <ipaddress or computername>
Queries the local computer’s default DNS name server for information on the specified IP address or computer name. Supply either piece of information and nslookup will return both pieces. It’s also possible to specify a particular DNS name server to be queried, which is useful when troubleshooting whether DNS is propagating/replicating correctly.

ping

Verifies IP-level connectivity to another TCP/IP computer by sending Internet Control Message Protocol (ICMP) Echo Request messages. The receipt of corresponding Echo Reply messages are displayed, along with round-trip times. Ping is the primary TCP/IP command used to troubleshoot connectivity, reachability, and name resolution.

You can use ping to test both the computer name and the IP address of the computer. If pinging the IP address is successful, but pinging the computer name is not, you might have a name resolution problem.
http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/ping.mspx?mfr=true

Usage:

ping <ipaddress or computername>
Makes four attempts to contact the computer at the specified IP Address or with the specified computer name, and reports back whether the machine could be contacted and the time taken for the request to travel to the remote computer, be acknowledged, and the acknowledgement received by the local computer.

ping <ipaddress or computername> -t
Repeatedly attempts to contact the remote computer until interrupted by pressing Ctrl+Break or Ctrl+C. This is sometimes called a persistent ping.

systeminfo

Displays detailed configuration information about a computer and its operating system, including operating system configuration, security information, product ID, and hardware properties, such as RAM, disk space, and network cards.
http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/systeminfo.mspx?mfr=true

The systeminfo command also reveals installed hotfixes and some information about the computer that isn’t readily available in Device Manager or other MMC Snap-ins, such as the BIOS version.

Usage:

systeminfo
Displays information about the local computer.

systeminfo /s computername /u domainuser
Displays information about a remote computer named computername.

systeminfo /s computername | find “System Model:”
Retrieves information about a remote computer named computername, but pipes the output of systeminfo to the find command, which returns only the line containing the string “System Model:”. This output in the command window shows only “System Model:” followed by the model of the remote computer.

The systeminfo report can be sent to a text file, ex: systeminfo > systeminforeport.txt

Bonus commands

getmac

Returns the media access control (MAC) address and list of network protocols associated with each address for all network cards in each computer, either locally or across a network.
http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/getmac.mspx?mfr=true

Usage:

getmac /v
Shows MAC addresses for the local computer.

getmac /s computername /u domainusername /v
Shows MAC addresses for a remote computer named computername while authenticating as a different user.

(Need to test this.)

msg

Sends a message to a user (this may be turned off in many environments). Run msg /? for usage information.

During the development of our Windows 7 image with Office 2010, we began seeing a problem around our users’ Outlook 2010 profiles on the pre-production builds. On occasion, after logging into a machine for the first time, our users would be prompted to choose an Outlook profile upon the first launch of Outlook. Every time the Choose Profile dialog box was presented, it had only a single option in the profile name menu, and that option was always “BACKUP OF Outlook”, where Outlook was our customized profile as configured in a .PRF and applied via the Office OCT.

Background

We were not using .PST files and we were not using Windows Roaming Profiles, but we were using Group Policy logon and logoff scripts to roam certain portions of our user profiles, including the entire registry key at [HKEY_CURRENT_USERSoftwareMicrosoftWindows NTCurrentVersionWindows Messaging SubsystemProfiles]. With 20/20 hindsight, it’s clear that this unwanted behavior was not happening when we logged into a machine for the first time as a brand-new user (ie, while also preventing the logon script from merging the Profiles key from another machine into HKCU before Outlook was opened), but before a pattern had emerged, we considered the problem to be intermittent.

We were building machines using System Center 2012 Configuration Manager and using the Microsoft Office Customization Tool for configuring our .MSP and .PRF files. We were familiar with Active Setup and recognized that Outlook was doing a similar first-run process to set up a profile for what it thought was a new user. When it discovered that an Outlook profile already existed, it created a new profile named “BACKUP OF Outlook” and offered the user a Choose Profile dialog box with this profile as the only choice, presumably because “BACKUP OF Outlook” was not yet set to be the default profile.

Observed symptoms

When the logon script had roamed a user profile from another machine by importing the Profiles key, and before Outlook was launched for the first time, our Profiles key looked similar to this (the snippet has had the juicy bits removed):

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USERSoftwareMicrosoftWindows NTCurrentVersionWindows Messaging SubsystemProfiles]
"DefaultProfile"="Outlook"

[HKEY_CURRENT_USERSoftwareMicrosoftWindows NTCurrentVersionWindows Messaging SubsystemProfilesOutlook]

After Outlook had been launched and the Choose Profile dialog box had been presented, the registry looked similar to this:

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USERSoftwareMicrosoftWindows NTCurrentVersionWindows Messaging SubsystemDeletedProfiles]

[HKEY_CURRENT_USERSoftwareMicrosoftWindows NTCurrentVersionWindows Messaging SubsystemDeletedProfilesOutlook]

[HKEY_CURRENT_USERSoftwareMicrosoftWindows NTCurrentVersionWindows Messaging SubsystemProfiles]

[HKEY_CURRENT_USERSoftwareMicrosoftWindows NTCurrentVersionWindows Messaging SubsystemProfilesOutlook]

[HKEY_CURRENT_USERSoftwareMicrosoftWindows NTCurrentVersionWindows Messaging SubsystemProfilesBACKUP OF Outlook]

The changes we noted were that a new profile named BACKUP OF Outlook had been created, a new DeletedProfiles key had been created, our desired profile had been flagged for deletion via a subkey under DeletedProfiles, and the DefaultProfile string value under the Profiles key that had been pointing to our profile had been deleted.

If we launched Outlook but cancelled out of the Choose Profile dialog box, closed Outlook, and put the Profiles key back to the state before Outlook was launched, we could then relaunch Outlook without issue. It had no objection to using the roamed profile on the second launch or any subsequent launches. The problem might arise if this user roamed the Profile key to yet another machine, but we had not yet identified a pattern or means of reproducing the problem.

Complicating factors

This was happening during a time of rapid development, when the Office OCT was being changed frequently, and machines were hitting the floor with different Office builds. The users logging into these machines were not always aware of all of the changes between builds, and in many cases we were not roaming the user’s profile in an attempt to get a ‘clean’ test of the new build. These factors contributed to the difficulty in establishing a pattern or recognizing commonalities.

A decent amount of time was spent researching problems with Outlook profiles in general, and this research turned up a few forum threads (http://social.technet.microsoft.com/Forums/en-US/outlook/thread/f05c057b-d226-4b7f-bf0d-0406db5acdb1/) that indicated the problem stemmed from the .PRF file. (We also found some mentions of an “undocumented” property named BackupProfile in the .PRF: http://www.slipstick.com/outlook/tips-for-using-outlook-prf-files-to-configure-profiles/ and http://www.slipstick.com/outlook/config/understanding-microsoft-outlook-profile-file-prf/.) We experimented briefly with making changes to the .PRF as hinted at in these threads, but felt that such trial-and-error experimentation was not the best use of our time.

The epiphany

A tip passed along by one of our Kraft Kennedy consultants lead to the break-through.

When 32-bit Office is installed with an .MSP generated by the OCT, a GUID-named key is created under [HKEY_LOCAL_MACHINESOFTWAREWow6432NodeMicrosoftOffice14.0User Settings] that contains a value named Count with a data of 1. For example:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINESOFTWAREWow6432NodeMicrosoftOffice14.0User Settings{75BB133B-F5DD-423C-8321-3BD0B50322A5}]
"Count"="1"

Much like Active Setup, when Outlook launches, it looks for a corresponding key in [HKEY_CURRENT_USERSoftwareMicrosoftOffice14.0User Settings], also with a
value named Count with a data of 1. If the matching key is not found, Outlook does its first-run process, applies the .PRF, and then writes the GUID-named key to HKCU so that the first-run behavior doesn’t happen on that machine again.

In our case, each time we made a change to the OCT and baked up a new OSD image in SCCM, the GUID-named key under HKLM changed. When a user from an old machine roamed to one of these new machines (or when a user initially on a new machine roamed to an older one), the GUID-named keys did not match and the first-run behavior fired off.

The resolution

Now that we better understood what was happening, we could evaluate a few ways to handle the situation. One way was to detect whether the user already had a default profile, and then add the current machine’s HKLM GUID key to her HKCU. Another way was to try to get a better handle on the .PRF and configure it to not create the backup, even when the first-run behavior was triggered. The latter seemed preferable, because we weren’t sure that avoiding the first-run behavior entirely was desirable. We suspected that there might be an advantage to allowing Office’s first-run process to play out, for example, if future changes to the OCT were made that needed to be added to the user’s environment.

After some communication with Microsoft, we made two changes to our .PRF that suppressed the creation of the BACKUP OF profile. The first change was to add BackupProfile=False to the Section 1, General area. The second change was to use UniqueService=Yes in the Section 4, Service1 area.

The corrected .PRF, in part, looks like this:

;Automatically generated PRF file from the Microsoft Office Customization and Installation Wizard

; **************************************************************
; Section 1 - Profile Defaults
; **************************************************************

[General]
Custom=1
ProfileName=Outlook
DefaultProfile=Yes
OverwriteProfile=Yes
ModifyDefaultProfileIfPresent=False
BackupProfile=False

...

;***************************************************************
; Section 4 - Default values for each service.
;***************************************************************

[Service1]
OverwriteExistingService=No
UniqueService=Yes
MailboxName=%UserName%

Some final thoughts

I would note that we are using BackupProfile=False, while many of the forum threads on the subject (incorrectly?) reference the property value as No, as in BackupProfile=No.

This “undocumented” BackupProfile property is actually quite well-documented, and even highlighted as important, in the TechNet article at http://technet.microsoft.com/en-us/library/cc179062.aspx.

A TechNet blog post from August, 2010, at http://blogs.technet.com/b/odsupport/archive/2010/08/06/multiple-exchange-accounts-created-in-outlook-2010-with-existing-outlook-profiles-after-upgrading-from-an-earlier-office-version-using-a-custom-msp.aspx is dedicated to a problem with multiple Exchange accounts that is resolved by making the same two changes to the .PRF. The blog post helpfully points out that the manually edited .PRF file must exist in the same location as the .PRF originally used with the OCT:

NOTE: If Outlook/Exchange settings in the MSP file need to be edited in the future, the custom PRF file created to work around this issue must be copied to the same location as it was when originally imported into the OCT (i.e., C:Custom14.PRF) on the machine that you’re running the Office Customization Tool on when modifying the MSP file.
http://blogs.technet.com/b/odsupport/archive/2010/08/06/multiple-exchange-accounts-created-in-outlook-2010-with-existing-outlook-profiles-after-upgrading-from-an-earlier-office-version-using-a-custom-msp.aspx

The work yet to be done

Without further testing, it remains unclear whether the BackupProfile=False instruction, possibly in combination with other options in the .PRF, causes settings in the .PRF to be merged into the existing Outlook profile, or whether the presence of an existing profile means Outlook just doesn’t do anything with the .PRF.

Customize Outlook profiles by using an Outlook Profile (PRF) file
An existing profile can be either overwritten or updated when a new .prf file is executed. Several settings control how the new settings are applied:

The OverwriteProfile setting can be set to Yes, Append, or No. To update existing profiles, set the value to Append. This preserves the existing profile and updates the sections that have been changed. To overwrite existing profiles with a new profile, set the value to Yes. To prevent overwriting an existing profile, set the value to No.

The ModifyDefaultProfileIfPresent setting can be set to True or False. When set to True, Outlook will modify the default profile even if the new and existing profile names are different.
http://technet.microsoft.com/en-us/library/cc179062.aspx

I would also like to better understand how the GUID-named key gets its name. The TechNet article on the Office Customization Tool in Office 2010 seems to possibly allude to the GUID being a timestamp.

Every time that you save a customization file in the OCT, the tool updates the customization file’s sequencing number with the current computer date and time stamp and generates a new update globally unique identifier (GUID).

http://technet.microsoft.com/en-us/library/cc179097.aspx

As it seems to be the subject of some debate, I want to point out that Microsoft supports applying Setup customization .msp files to existing installations of Office 2010. I suspect, but have not attempted to confirm, that this would generate additional GUID-named keys.

I want the SparkFun VC830L multimeter, to replace a $10, no-name multimeter that I’ve had for a few years (and it still works, but the probes are falling apart).

SparkFun VC830L multimeter

SparkFun VC830L multimeter

This is for all those starving students that need to buy their first good, low-cost multimeter. This meter has really impressive overall feel for being so low-cost. We’ve played with a lot of cheap-o DMMs and found that this unit’s function selector has a great, solid, clicking feel to it. This unit has good continuity (rare for low-cost units), and decent probes.

http://www.sparkfun.com/products/9141

And while I’m at it, I’d also like a GE 50957 GFCI Tester. I’m weird about plugging a multimeter into an outlet in order to test for incorrect wiring.

GE 50957 GFCI Tester

GE 50957 GFCI Tester

I’ve been a fan of the simple and effective Windows 7 USB/DVD Download Tool for quite awhile, and have often used it to create a bootable USB flash drive for installing Windows 7.

But I recently ran into a problem with a flash drive after connecting it to my Xbox 360 and using it to move my profile. The Xbox 360 must have made some change to the MBR on the flash drive that the WUDT didn’t like, because it was unable to format the drive.

The WUDT would begin to format the drive, then report:

We were unable to copy your files. Please check your USB device and the selected ISO file and try again.

Windows 7 had no problems formatting the drive, but something was obviously missing from the process.

A quick search in Google turned up the solution. The formatting done by Windows 7 or the WUDT wasn’t cleaning the MBR and partition table.

To thoroughly format the drive so that it can be used by the WUDT, open an elevated command prompt and enter the following commands, using the drive number of the USB drive reported in list disk for the value of select disk #.

diskpart
list disk
select disk #
clean
create partition primary
select partition 1
active
format quick fs=fat32
assign
exit

For the curious, here’s a more detailed explanation of the clean command:

Removes any and all partition or volume formatting from the disk with focus. On master boot record (MBR) disks, only the MBR partitioning information and hidden sector information are overwritten. On GUID partition table (GPT) disks, the GPT partitioning information, including the Protective MBR, is overwritten; there is no hidden sector information.
http://technet.microsoft.com/en-us/library/cc766465(v=ws.10).aspx

I would expect that the MBR and partition table would need to be cleaned after formatting a drive for booting Mac OS X, too.

Credit: http://4sysops.com/archives/windows-7-usbdvd-download-tool-wudt-is-unable-to-copy-files/

I recently reinstalled Windows 7 and then VM Workstation 7 on a machine that I’d been using as a VMware Workstation host running an XP virtual machine. The VM is named “XP-Office2007″ and it resides on a separate physical hard drive in the machine. Since the reinstall, upon clicking the “Power on this virtual machine” link, VMware returns a cryptic “Internal error.” and fails to start the VM.

VMware Workstation - Internal error.

VMware Workstation - Internal error.

The vmware log in %temp% had the following entries:

Mar 01 09:28:46.750: vmui| CVMUIStatusVM::OnPowerVM clicked
Mar 01 09:28:46.920: vmui-1176| /vm/#6f7088f493f32788/: VMHSVMCbPower: Setting state of VM to powerOn with option hard
Mar 01 09:28:46.921: vmui-1176| VMHSGetVMX failed: Empty vmxFilePath
Mar 01 09:28:46.921: vmui-1176| VMHSLaunchVM failed: VMDB failure
Mar 01 09:28:46.957: vmui| Internal VMDB error: VMDB failure
Mar 01 09:28:46.957: vmui| Internal error.
Mar 01 09:28:46.957: vmui| VMDlg::ShowDialog: Internal error.

Of course, I immediately started Googling these errors and failure messages, but found very little. At least one page indicated that a similar sounding problem wasn’t resolved by re-installing VMware. I like to think I’m pretty decent with VMware, so I decided I’d roll up my sleeves, dig into the VM, and try to figure it out.

Trying to get lightning to strike twice, I tried my old standby fix of editing the name of the hard drive in the *.vmx file. Instead of pointing the IDE drive to the “XP-Office2007-000001.vmdk” file, I moved that file out of my VM directory and then changed the ide0:0.fileName value to point to the older *.vmdk file, named “XP-Office2007.vmdk”. The IDE lines now looked like this:

ide0:0.present = "TRUE"
ide0:0.fileName = "XP-Office2007.vmdk"
ide1:0.present = "TRUE"
ide1:0.fileName = "E:"

When the machine was powered on, it still failed, but with a different and more descriptive error:

VMware Workstation - Unable to open file

VMware Workstation - Unable to open file

VMware Workstation
Unable to open file “D:VMwareVirtual MachinesXP-Office2007XP-Office2007.vmdk”: One of the disks in this virtual machine is already in use by a virtual machine or by a snapshot.

The more verbose message from the vmware log in %temp% read:

Mar 01 10:31:22.814: vmui| CVMUIStatusVM::OnPowerVM clicked
Mar 01 10:31:23.016: vmui-3992| SNAPSHOT: SnapshotDiskTreeAddFromSnapshot: Trying to add snapshot XP-Office2007-Snapshot2.vmsn to disk D:VMwareVirtual MachinesXP-Office2007XP-Office2007.vmdk which already has snapshot currentState.
Mar 01 10:31:23.016: vmui-3992| Cannot open D:VMwareVirtual MachinesXP-Office2007XP-Office2007.vmdk of type disk: One of the disks in this virtual machine is already in use by a virtual machine or by a snapshot.
Mar 01 10:31:23.016: vmui-3992| Cmd /vm/#6f7088f493f32788/cmd/##94/op/checkMissingFiles/ failed: Unable to open file "D:VMwareVirtual MachinesXP-Office2007XP-Office2007.vmdk": One of the disks in this virtual machine is already in use by a virtual machine or by a snapshot.
Mar 01 10:31:23.016: vmui| Unable to open file "D:VMwareVirtual MachinesXP-Office2007XP-Office2007.vmdk": One of the disks in this virtual machine is already in use by a virtual machine or by a snapshot.
Mar 01 10:31:23.016: vmui| VMDlg::ShowDialog: Unable to open file "D:VMwareVirtual MachinesXP-Office2007XP-Office2007.vmdk": One of the disks in this virtual machine is already in use by a virtual machine or by a snapshot.

I copied only the *.vmx and *.vmdk files into a new folder and tried to launch the *vmx as a new VM, but got the Internal error message again. This was something of a relief, as it suggested that the problem wasn’t with the VM itself.

I tried to create a new, empty virtual machine using the New Virtual Machine Wizard, but the process didn’t complete. After setting up the basic machine, I clicked the Finish button in the wizard, but the window did not close. The *.vmx and *.vmdk files were created, however. When I closed the window with the red X and tried to power on the VM, I got the same Internal error message.

I found a VMware community article suggesting that I needed to run Windows Updates on the host. This seemed logical, as perhaps the old host had more recent updates, but I found that the current host was up to date.

As I was running out of ideas, I decided that maybe re-installing Workstation was worth a shot, so I first checked in SCCM Software Center and found it had a Failed status. I then looked in Windows Programs and Features and found it wasn’t listed at all.

I reinstalled Workstation from Software Center and lo and behold, the VMs powered up normally. If I’d just kept my self-confidence in check, I would probably have gotten around to verifying the install much sooner.

7:21 PM 2/26/2012

I recently ran the spider at www.xml-sitemaps.com against www.ardamis.com and it returned a list of URLs that included a few pages with some suspicious-looking parameters. This is the second time I’ve come across these URLs, so I decided to document what was going on. The first time, I just cleared the cache, spidered the site to preload the cache, and confirmed that the spider didn’t encounter the pages. And then I forgot all about it. But now I’m mad.

Normally, a URL list for a WordPress site includes the various pages of the site, like so:


http://www.ardamis.com/


http://www.ardamis.com/page/2/


http://www.ardamis.com/page/3/

But in the suspicious URL list, there are additional URLs for the pages directly off of the site’s root.


http://www.ardamis.com/


http://www.ardamis.com/?option=com_google&controller=..%2F%2F..%2F%2F..%2F%2F..%2F%2F..%2F%2F..%2F%2F..%2F%2F..%2F%2F%2Fproc%2Fself%2Fenviron%0000


http://www.ardamis.com/page/2/


http://www.ardamis.com/page/2/?option=com_google&controller=..%2F%2F..%2F%2F..%2F%2F..%2F%2F..%2F%2F..%2F%2F..%2F%2F..%2F%2F%2Fproc%2Fself%2Fenviron%0000


http://www.ardamis.com/page/3/


http://www.ardamis.com/page/3/?option=com_google&controller=..%2F%2F..%2F%2F..%2F%2F..%2F%2F..%2F%2F..%2F%2F..%2F%2F..%2F%2F%2Fproc%2Fself%2Fenviron%0000

This occurs only for the pagination of the main site’s pages. I did not find URLs containing the parameter ?option=com_google&controller= for any pages that exist under a category or tag, but that also use the /page/2/ convention.

The parameter is the urlencoded version of the text:

?option=com_google&controller=..//..//..//..//..//..//..//..///proc/self/environ00

Exploration

I compared the source code of the pages at the clean URLs vs that of the pages at the bad URLs and found that there was a difference in the pagination code generated by the WP-Paginate plugin.

The good pages had normal-looking pagination links.

<div class="navigation">
<ol class="wp-paginate">
<li><span class="title">Navigation:</span></li>
<li><a href="http://www.ardamis.com/page/2/" class="prev">&laquo;</a></li>
<li><a href='http://www.ardamis.com/' title='1' class='page'>1</a></li>
<li><a href='http://www.ardamis.com/page/2/' title='2' class='page'>2</a></li>
<li><span class='page current'>3</span></li>
<li><a href='http://www.ardamis.com/page/4/' title='4' class='page'>4</a></li>
<li><a href='http://www.ardamis.com/page/5/' title='5' class='page'>5</a></li>
<li><a href='http://www.ardamis.com/page/6/' title='6' class='page'>6</a></li>
<li><a href='http://www.ardamis.com/page/7/' title='7' class='page'>7</a></li>
<li><span class='gap'>...</span></li>
<li><a href='http://www.ardamis.com/page/17/' title='17' class='page'>17</a></li>
<li><a href="http://www.ardamis.com/page/4/" class="next">&raquo;</a></li>
</ol>
</div>    

The bad pages had the suspicious URLs, but were otherwise identical. Other than the URLs in the navigation, there was nothing alarming about the HTML on the bad pages.

I downloaded the entire site and ran a malware scan against the files, which turned up nothing. I also did some full-text searching of the files for the usual base64 decode eval type stuff, but nothing was found. I searched through the tables in my database, but didn’t see any instances of com_google or proc or environ that I could connect to the suspicious URLs.

Google it

Google has turned up a few good links about this problem, including:

  1. http://www.exploitsdownload.com/search/com_/36 – AntiSecurity/Joomla Component Contact Us Google Map com_google Local File Inclusion Vulnerability
  2. http://forums.oscommerce.com/topic/369813-silly-hacker/ – “On a poorly-secured LAMP stack, that would read out your server’s environment variables. That is one step in a process that would grant the hacker root access to your box. Be thankful it’s not working. Hacker is a bad term for this. This is more on the Script Kiddie level.”

    The poster also provided a few lines of code for blocking these URLs in an .htaccess file.

    # Block another hacker
    RewriteCond %{QUERY_STRING} ^(.*)/self/(.*)$ [NC]
    RewriteRule ^.* - [F]
    
  3. http://forums.oscommerce.com/topic/369813-silly-hacker/ – “This was trying for Local File Inclusion vulnerabilities via the Joomla/Mambo script.”
  4. http://core.trac.wordpress.org/ticket/14556 – a bug ticket submitted to WordPress over a year earlier identifying a security hole if the function that generates the pagination isn’t wrapped in a url_esc function that sanitizes the URL. WP-Paginate’s author submits a comment to the thread, and the plugin does use url_esc.

So, what would evidence of an old Joomla exploit be doing on my WordPress site? And what is happening within the WP-Paginate plugin to cause these parameters to appear?

Plugins

It seemed prudent to take a closer look at two of the plugins used on the site.

Ardamis uses the WP-Paginate plugin. The business of generating the /page/2/, /page/3/ URLs is a native WordPress function, so it’s strange to see how those URLs become subject to some sort of injection by way of the WP-Paginate plugin. I tried passing a nonsense parameter in a URL (http://www.ardamis.com/page/3/?foobar) and confirmed that the navigation links created by WP-Paginate contained that ?foobar parameter within each link. This happens on category pages, too. This behavior of adding any parameters passed in the URL to the links it is writing into the page, even if they are urlencoded, is certainly unsettling.

The site also uses the WP Super Cache plugin. While this plugin seems to have been acting up lately, in that it’s not reliably preloading the cache, I can’t make a connection between it and the problem. I also downloaded the cache folder and didn’t see cached copies of these URLs. I turned off caching in WP Super Cache but left the plugin activated, cleared the cache, and then sent the spider against the site again. This time, the URL list didn’t contain any of the bad URLs. Otherwise, the lists were identical. I re-enabled the plugin, attempted to preload the cache (it got through about 70 pages and then stopped), and then ran a few spiders against the site to finish up the preloading. I generated another URL list and the bad URLs didn’t appear in it, either.

A simple fix for the WP-Paginate behavior

The unwanted behavior of the WP-Paginate plugin can be corrected by changing a few lines of code to strip off the GET parameters from the URL. The lines to be changed all reference the function get_pagenum_link. I’m wrapping that function in the string tokenizing function strtok to strip the question mark and everything that follows.

The relevant snippets of the plugin are below.

			
$prevlink = ($this->type === 'posts')
? esc_url(strtok(get_pagenum_link($page - 1), '?'))
: get_comments_pagenum_link($page - 1);
$nextlink = ($this->type === 'posts')
? esc_url(strtok(get_pagenum_link($page + 1), '?'))
: get_comments_pagenum_link($page + 1);
			
function paginate_loop($start, $max, $page = 0) {
    $output = "";
    for ($i = $start; $i <= $max; $i++) {
        $p = ($this->type === 'posts') ? esc_url(strtok(get_pagenum_link($i), '?')) : get_comments_pagenum_link($i);
        $output .= ($page == intval($i))
        ? "<li><span class='page current'>$i</span></li>"
        : "<li><a href='$p' title='$i' class='page'>$i</a></li>";
    }
    return $output;
}

Once these changes are made, WP-Paginate will no longer insert any passed GET parameters into the links it’s writing into that page.

Bandaid

The change to the WP-Paginate plugin is what we tend to call a bandaid – it doesn’t fix the problem, it just suppresses the symptom.

I’ve found that once the site picks up the bad URLs, they can be temporarily cleaned by clearing the cache and then using a spider to recreate it. The only thing left to do is determine where they are coming from in the first place.

The facts

Let’s pause to review the facts.

  1. The http://www.xml-sitemaps.com spider sent against http://www.ardamis.com discovers pages with odd parameters that shouldn’t be naturally occurring on the pages
  2. The behavior of the WP-Paginate plugin is to accept any parameters passed and tack them onto the URLs it is generating
  3. Deleting the cached pages created by WP Super Cache and respidering produces a clean list – the bad URLs are absent

So how is the spider finding pages with these bad URLs? How are they first getting added to a page on the site? It would seem likely that they are originating only on the home page, and the absence of the parameters on other pages that use pagination seems to support that theory.

An unsatisfying ending

Well, the day is over. I’ve added my updated WP-Paginate plugin to the site, so hopefully Ardamis has seen the last of the problem, but I’m deeply unsatisfied that I haven’t been able to get to the root cause. I’ve scoured the site and the database, and I can’t find any evidence of the URLs anywhere. If the bad URLs come back again, I’ll not be so quick to clean up the damage, and will instead try to preserve it long enough to make a determination as to their origin.

Update 07 April 2012: It’s happened again. When I spider the site, two pages have the com_google URL. These page have the code appended to the end of the URL created by the WordPress function cancel_comment_reply_link(). This function generates the anchor link in the comments area with an ID of cancel-comment-reply-link. This time, though, I see the hijacked URL used in the link even when I visit the clean URL of the page.

This code is somehow getting onto the site in such a way that it only shows up in the WP Super Cache’d pages. Clearing the cache and revisiting the page returns a clean page. My suspicion is that someone is visiting my pages with the com_google code as part of the URL. WordPress puts the code into a self-referencing link in the comment area. WP Super Cache then updates the cache with this page. I don’t think WordPress can help but work this way with nested comments, but WP Super Cache should know better than to create a cached page from anything but the content from the server.

In the end, because I wasn’t using nested comments to begin with, I chose to remove the block of code that was inserting the link from my theme’s comments.php file.

    <div class="cancel_comment_reply">
        <small><?php cancel_comment_reply_link(); ?></small>
    </div>

I expect that this will be the last time I find this type of exploit on ardamis.com, as I don’t think there is any other mechanism that will echo out on the page the contents of a parameter passed in the URL.

I’m in the middle of troubleshooting a printing problem that has arisen with our in-development Windows 7 image. We’re running 64-bit Windows 7 Enterprise with Office 2010 and using the HP Universal Print Driver for Windows PCL6 version 5.4.0 dated 1 Dec 2011 (the current version). The printer driver is installed on a Windows server using default settings and the printer connections on the workstations are created either as per-machine connections by running printui.exe /ga or as per-user connections by running the Find Printers wizard in an Office application. The printers themselves are HP 4250n and HP P4015 models with relatively up-to-date firmware.

The problem is that certain print jobs produce many pages of apparent gibberish instead of the intended file or email message. The gibberish pages begin like this:

"
 @PJL SET JOBATTR="JobAcct8=USERNAME"
                                     @PJL SET JOBATTR="JobAcct9="
                                                                 @PJL SET RET=OFF

I’ve done some research into the lines beginning @PJL, and my understanding is that PJL (Printer Job Language) commands are part of the standard job header output from the Universal Printer Driver, and that when everything is working normally, they are processed by the printer as instructions instead of printed as text.

For more reading about PJL commands, I can recommend the page at: http://www.sxlist.com/techref/language/pcl/lj1686.htm

Almost immediately, I was able to rule out the per-machine connections as being the cause, as the problem also occurred on per-user connections. The same files that printed problematically to the networked HP printers printed normally to locally-installed printers using non-UPD PCL 6 drivers. It seemed logical to pursue this as a driver-related problem.

What is PCL 6

It’s probably worth pausing here for a bit of explanation of PCL 6.

The Enhanced PCL XL or PCL6 driver that is included with the HP LaserJet printers provides enhanced WYSIWYG and enhanced performance with application support over the Standard (PCL5e) driver. PCL XL is a new page description language by HP that is part of PCL6 and is closer to GDI, which many applications use. Less translation takes place by the driver, which means increased WYSIWYG capabilities and better performance with applications that support escapes implemented by the Enhanced driver. The output from the Enhanced (PCL XL) driver may not be the same as the output from the Standard driver. If the output is not as expected, choose the Standard (PCL5e) driver instead.
What is the Enhanced PCL XL or PCL6 Driver?

The part that catches my eye is “better performance with applications that support escapes implemented by the Enhanced driver”. Are we encountering applications that do not support escapes?

Eliminating possible causes

Possible causes of the PJL commands being output as text include the driver not prefixing the PJL statements (at the beginning of each job) with a Universal Exit Language (UEL) escape sequence. (http://www.tek-tips.com/viewthread.cfm?qid=1618494)

To rule this out, one can use the “print to file” option in the print dialog box to produce a file that contains the instructions that would be sent to the printer.

Choose File | Print in your application, then check the “Print to file” box in the print dialog box. (In Office 2010, the Print Options button under the available printers menu displays the print dialog box.) Choose a name for the .prn file and save it somewhere, then open the resultant *.prn file in something that displays escape characters, such as Notepad++ (or even Notepad). The first character should be an escape character, and the first line of text will begin something like this:

{ESC}%-12345X

If the PJL initialization command looks correct, it’s possible that the printer is not properly configured to accept PJL commands. Older printers may not be PJL-aware, but I knew our printers to work fine with older 32-bit HP UPDs installed on our Windows XP machines. The ‘Personality’ attribute on HP printers can be checked by going to the printer’s web admin panel and browsing to Settings | Configure Device | System Setup. Setting the Personality to PS is probably going to cause problems, but either Auto or PCL should work. I confirmed that our printers were set to Auto, further ruling out the printers themselves as the cause of the problem.

I next looked at disabling the advanced features of the driver (a little skeptically, I’ll admit). This can be done by going into the printer’s properties and unchecking the “Enable advanced printing features” box on the Advanced tab. (http://h30499.www3.hp.com/t5/Print-Servers-Network-Storage/12345X-PJL-Printing-on-Dot-Matrix-Printers/td-p/1132391) I was curious about how this affected the job sent to the printer – would the entire series of JPL commands be removed?

To test, I unchecked the “Enable advanced printing features” and printed an email message to a *.prn file, then checked the box and printed the same email to a second *.prn file, then compared the two files. The only difference in the PJL commands was that “@PJL SET SEPARATORPAGE=OFF” was present with advanced printing features enabled, and absent with advanced printing features disabled.

I found the separator page line to be an interesting difference, as banner pages/separator pages had been suggested as a possible cause, but our drivers were not configured to print separator pages. (http://www.oasq.com/PJL-SET-JOBATTR-thread-252568-1-1.html)

So, that’s where the issue currently stands. I’m waiting to see if turning off advanced printing features has any effect. To be thorough, I need to test whether the UPD PS driver prints without error and whether the problem continues with a printer connected via TCP/IP and with a manually installed driver. I can also bring the printers up to the latest version of the firmware, although this would be a less satisfactory resolution, as we have a variety of printer models and not all of them have firmware updates available.

Update 17 Feb. 2012

The Application event log on the print server contains a number of errors, though we’re unsure of whether there is a direct correlation between the errors and attempts by Windows 7 users to print, or jobs in the spooler being processed, or any other activity.

Description:
Faulting application name: PrintIsolationHost.exe, version: 6.1.7600.16385, time stamp: 0x4a5bd3b1
Faulting module name: hpzuiwn7.dll, version: 0.3.7071.0, time stamp: 0x4a5bdfcb
Exception code: 0xc0000005
Fault offset: 0x00000000000d6971
Faulting process id: 0x900
Faulting application start time: 0x01ccea9860e17377
Faulting application path: C:Windowssystem32PrintIsolationHost.exe
Faulting module path: C:Windowssystem32spoolDRIVERSx643hpzuiwn7.dll
Report Id: 3eaa21e6-568c-11e1-b7a4-005056a50027

It certainly does look like the 64-bit HP driver is at fault here. More searching has turned up a number of reports of this error with HP’s UPD PCL6 driver, going back to 2010.

Because we have a small number of Windows 7 users, we’re removing the network printers from the Windows 7 machines temporarily, to see if the server stabilizes.

Update 21 Feb. 2012

We were able to take a closer look at the print server today. We searched the registry for hpzuiwn7.dll and noted the printers that had this DLL listed among the supporting files. Many, but not all, of the printers included this DLL. We also reviewed the printers in Print Management and made an odd discovery. There seemed to be two varieties of the model-specific PCL 6 driver in use: one is named “HP LaserJet 4250 PCL 6” and the other is “HP LaserJet 4250 PCL6“. The difference in the naming is that the later driver has a space between PCL 6. While most of the printers used the UPD, a handful were using one of the model-specific drivers. When we looked at the Additional Drivers, we found that one of them had only the 64-bit version available. I expect that only 32-bit workstations are printing to those printers, so I’m not sure how they even functioned, but it would seem that the next step would be to either add the matching 32-bit drivers for that model printer or change the assigned driver to UPD PCL 6. I suspect that we were not diligent enough about exactly matching the printer driver names (let alone the version numbers) when we were installing drivers on the server.

Update 1 Mar. 2012

After installing the missing 32-bit driver that complemented the stray 64-bit driver, all of the printing problems, including the error messages in the Application log on the server, have subsided.

In Windows, the Num Lock key state (on or off) can be set in the registry. It can be set in either of two locations, depending on when you wish to set the state, or both, if you want to force the state at boot and change it after the user logs in.

The Num Lock key state after logon can be set as a registry value for the current user in the key HKEY_CURRENT_USERControl PanelKeyboard. To set the state of the Num Lock key before logon (the key state will be set before the Ctrl+Alt+Del screen), change the registry value in the key HKEY_USERS.DefaultControl PanelKeyboard. For both keys, the data for the InitialKeyboardIndicators value determines the state of the NumLock key. There are three possible settings.

0 = Num Lock is turned OFF after/at logon.
1 = Disable Num Lock.
2 = Num Lock is turned ON after/at logon.

A registry merge file that sets Num Lock on for the current user after logon is below.

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USERControl PanelKeyboard]
"InitialKeyboardIndicators"="2"

It’s also (typically) possible to configure the Num Lock key state in the BIOS, although I personally don’t see the advantage of setting in the BIOS something that is configurable in Windows.

Note that users of full-sized keyboards with distinct Num keypads generally prefer to have the Num Lock key enabled and laptop users typically have Num Lock disabled. Much like the Function key is used to change the behavior of certain laptop keys, laptop keyboards without dedicated Num keypads map numbers to regular character keys. This could potentially cause some confusion, when users begin hitting the letter keys and get numbers instead.

Autonegotiation

Network autonegotiation is easily misunderstood. Consider two 10/100Mb devices attached to one another – a PC connected to a router. For each of these devices, it’s possible to configure the connection to use either 1) a fixed speed and duplex or 2) to negotiate the optimal shared speed and duplex with whatever it is connecting to. What is not intuitive is that both devices must be configured with the same settings. The connection will suffer a performance hit, or may not work at all, if the two devices are configured differently.

A common misconception about autonegotiation is that it is possible to manually configure one link partner for 100 Mbps full-duplex and autonegotiate to full-duplex with the other link partner. In fact, an attempt to do this results in a duplex mismatch. This is a consequence of one link partner autonegotiating, not seeing any autonegotiation parameters from the other link partner, and defaulting to half-duplex.

http://www.cisco.com/en/US/products/hw/switches/ps4324/products_tech_note09186a0080094713.shtml#auto_neg

If both devices are configured to autonegotiate speed and duplex, then each will attempt to make the best possible connection among the possibilities they have in common. However, if one of the devices is set to use a fixed speed and duplex and the other device is set to autonegotiate, the autonegotiating device can determine the speed but not the duplex of the other device and so falls back to its default duplex mode. In the case of Cisco switches, the default duplex mode is half-duplex.

…it is possible for a[n autonegotiating] link partner to detect the speed at which the other link partner operates, even though the other link partner is not configured for auto-negotiation. In order to detect the speed, the link partner senses the type of electrical signal that arrives and sees if it is 10 Mb or 100 Mb.

It is not possible to detect the correct duplex mode in the same method that the correct speed can be detected. In this case, the [...] port of [the autonegotiating] switch [...] is forced to select the default duplex mode. On Catalyst Ethernet ports, the default mode is auto-negotiate. If auto-negotiation fails, the default mode is half-duplex.

http://www.cisco.com/en/US/tech/tk389/tk214/technologies_tech_note09186a0080094781.shtml

Half-duplex as a default duplex mode is not unique to Cisco switches. Below is a link to an article on www.dell.com written by Rich Hernandez, a senior engineer with the Server Networking and Communications Group at Dell, that contains a table summarizing “all possible combinations of speed and duplex settings, both on 10/100/1000-capable switch ports and on NICs.” Included are combinations that would yield no link or link fail conditions, as well as combinations that would yield a duplex mismatch.

http://www.dell.com/content/topics/global.aspx/power/en/ps1q01_hernan?c=us&cs=555&l=en&s=biz

The importance of using identical settings on both sides of a network connection is stressed in a KB article from www.symantec.com with information on how an autonegotiating port may report that it has established a full-duplex connection with a NIC configured for 100MBs/Full, but in fact is communicating at less than expected capacity.

Only by explicitly setting both sides of the link to the same duplex mode would the link work flawlessly.

http://www.symantec.com/business/support/index?page=content&id=TECH87827

Understanding link data errors

The page at the link below contains two tables that explain the various errors and counters logged by a network switch and the possible causes.

http://www.cisco.com/en/US/products/hw/switches/ps708/products_tech_note09186a00800a7af0.shtml#ustand

Troubleshooting Ethernet Collisions

Collisions may appear to indicate communication problems with a network connection, but as a technote from cisco.com states, collision counters alone are not indicative of network problems.

…collisions are a way to distribute the traffic load over time by arbitrating access to the shared medium. Collisions are not bad; they are essential to correct Ethernet operation.

There is no set limit for “how many collisions are bad” or a maximum collision rate.

In conclusion, the collisions counter does not provide a very useful statistic to analyze network performance or problems.

http://www.cisco.com/en/US/products/hw/modules/ps2033/products_tech_note09186a008009446d.shtml

Late Collisions

When a collision is detected by a station after it has sent the 512th bit of its frame, it is counted as a late collision.

The station that reports the late collision merely indicates the problem; it is generally not the cause of the problem. Possible causes are usually incorrect cabling or a non-compliant number of hubs in the network. Bad network interface cards (NICs) can also cause late collisions.

http://www.cisco.com/en/US/products/hw/modules/ps2033/products_tech_note09186a008009446d.shtml

I have a Windows XP guest running in VMWare Workstation 7 on a Windows 7 Ultimate host machine. This is working pretty well. The XP guest is nice and responsive. I have only one gripe. I’d like all of the buttons on my Logitech MX510 (the best mouse ever) to be mappable in the guest.

Starting from square one, I decided to try installing the current version of SetPoint in the guest OS. The installation went fine, but the usual functionality of the SetPoint settings utility was absent.

SetPoint Settings in an XP virtual machine

SetPoint Settings in an XP virtual machine

As shown in the screenshot, the SetPoint Settings utility displays only the Tools tab. It is missing the My Mouse tab (and if a keyboard were installed, I presume it would be missing the Keyboard tab, too).

After some Googling around, it appears to be a due to the way VMware approximates the physical mouse. VMware seems to treat USB mice connected to the host as PS/2 devices in the guest. SetPoint, then, doesn’t detect any Logitech hardware that it can configure.

The question of how to obtain SetPoint functionality in virtual machines is one that has been asked many, many times before, without a satisfactory answer. More on that in a little bit.

The best work around

Thankfully, it seems that, at least in the case of a Windows host and a Windows guest, installing SetPoint inside the virtual machine is not necessary. Installing it on the host seems to make all of the functionality available in the guest. This is the solution that I’m implementing now, and it is what I would recommend, provided you have rights to install software on the host.

Paths to follow if you want to pursue installing SetPoint inside a VMware virtual machine

I applaud your courage. There are a few settings that can be tweaked that may get you closer to a working installation.

Possible setting number one

From the post at http://coreygilmore.com/blog/2008/04/30/better-multi-button-mouse-support-with-vmware-fusion-and-workstation/

Add the following line to the virtual machine’s .vmx file:

mouse.vusb.enable = "TRUE"

From what I can tell, this setting allows me to use the Forward and Back buttons on the mouse, but does not make the mouse detectable by SetPoint. The remaining mouse buttons do nothing.

Possible setting number two

From the post at http://superuser.com/questions/35830/back-forward-mouse-buttons-do-not-work-in-vmware-workstation-6-5-guest-os/304583#304583

The solution given (which did not work for me) is to:

First add the following line to the virtual machine’s .vmx file:

usb.generic.allowHID = "TRUE"

An explanation of what this does, by a VMware associate, can be found in the thread at http://communities.vmware.com/thread/110919?start=15&tstart=0

If you’re feeling really adventurous and/or desperate, you can take out the mouse.vusb.enable line and add this option instead:

usb.generic.allowHID = “TRUE”

Then, you’ll notice that your main mouse and keyboard (if they are USB) are available to pass through into the guest via the USB devices menu.

The dangerous part here is that once you pass through the mouse, it is actually disconnected from the host, so you won’t be able to ungrab from the guest just by mousing out of the Fusion window. You can still ungrab with the keyboard (ctrl-cmd I believe is the shortcut?). If you actually pass through your keyboard and your mouse, you’ll be stuck in the guest and you’ll have to shut it down (or worse, reboot your physical machine).

This sounded like a great idea, and I was willing to set up a second, PS/2 mouse to control just the host, if necessary. Without connecting a second mouse, I tried passing the Logitech mouse as a USB device to the VM, just as I would an external hard drive, but VMware prevented this, with a warning message:

[Machine Name] – VMware Workstation
Cannot connect “Logitech USB-PS/2 Optical Mouse” to this virtual machine. The host requires this device for input.
[OK]

The second step would have been to go into Device Manager, click Actions, and then choose “Scan for hardware changes”.

I didn’t get to the second step, as I was too lazy to track down a PS/2 mouse to keep attached to the host, and I still wanted to find a software solution. I suspect, though, that this would be were to begin, were I to need to get SetPoint running in the guest OS.

Summary

While I wasn’t able to figure out how to install SetPoint on a guest OS, the workaround of installing SetPoint on the host OS seems to accomplish my goal.