tags:

views:

255

answers:

5

I've noticed that in c/c++ a lot of Win32 API structs need to be told how big they are. i.e someStruct.pbFormat = sizeof(SomeStruct)

Why is this the case? Is it just for legacy reasons? Also any idea what "pb" stands for too?

EDIT: oops, yeah I meant "cbFormat"

+7  A: 

This is so that the structure can be extended in future versions of the API, and Windows can then know (by the size the caller passed in) which fields should be looked at or not. It's basically a crude form of API versioning.

Usually those count bytes are prefixed with cb, which stands for "count of bytes". For example, the STARTUPINFO structure starts with:

typedef struct _STARTUPINFO {
  DWORD  cb;
  LPTSTR lpReserved;
  ...
} STARTUPINFO, *LPSTARTUPINFO;

This was extended at some point with the STARTUPINFOEX structure, which contains the same first part but a different size. Depending on the value of cb, Windows will know whether or not to look at the new lpAttributeList field.

Greg Hewgill
Do other major OSes do API versioning this way, or are there better alternatives in use?
MusiGenesis
@MusiGenesis: good question, ask it :)
MSalters
A: 

So that future versions can add extra fields and still be able to provide backwards binary compatibility:

// CAUTION - the code is not 100% accurate and can fail due to packing rules.
// For illustrative purposes only
if (offsetof(struct foo, field) > f->pbFormat)
{
   // called with a version that predates the addition of
   // field so revert to a default value
}
R Samuel Klatchko
Actually it can't fail due to packing rules, as those are implied by Win32.
MSalters
@MSalters - unfortunately, it can fail. Consider starting with `struct foo { int size; short s1; char c1; }` and later extending that to `struct foo { int size; short s1; char c1; char c2; }` Both will have size 8 so you won't be able to tell if the caller has a definition with or without field `c2`.
R Samuel Klatchko
Per the Win32 rules, that's not a valid way to define version 2 of `struct foo`. The first DWORD, set to sizeof(object), must differ between v1 and v2.
MSalters
+1  A: 

The pb is an example of Hungarian Notation, basically a scheme for encoding a variable type into its name.

Dave Kilian
I believe the question is not directed to the naming convention
YeenFei
Although this is a good incidental illustration of the main problem with Hungarian notation: if you start counting on those little letters to actually *mean* something important, you're in trouble.
MusiGenesis
Actually the two characters 'cb' indicate something your IDE won't: count of bytes.
iconiK
+1  A: 

Because Win32 API is a C API - not C++, so object orientated methods of extending the API are not available. With C++ API a new feature would use a structure that derives from the older one and call an interface that take the base structure, ensuring type safety.

C is a procedural language and is more limited in what you can do with structures.

Igor Zevaka
+8  A: 

This is for backward compatibility when Windows API is extended.

Imagine the following declarations

struct WinData
{
   long flags;
}
BOOL GetWinData(WinData * wd);

which you are calling like this:

WinData wd;
GetWinData(&wd);

A future OS version may extend this to

struct WinData
{
   long flags;
   long extraData;
}

However, if you have compiled against the "older" SDK, GetWinData has no chance to figure out you don't know about extraData. If it would fill it in regardless, it would overwrite data on the stack. BOOOM!

That's why, the "size known to the caller" is added to the structure, and new members are appended at the end. The GetWinDataimplementation can inspect the size and decide "this poor guy doesn't know about all the new features yet".

peterchen
+1 There should be a web site dedicated to reasons people think Windows sucks, along with rational, sensible explanations (like this one) for why something is done a certain way. It's interesting also how backwards compatibility is so often the explanation for something otherwise odd in Windows - I use this to hush up Mac fanboys sometimes, by reminding them how all their software stops working with each new OS.
MusiGenesis
Sometimes they use the size or version variable, sometimes they go somestructEx to indicate extra or extended.
gbrandt
@MusiGenesis: I believe there is such a website and it's called [Raymond Chen's Blog](http://blogs.msdn.com/b/oldnewthing/). :-)
James McNellis
Any relation to this "Peterc Hen" fellow?
MusiGenesis
I actually got my 5 seconds of sh/fame there :) - http://blogs.msdn.com/b/oldnewthing/archive/2006/04/12/574928.aspx(scroll down to Nish's comment)
peterchen