Common WWSAPI errors: A NULL WS_STRUCT_DESCRIPTION was specified.


When you use WsUtil to generate stub code and then work with the generated structures, you may get E_INVALIDARG when making the call to the service and, with WWSAPI tracing turned on, see the error message “A NULL WS_STRUCT_DESCRIPTION was specified.”.


 


WS_STRUCT_DESCRIPTION is one of the WWSAPI serialization structures and describes how a structure should be serialized into XML and deserialized from XML. When you use WsUtil to generate the stub code, lots of complex structures will be generated, including WS_STRUCT_DESCRIPTION. You’ll need to make sure that the structures are initialized properly. By default, if you use a structure that has either a base structure or derived structure(s), you should use a generated function to initialize it. For example, say the schema in the WSDL defines a type Location that has two derived types UserLocation and GeocodeLocation, WsUtil will generate the Location type like the following:


 


#if !defined(WS_CPLUSPLUS)


typedef struct Location


{


    const struct _WS_STRUCT_DESCRIPTION* _type;


    double Altitude;


    double Latitude;


    double Longitude;


} Location;


void WINAPI Location_Init(Location*);


struct UserLocation* WINAPI Location_AsUserLocation(Location*);


struct GeocodeLocation* WINAPI Location_AsGeocodeLocation(Location*);


#endif


 


Notice the function Location_Init after the structure. In order to properly initialize a Location structure, you need to call the Location_Init function like this:


 


    Location location = {NULL, 0, latitude, longitude};


    Location_Init(&location);


 


When you get the E_INVALIDARG with the error message I mentioned above, it’s because you forgot to call the *_Init function, which will set the WS_STRUCT_DESCRIPTION structure (the location._type field in this example). The Location_Init is generated like the following:


 


#if !defined(WS_CPLUSPLUS)


void WINAPI Location_Init(Location* _Location)


{


    ((Location*)_Location)->_type =


        (WS_STRUCT_DESCRIPTION*)&dev_virtualearth_net_webservices_v1_common1_xsd.globalTypes.Location;


}


#endif


 


The *_Init functions (and the _type field) won’t be generated for types that don’t have base type or derived types. When you are consuming a service without knowing the details of the server type definitions, it’s always a good idea to open up the generated header file to see if *_Init functions are generated for the structures you use.


 


Please note that this is the default behavior. If you define a preprocessor WS_CPLUSPLUS, the requirement is different. I’ll discuss that in a later post.


 


For further reading on WsUtil’s support of XML schema, please go to http://msdn.microsoft.com/en-us/library/dd815313(VS.85).aspx.


 

Comments (0)