140 likes | 303 Views
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.
E N D
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