So, I was looking at that monster thread (Help! Downloaded update now Scrivener won’t load) about how certain fonts caused the startup of Scrivener to fail. My symptoms matched those of WrittenHard (log shows fonts loading, a few “No PostScript name” messages, followed by repeated “RegEnumValue failed” messages).
Following the posts in this thread, I was experimenting to see which fonts might be causing my problem. Turns out, the problem has nothing to do with fonts.
Since I was getting “QSettings: RegEnumValue failed:” in my –log output, I did a google search to find out what code might produce that message. That found me this:
This may not be the exact source file Scrivener is using, but given the (unusual) error string, and the fact that this code has the same problem as Scrivener, I’ll bet it’s close.
In short, childKeysOrGroups() is trying to return a list of all the subkeys of a specified registry key. It does this by calling RegQueryInfoKey to get the number of subkeys, then it performs a loop calling RegEnumKeyEx, passing the loop value as the index number to retrieve. If it encounters a problem, it logs this ‘QSettings’ message.
Because of what appears to be a bug in Windows, this approach for reading subkeys doesn’t work correctly. Put simply, RegQueryInfoKey isn’t consistently returning the correct count of subkeys. It often returns values in the tens of millions, when the correct answer is actually 2 (suggesting Scrivener would start… eventually).
I can see at least 2 different ways to fix this:
- The RegQueryInfoKey function takes a number of parameters for values it can return. If you don’t need a particular value, you can just pass NULL. However for some reason, if you don’t retrieve the value for the 7th parameter (lpcMaxClassLen), the number of subkeys returned is unreliable. Obviously you don’t need to use the returned value, but apparently you must ask for it.
Note: This bug doesn’t affect every key. But clearly it affects HKEY_CURRENT_USER\Software\Classes\CLSID (or more accurately HKEY_CURRENT_USER\Software\Classes\Wow6432Node\CLSID since I am on x64 and Scrivener is a 32bit app), which is one you are using.
- The registry is basically a database, and any application running on the computer might be adding or removing keys at any time. Getting a ‘count’ and then walking ‘count’ keys runs the risk of someone having make a change between the two operations. A (slightly) better approach is simply to keep calling RegEnumKeyEx, incrementing the requested index until ERROR_NO_MORE_ITEMS is returned.
My test code showing the bug in RegQueryInfoKey is available upon request.
PS My next goal is to report this to MS. Wish me luck.