Win32 Programming
E N D
Presentation Transcript
Win32 Programming Lesson 5: Error Codes
Before We Begin • Much of the time in this class we’ll be calling Win32 Functions • However, sometimes they’re not going to work as you expect • How do you deal with the unexpected?
First, a question • What’s the difference between these lines, and how is that difference realized: • void main() { node *foo; foo = new node(); node bar; …}
Return Codes • Windows functions (and C/C++ calls in general) can only directly return one value… why?
Common Win32 Returns • VOID: This function cannot possibly fail (Ha!) • BOOL: Success is 0. Non-zero is a failure. Check for 0 or not 0… don’t check for TRUE • HANDLE: NULL (failure) or an OBJECT which can be manipulated • PVOID: NULL (failure) or a Pointer to an area of memory • LONG/DWORD: 0 or -1 for failure – sometimes. Varies from function to function
Tracking Errors • The actual error code is stored in thread local storage • Remember that term, we’ll be looking at it a lot later • For now, that means every thread has its own error codes • MSDN: DWORD GetLastError
The Actual Values • Stored in WinError.h • // // MessageId: ERROR_INVALID_FUNCTION // // MessageText: // // Incorrect function. // #define ERROR_INVALID_FUNCTION 1L // dderror // // MessageId: ERROR_FILE_NOT_FOUND // // MessageText: // // The system cannot find the file specified. // #define ERROR_FILE_NOT_FOUND 2L
Not Very Helpful… • People don’t do well with numbers • Need to convert into a Text String • Fortunately, there is a way!
FormatMessage • DWORD FormatMessage( DWORD dwFlags, LPCVOID pSource, DWORD dwMessageId, DWORD dwLanguageId, PTSTR pszBuffer, DWORD nSize, va_list *Arguments);
MSDN • It’s an invaluable resource but you have to learn how to use it • I’ll do this one for you… some of the rest you will have to do on your own
Parm by Parm • dwFlags: (in) • Something we supply. FORMAT_MESSAGE_FROM_SYSTEM gives us the result from GetLastError • lpSource: (in) • Where the definitions are – for us, NULL. • dwMessageId: (in) • The message we want to translate
Parm by Parm (ctd) • dwLanguageID: (in) • What language to format the message in • lpBuffer: (out) • The buffer for the message • Can be auto-alloced • nSize: (in) • Either: the size of the output, or the minimum number of TCHARS the message will contain • Arguments: (in) • Pointer to an array of values to insert into the formatted message
FormatString in Action • BOOL fOk = FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, dwError, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), (LPTSTR) &hlocal, 0, //dwSizeNULL);
A GUI Version • Turns out to be very tricky, due to one parameter which is hard to marshal: va_list • Why is this hard? • .NET implements its own object to get around this: Win32Exception • Note here how we’re getting into some of the “gnarliness” of Win32