Firstly, it’s cool that they are there. Rather than having to do something surreal involving runas, explorer and a couple of other things to allow you to run an application at a privileged level you now encounter the ubiquitous shield icon, which tells you that to perform this operation you need to acquire the appropriate privileges. It’s a lot like the linux sudo, except by default you just have to click the ‘continue’ prompt instead of a password.
Pretty cool, even if you’re an administrative user, you don’t start with all the privileges that your group memberships provide.
Here comes the rub – I’ve stopped reading the prompts, I just find the one that tells me how to get to the next step and click on it. I’m not positive, but I think this is probably par for the course for other users as well.
Shame that, nice idea, but hamstrung by having too many things need administrative privileges.
ID3 tag type was the issue with Media Player 11
When I converted the id3 tags to v2.3 all the album art went to the correct format. Interesting issue that. By noting it here I hope that it will help someone else. iTunes has been great for this as it can convert between various tag types (from v1.1 through). I’ve shoved my collection to version 2.3 tags, and it seems to have solved the problem with the screwed up album art.
Let’s see, a bulk change of many thousands of tracks should take all night.
Windows media player 11 – album art
Interesting thing that Windows Media Player 11 does to the artwork on albums you possess is to place them in a cache directory under %USERPROFILE%\Local Settings\Application Data\Microsoft\Media Player\Art Cache\LocalMLS. Each one is names after a guid, which is probably generated for each track in the collection.
I’m just wondering how difficult it would have been to use a hash of the image data as it’s file name, and storing the hash in the media library instead of the pointer to the guid. This way when you have duplicate images (typically 10 per album), they are not replicated into the cache of images.
The other complaint is that I’ve got a bunch of black album art images. It’s completely odd, as they seem to be completely ok inside in the file – other tools have no difficulty in examining them, and show correct icons. Maybe I should feed this back to them – after all it’s a beta of media player 11.
Disabling that PC speaker beep once and for all
For some reason the ^G character is not performing a ‘default system sound’ when it happens. No idea why, probably a misconfiguration on my behalf. It makes using a console very annoying – for example every exception on vmware produces an annoying beep when anything wrong happens.
The solution is in, of all places, the MSDN reference for Beep(), which states in small print to type: net stop beep followed by sc config beep start= disabled
Reenabling it involves typing: sc config beep start= system followed by net start beep
I hope you found this as useful as I did.
Waiting for Vista
It’s my own limited homage to Samuel Beckett. 🙂
Direct3D 10 (AKA DirectX 10) is a Vista only item. Considering the driver model changes for Vista I can see how you would have a problem shoehorning the API back into XP. The problem is that they keep delaying the release for various reasons meaning that the games keep being delayed. The longer you delay the OS the later it will be adopted. I’m not planning on an upgrade until I’ve heard a reasonable amount of feedback as I can’t afford to waste time troubleshooting problems. Considering that everything native I’m developing has to be backwards compatible with Windows 2000, my upgrade path has been restricted somewhat.
The new toy has the dreaded ‘Windows Vista Capable‘, which is a tad suspicious.
You don’t need Administrator access for that
I encountered a real dunderhead of a program. It claims to be completely NT, 2K and XP happy, yet it doesn’t tell us it needs administrator access because it creates it’s temp files in C:\, yes, the root of the C drive. There is a perfectly good API available for making good, clean temp files – it’s called GetTempFileName. for a bonus there’s GetTempPath, which gets you a directory for creating temp files, and this directory stands a really good chance of being user isolated (being that it’s %USERPROFILE%\Local Settings\Temp on most NT based OSes). But no, you go and ruin my perfectly working ordinary user program by insisting that you run as administrator. Bloody not written by me sub-programs. You deserve great pain for what you have done.
Detecting debuggers
Let’s assume that we’re all using an NT based OS (2k, XP, 2003). It’s a simple matter to detect that you’re being run unde a debugger – simply isue an IsDebuggerPresent call. Heck, you could even put it into a thread that intermittently polls and reacts (in)appropriately.
Of course, I’m not one for polling. Never have been. I just consider it ‘lower class’ to do something like that. This is of course why I like the next trick for detecting the arrival of a debugger.
what happens is that an external thread attaches and executed the ‘DbgUiRemoteBreakin’ function; which at some point issues an ‘DbgBreakPoint’, which of all things contains an int3 and a return statement (this is a kick the debugger operation).
Detecting the debugger consists of rewriting the function implementation.
What we want to do is invoke our function (fun) when a debugger attaches. The following code does just that, and as a result of the attachment of the process simply spits out a message and terminates.
#include <windows.h> #include <stdio.h> HANDLE wh; void message(void) { SetEvent(wh); ExitThread(0); } int main(int argc, char **argv) { unsigned char *abki; HMODULE dlh; wh = CreateEvent(NULL, FALSE, FALSE, NULL); dlh = GetModuleHandle("ntdll.dll"); abki = (void *)GetProcAddress(dlh, "DbgUiRemoteBreakin"); if (abki != NULL) { DWORD olp; if (VirtualProtect(abki, 20, PAGE_EXECUTE_READWRITE, &olp)) { *abki++ = 0xb8; // Mov EAX, *(DWORD *)abki = (DWORD)message; abki+=4; *(WORD *)abki = 0xd0ff; // call EAX } else { printf("Page Protection Failed\n"); return (1); } } WaitForSingleObject(wh, INFINITE); printf("Debugger\n"); return (0); }
This is the beginning of something bigger.
Please wait while the uninstaller makes sure that the world can’t end
Uninstalling Visual Studio .NET. It’s taking an age. All this so I can install visual studio 2005 and hockey things up again 🙂
At least one cause of ‘multi-step ADO operation generated errors’
I was experiencing this occasionally when implementing the delete functionality for a browse window. It turns out that I was not positioned on a record, but instead was either before first or after the last record. Simple problem, really but a bit of a pain to discover the reason as the error isn’t really informative.
The solution was to do move to either the first or last record. Thanks to the magic of the ‘meta bof/eof records’. I have to use the description loosely, as they definitely ain’t records and the correctness police would be rapping my knuckles for such a statement.
Discovering the solution was not helped by the browse grid control I was using – it seemed to indicate that I was on a record when in reality it wasn’t. Another case of model does not match the implementation.
Who’s living in what apartment?
It’s the COM apartment models. They’re related to the threads that make use of COM objects. What happens is that when you initialize COM for a specific thread you declare that it’s either Apartment Threaded (AKA Single Threaded Apartment) or Multi Threaded.
When you use the Apartment threading model, it means that the COM object is isolated within the thread that created it. The most important piece of information about this model is that you should never use that object in another thread – it causes brokenness.
When you use the multi-threading model, what you’re pretty much saying is that I’m probably going to use this COM object in several threads. The way it works is that a multi threaded model, then the context is shared within the process.
The model you support also puts extra complications on you, the creator of the object. COM objects with a declared MT support must use some synchronization to protect shared information within the object, otherwise you’ll suffer from data corruption due to threads walking over the data. You don’t have any of these considerations in a Single threaded model – you’re guaranteed safe and sane interactions.
Additionally, when you’re in COM land, remember never just WaitFor*, but instead MsgWaitFor* things. This also applies to using DDE. This is because the Apartment model uses windows messages under the hood.