How to return a positive error code from ATL in VB6?

I checked the answer: How to return the error string and error code in VB6 from an ATX ActiveX control?

I can return user-defined negative error codes, that is, with the severity bit set, and a custom error message. But I would like to be able to generate code that VB6 will present as a positive number # for Err.Number, which will be easier for the user to use. I am sure that this can be done since the Microsoft DAO 3.6 DLL can. For example, it returns Err.Number = 3078 with Err.Description "Microsoft Jet Database ..." if the table does not exist.

Note that for error reporting I have implemented ISupportErrorInfo etc.

+6
source share
2 answers

Annotating the comment a bit. He's right about using FACILITY_CONTROL. In addition, you must ensure that the error code is greater than 512 so that it does not interfere with the error codes during VB6 execution. So use something like this:

HRESULT MakeVB6Error(UINT errCode) { assert(errCode > 0 && errCode < 65536 - 513); return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_CONTROL, errCode + 513); } 
+5
source

VB makes many mappings of HRESULT values ​​to Err.Number values. For example, if HRESULT was 0x8007002, VB breaks them according to the COM standard as follows:

 Bit 31 - Severity (set to 1 in all errors) Bit 30 - Reserved Bit 29 - Customer Bit Bit 28 - Reserved Bit 27 - 16 Facility code Bit 15 - 0 Error code 

In practice, the upper nibble is always 8. The mechanism varies and tells you what type of error it is. In this case, the object code is 0x007 (FACILITY_WIN32), which means that this is a standard Win32 error. The bottom two bytes represent the actual error. Looking in winerror.h, this error is 2 - ERROR_FILE_NOT_FOUND. VB is smart enough to correlate this error with the standard error VB 53 "File not found".

In VB documentation, we are always advised to add the vbObjectError constant to our error numbers when they increase from the VB component. This was almost equivalent to ORing a 32-bit integer 0x80040000 to your error number (assuming it is <= 65535). In this case, the object code was 0x4 (FACILITY_ITF), which indicated that the error was raised using a specific interface in the class. In practice, this simply made our error numbers large and negative, and hard to understand.

We really had to ignore the documentation and just raise the direct error numbers. Behind the scenes, VB OR'd has its own object code - 0xA (FACILITY_CONTROL). However, any VB component, seeing HRESULT with this object code, will automatically clear the upper two bytes, so we will see that the number will be positive - not negative.

I suggest you use FACILITY_CONTROL for your own error numbers. Other COM clients may be confused, but VB clients see your error number as positive.

Alternatively, you can ignore the usual HRESULT mechanism for return values. Instead, return HRESULT = S_OK and use the [retval, out] parameter at the end of the function to make it look like it is a VB function.

+4
source

Source: https://habr.com/ru/post/944561/


All Articles