Comparing the OPC managed-code and native-code Part URI helper APIs


Windows 7 includes new native-code APIs that provide functionality to compose and parse Part URIs. These APIs are provided through the IOpcUri and IOpcPartUri interfaces. Managed-code provides similar functionality with the System.IO.Packaging PackUriHelper class.


A difference between the two API sets is that while the managed-code PackUriHelper APIs support both Pack URIs and Part URIs (also called “part names”), the native-code IOpcFactory::CreatePartUri and IOpcPartUri APIs only provide functionality to create and manage Part URIs. The native-code Packaging APIs do not provide any functionality to access packages or package content as external resources, and therefore only supports Part URIs to address part content within the immediate package.


The managed-code PackUriHelper and native-code CreatePartUri/IOpcPartUri APIs are both designed to be ECMA 376-2 (2006) compliant.


The table below shows a comparison between the managed-code and native-code APIs, and which APIs provide similar functionality:



























































Managed API


Equivalent Native API


Parity


PackUriHelper.CreatePartUri


IOpcFactory::CreatePartUri


See 1.1


No equivalent API


IOpcFactory::CreatePackageRootUri

 

PackUriHelper.GetRelationshipPartUri


IOpcUri::GetRelationshipsPartUri


Identical


PackUriHelper.GetRelativeUri


IOpcUri::GetRelativeUri


Identical


PackUriHelper.ResolvePartUri


IOpcUri::CombinePartUri


See 1.2


PackUriHelper.ComparePartUri


IOpcPartUri::ComparePartUri


Identical


PackUriHelper.GetSourcePartUriFromRelationshipPartUri


IOpcPartUri::GetSourceUri


Identical


PackUriHelper.IsRelationshipPartUri


IOpcPartUri::IsRelationshipsPartUri


Identical


PackUriHelper.Create


No equivalent API

 

PackUriHelper.ComparePackUri


No equivalent API

 

PackUriHelper.GetNormalizedPartUri


No equivalent API

 

PackUriHelper.GetPackageUri


No equivalent API

 

PackUriHelper.GetPartUri


No equivalent API

 


1. API differences


1.1 IOpcFactory::CreatePartUri differences from PackUriHelper.CreatePartUri


The functionality of the native-code IOpcFactory::CreatePartUri API, follows the rules provided in ECMA 376-2 OPC standard, Appendix A.3 for resolving a relative reference to a valid Part URI (part name). The IOpcFactory::CreatePartUri and IOpcUri::CombinePartUri native-code APIs both produce the same output (“Native-code Behavior” below).





























Input


Native-code CreatePartUri Behavior


Managed-code CreatePartUri Behavior


Contains bad UTF-8 encoding e.g. ‘%FC’:


Leaves %FC unchanged in output.


Changes to valid UTF-8 output %C3%BC. (See * below)


Contains empty segments i.e. multiple forward slashes


Collapses multiple forward slashes to a single forward slash.


Does not collapse. (This is OPC rule violation).


Begins with 2 or more forward slashes


Collapses multiple forward slashes to a single forward slash.


Fails, throws an “ArgumentException”.


Contains a single trailing forward slash


Removes trailing slash.


Fails, throws an “ArgumentException”.


Contains a percent-encoded NULL (%00)


Returns an “E_UNEXPECTED” HRESULT error.


Percent-encoded NULL is kept unchanged, and returns a valid part name.


* – Characters above 0x7F are required to be escaped using UTF-8. For example, if the input URI contains %FC, which is not a legal UTF-8 sequence, the rules provided in RFC 3987 section 3.1, require leaving the input unchanged. The PackUriHelper.CreatePartUri method however, decodes %FC as UTF-16 to its octet <FC> (character ‘ü’) and then re-encodes it to the valid UTF-8, ‘%C3%BC’. Unfortunately, this approach is incompliant with RFC rules. [Note: If the relative reference contains a %FC, both IOpcUri::CombinePartUri and PackUriHelper.ResolvePartUri leave it unchanged.]



1.2 IOpcUri::CombinePartUri differences from PackUriHelper.ResolvePartUri


The managed-code PackUriHelper.ResolvePartUri API differs from the native-code IOpcUri::CombinePartUri API in that it resolves the input relative reference against a base URI, but it does not ensure that the result is a valid part name. In contrast, the native-code IOpcUri::CombinePartUri API both resolves the input and ensures that the result is a valid part name.



























Input


Native-code CombinePartUri Behavior


Managed-code ResolvePartUri Behavior


Contains percent-encoded unreserved characters


Un-encodes unreserved characters, resulting in a valid part name.


Leaves characters in encoded form resulting in an invalid part name.


Contains empty segments i.e. multiple forward slashes


Collapses multiple slashes to a single forward slash, resulting in a valid part name.


Does not collapse empty segments, resulting in an invalid part name.


Begins with 2 or more forward slashes


Collapses multiple slashes to a single forward slash, resulting in a valid part name


Fails, throws an “ArgumentException”.


Contains a single trailing forward slash


Removes trailing slash.


Does not remove trailing slash resulting in an invalid part name.


Contains a percent-encoded NULL (%00)


Returns an ” E_UNEXPECTED ” HRESULT error.


Percent-encoded NULL is kept unchanged, and returns a valid part name.


– Ali Naqvi


Comments (0)