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.
February 2006 Archives
Just had to put something useless into the mix! guess what, I'm tired and I don't have much to contribute to the wide world. I'm interested in the GTD stuff. Maybe I should just GTD.
One thing I have to say is that I don't like the bloody shite on the TV.
One thing I have to say is that I don't like the bloody shite on the TV.
Ah, yes. I saw that Albert had posted the listings for how young Dave Connolly got on in the winter Olympics Skeleton (20th! excellent for him), his previous blog entry had me cringe.
It was another case of expecting a language to perform implicit type conversion when assigning it. I was learning C when I found out about this. <float> = <int> / <int>; does not yield the correct answer if you were expecting a floating point answer.
It's partially to do with the way the language is implemented and partially to do with the KISS principle. What you are doing is essentially performing two separate operations. A division operation, followed by an assignment operation. The division operation will happen with all the precision of the types that were used, so under the rules, if none of the values are a floating point value then the operation will not use floating point arithmetic. I mean, if you had to convert every integer into a floating point value every time you encountered a mathematical operation just in case the answer is a floating point value you end up making the system very, very slow and potentially likely to cause problems of other types.
Like attempting to make an equality test on floating point numbers. Let's just say you should never use a direct equality comparison on floating point values, as even if you think the value is 0.0 it may in reality be 0.0000000000001. With the extra precision of floating point numbers comes less accuracy, and to steal someone else's description, if ints are bricks then floats are more like silly putty.
If you want to use floating point math then at least one of the elements of the operation must be a floating point value. For example:
Of course, we can't forget all the joyous C constant things we had to remember.... <value>U for unsigned, L for long, UL for unsigned long, LL for long long (64 bit anyone). When you're using C on a predominantly 16 bit programming environment (like the palm platform), then you need to keep reminding yourself, because an int on the palm is only 16bits in size.
oh the joy of it all!
It was another case of expecting a language to perform implicit type conversion when assigning it. I was learning C when I found out about this. <float> = <int> / <int>; does not yield the correct answer if you were expecting a floating point answer.
It's partially to do with the way the language is implemented and partially to do with the KISS principle. What you are doing is essentially performing two separate operations. A division operation, followed by an assignment operation. The division operation will happen with all the precision of the types that were used, so under the rules, if none of the values are a floating point value then the operation will not use floating point arithmetic. I mean, if you had to convert every integer into a floating point value every time you encountered a mathematical operation just in case the answer is a floating point value you end up making the system very, very slow and potentially likely to cause problems of other types.
Like attempting to make an equality test on floating point numbers. Let's just say you should never use a direct equality comparison on floating point values, as even if you think the value is 0.0 it may in reality be 0.0000000000001. With the extra precision of floating point numbers comes less accuracy, and to steal someone else's description, if ints are bricks then floats are more like silly putty.
If you want to use floating point math then at least one of the elements of the operation must be a floating point value. For example:
int a = 1; int b = 2; float c = 0; c = a / b;Means that c is 0.0, not 0.5, because everything on the right hand side of the operation is an integer
c = (float)a / b;Would cause c to be 0.5, which is what you wanted. As an aside the initial float c = 0 has an implied type conversion from int to float. It should really have been c = 0.0.
Of course, we can't forget all the joyous C constant things we had to remember.... <value>U for unsigned, L for long, UL for unsigned long, LL for long long (64 bit anyone). When you're using C on a predominantly 16 bit programming environment (like the palm platform), then you need to keep reminding yourself, because an int on the palm is only 16bits in size.
oh the joy of it all!
In an article by Andrew Keen, he rants somewhat about Web 2.0 being a bit too reflective on ourselves. I find myself agreeing somewhat with the problem of reflection. Being that this is my blog, of course the whole thing is reflexive from the get-go, but bear with me. The web is a dangerously filtering medium. Web 2.0 makes it even more so. Communities of likeminded individuals keeping to their own interests. I'm tempted to make a roulette style take me somewhere new website that is as random as possible. Of course any mechanism I would consider using (search engine based) would of course not be completely random.
I'm getting annoyed with the virtual community building. we need to build real communities.
I'm getting annoyed with the virtual community building. we need to build real communities.
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.
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.
I had a minor complaint some time back about the lack of consistency amongst the various windows APIs, they seemed to be written by people who chose one mechanism one day, and another the other day. The reality is that in such a large company as Microsoft, the different groups were consistent amongst themselves, the problem was that they were not consistent amongst each other.
This brings me to the rant du jour. When one finds oneself reading/writing assembly language, the code is platform consistent. For example on x86 the format is: operator parameters,destination. So, mov 0xffffffff, %eax means put the value 0xffffffff into the register eax. On Sparc the parameter and destinations are reversed so mov %l0,0x110011 means put the value 0x110011 into the register l0. It's quite easy to see one from the other because you are aware of what platform you are on. Sun, for reasons best known to themselves reversed the order of the parameters - probably to make them more like the Solaris 'native' format and easier for their developers to follow.
All very fine and well, Sun are entitled to confuse native x86 developers all they want, and besides which, because of the consistency, it is a really easy switch.
My mini bugbear is of course, the bcopy function. It performs a block copy from a source to a destination. It's part of libc, it's simple, it's easy to use, the only problem is that it is in the reverse order from all the string routines (dest, source), memmove (dest, src). If you look up the definition of bcopy it generally asserts that it is implemented in terms of memmove, and if you look at most implementations you find that bcopy just swaps the in and out parameters and then invokes memmove (I believe the exception is sparc, where this is the opposite). This is why bcopy is officially off my list of functions to use. It's simply the one lone voice of dissent amongst all the consistency that libc affords.
Who made bcopy then?
This brings me to the rant du jour. When one finds oneself reading/writing assembly language, the code is platform consistent. For example on x86 the format is: operator parameters,destination. So, mov 0xffffffff, %eax means put the value 0xffffffff into the register eax. On Sparc the parameter and destinations are reversed so mov %l0,0x110011 means put the value 0x110011 into the register l0. It's quite easy to see one from the other because you are aware of what platform you are on. Sun, for reasons best known to themselves reversed the order of the parameters - probably to make them more like the Solaris 'native' format and easier for their developers to follow.
All very fine and well, Sun are entitled to confuse native x86 developers all they want, and besides which, because of the consistency, it is a really easy switch.
My mini bugbear is of course, the bcopy function. It performs a block copy from a source to a destination. It's part of libc, it's simple, it's easy to use, the only problem is that it is in the reverse order from all the string routines (dest, source), memmove (dest, src). If you look up the definition of bcopy it generally asserts that it is implemented in terms of memmove, and if you look at most implementations you find that bcopy just swaps the in and out parameters and then invokes memmove (I believe the exception is sparc, where this is the opposite). This is why bcopy is officially off my list of functions to use. It's simply the one lone voice of dissent amongst all the consistency that libc affords.
Who made bcopy then?
Dermot has a mini-rant about this on his blog. It turns out that in order to do most anything useful on journalspace you need to pay for it. For example exporting RSS2.0 feeds is a premium service, which makes allowing rss readers access to your site (last updated pings, for example) costs you money. Being able to post from external applications (via XML-RPC) is another premium service, making cross blog synchronization difficult.
I suppose that is the price of using a free service.
I suppose that is the price of using a free service.
Uninstalling Visual Studio .NET. It's taking an age. All this so I can install visual studio 2005 and hockey things up again :)
More 'extreme scenes', but with a shiny happy ending. I think I need to sit down with about 4 days worth of the show to get it out of my system - just like I did with Kit Kat's. I can't eat one anymore without thinking - damn, but this is tastless crap. I'm currently avoiding going through the process with the Tesco continental thins. Yummy, but I'm careful about it.
Donal! Where can I buy the booze! It's all good; honest!
Donal! Where can I buy the booze! It's all good; honest!
I thought I had it, but I didn't. I still can't find out the reason. Currently, after each post I re-read the table by closing and opening it. The table is a small, local, temporary table for recording information before posting it to the real database so I don't really care that the exception is triggered.
Now, I'm getting DbgBreakPoint exceptions. This was in a simple showmodal call, so I have no idea why it's there. Apparently it might have something to do with opening the table concerned.
Now, I'm getting DbgBreakPoint exceptions. This was in a simple showmodal call, so I have no idea why it's there. Apparently it might have something to do with opening the table concerned.
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.
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.
I finally got someone to send me/link to The Chronicles of Davetron, where I discovered that he qualified for the Winter Olympics in the skeleton. Let me tell you that since I've know Dave he's always been a fanatic for the sports, and to find this out I am just as proud as punch. While we partied he trained, and now he gets to represent the country at the Olympics - it just brings a tear to my bitter eyes.
The godchild was in a table quiz tonight and he won! we were all surprised. while we were going home he asked a question about the internet - basically claiming that the internet was invented in 1990. I had to correct him, of course that it was the world wide web. Then I decided to explain the 7 layer OSI model to him. I think he regretted having made the slight factual error at the beginning. In the end, I explained to him that the web operated as a level 7 protocol; or in the parlance of Arthur C. Clarke; is indistinguishable from magic. It would have driven him to sleep if it wasn't for the vast amount of soda he had consumed.
this site is not designed for minors. With that in mind we have created this really crappy test for you. If you can input a date of birth that means you are over a certain age then we will permit you entrance to our web site, otherwise please leave.
Problem number 1, anyone over the age of 18 (or, shock horror for drinks sites 21) gets sick of these things coming up so often. I mean come on people, just a button saying 'i agree, I'm over the required age' is a much better mechanism, because invariably the implementors of the web site in question have used some gorram flash animation that doesn't take key input, and can't deal with nerds typing dates.
The only time I got a kick out of something that insisted I was over a certain age asked me questions that were unlikely to be known by an under 18. The game was Leisure Suit Larry and it had a good collection of questions. I'm not certain, but I think they were age related, so if you claimed you were of a certain age then a different set of questions were sourced. you had to get three questions correct, and could fail two, after which it kicked you out.
Problem number 1, anyone over the age of 18 (or, shock horror for drinks sites 21) gets sick of these things coming up so often. I mean come on people, just a button saying 'i agree, I'm over the required age' is a much better mechanism, because invariably the implementors of the web site in question have used some gorram flash animation that doesn't take key input, and can't deal with nerds typing dates.
The only time I got a kick out of something that insisted I was over a certain age asked me questions that were unlikely to be known by an under 18. The game was Leisure Suit Larry and it had a good collection of questions. I'm not certain, but I think they were age related, so if you claimed you were of a certain age then a different set of questions were sourced. you had to get three questions correct, and could fail two, after which it kicked you out.
