So Microsoft needed to come up with a way for a programmer to get and set system information, such as whether menu fading is turned on, or how quickly tooltips fade, etc. So they came up with the API for SystemParametersInfo. On the surface, this API looks quite harmless -- it takes a whopping (and obvious) four parameters:
- A constant for what piece of information you wish to query or mutate
- A 32-bit integer for setting information
- A 32-bit pointer for getting information
- A bitmask for whether you want the change to be persistent across reboots or not
That's the general thought for each of the parameters, supposedly.
The problem is there are exceptions to those rules. One should spring to your mind immediately -- setting information where the parameter needs to be a structure. Ok, so there's two options that Microsoft could have taken. They could have made you typecast the structure as an int and pass it into the setter parameter. This would make sense because the setter is still what takes the information. But instead, they chose to favor passing the structure in as the pointer parameter. I can sort of see the point to this -- it is a pointer already, so why not just use it? So the line is slightly blurred, but it's not that large of a deal, right?
Wrong. For some of the setter constants, you must pass in integer (or boolean) data, such as for setting whether tooltips fade or not (SPI_SETTOOLTIPFADE) into the pointer parameter, while others get passed into the integer parameter like you would expect. That's right. Scary, eh? Most people (myself included) would guess that it is logical for all integer/boolean data to be passed into the 32-bit integer setter parameter. However, someone in Redmond decided that would make too much sense. So, I will repeat myself: you typecast a boolean (or integer) to a void pointer and pass that in as the pointer (getter) parameter instead of the integer (setter) one.
So, why does Microsoft feel that this is a good idea? No clue. I wracked my brain for an evening, trying to fathom what they were thinking, and I cannot come up with an excuse. The data is 32-bits wide, and you are meant to set the data. Why you should have to typecast it to a void pointer so that it can be set is beyond me.
I would like to personally thank Microsoft for taking what should have been a simple API and turning it into a steaming cesspool for no good reason.
What a nice site, been surfing on it for the whole night and day and i neva got bored for a single minute. Keep up your good work and all of the best in everything you do! :-)
Thanks! Glad you found it interesting. :-)
It's actually much worse. Many of the structs have elements for pointers to strings. You allocate the struct, call SystemParametersInfo(SPI_GETxxx, ...) and the struct elements are filled in, including the pointers to strings. Who allocated the strings? Where is that memory? Either those pointers point into strings in the user sub-system, or the call allocates the memory in your process. Either way is bad. The former is unlikely because it would require an LPC call to read them. The latter would result in leaked memory in your process. Yikes!