Part 1 – Technical Background
I assume you often heard the statement: “Don’t use undocumented API calls”. And you might often have thought: “Why not? There are so powerful features under the surface of the documented API! I want to use them!”. This article should give you some ideas what could happen when undocumented API calls are used.
First of all: undocumented API is a wrong term. API means Application Programming Interface. But the function calls that usually get the title undocumented API are not intended to be used to program against. A better name would be undocumented program internal interface or short undocumented interface. That’s the term I will use here in this article.
So what’s the problem with using these undocumented interfaces? There are a couple of problems coming with this:
1) They are undocumented
Undocumented means that there is no documentation available that tells a programmer what exactly such an undocumented interface does and which parameters have to be passed to methods. Usually such undocumented program internal interfaces are DLL entry points used by the program internally. Every DLL needs to have such entry points to allow other DLLs to access classes and methods inside a DLL. The only practical way to ensure that such entry points are not called from others would be to compile the whole application into one monolitic EXE file. But this would kill code reusability between different parts of the application.
The fact that these interfaces are undocumented means that a programmer can only identify what such an interfaces does and which parameters have to be passed in by either reverse engineering (decompiling) the DLL that hosts the undocumented interface or a DLL that properly calls this method or by guessing and black box testing – means by passing in parameters and test the result. This often works very well and usage of the undocumented interface gives you the expected result. But what if the programmer missed a tiny bit of information about the required context which causes the function to fail in – let’s say 1% of all calls? That would mean that on an everage every 100th use of this interface results in an unexpected behaviour! Even if it would only fail in 0,01% of all cases this would still mean that every 10000th function call result in an unexpected behaviour – potentially leading to data loss. Is this something you would like to rely on?
2) Again: They are undocumented
Even if the the programmer identified the usage of the function call correct and on his machine he has verified that the function call does exactly what it should do in 100% of all cases. Would this mean that he can savely develop an application based on this function call? Lets take a simple sample. Let’s assume the function the programmer is interested in is a string to number converter for strings holding number. The undocumented interface he found looks like this:
public double string2double(string str)
The implementation of the function is not visible to him but he guesses that this function will do the job he is looking for. Means if a string containing a number is passed in it will return the number. Fine. He tests this function for several thousand random numbers on his system and always gets the expected result. Great! Now he builds the applicaton and gives it to his customers as an add-on of the original product.
A couple of weeks later some of the companies he gave the add-on complain about problems with the application. On others systems everything works fine. What did he miss? The fact that he does not know the internals of the function he was calling and not the information about how exactly the parameters need to look like caused problems on some systems. For the sample above you just need to know that some countries use the “.” as decimal separator and “,” as thousand separator while other countries use it vice versa.
So if you pass in 10,000 on some system you will get back 10000 on others you will get back 10. On a single system there would have been no way to identify this using black-box-testing!
So even if all your tests are fine you can never be sure that an undocumented interface will return the same result on other machines. Is this something you would like to rely on?
3) Hotfixes and Patches
Unlike documented API calls undocumented internal function calls are subject to change without notice. This means a developer can easily change sequence, number or type of parameters of a method. As all callers are under his control he only needs to ensure that the calling code is adjusted as well and that all change are shipped to customers using the application together.
But custom code using these undocumented interfaces will not be adjusted by the developer! Ok, you would say. I will easily notice this when the application starts throwing exceptions because the number or type of the arguments suddenly became wrong and then I can correct this.
Fine. But what if the change is in a way that no exceptions is been thrown? If only the interpretation of the parameter values changes or if only the sequence of parameters with identical types changes?
Let’s assume the following. The undocumented interface exposes a copy function to copy information from one place to another:
public void copy(string destination, string source)
The custom code has used this function savely since months without any problems so it seems to be save to use this undocumented method call.
But what if now the developer of the application gets the requirement to make the destination an optional parameter and if omitted a default location should be used? He could implement this the way that he tests if the first paramter is null. But he could also decide that first should come the mandatory parameters and behind that the optional parameters.
He now changes the undocumented interface and all code parts in his application that reference this interace to look as follows:
public void copy(string source, string destination)
You see what will happen? When this hotfix is rolled out to customers using other programs using the undocumented function call will result in data loss as suddenly the destination item will be copied over the source item! Is this something you would like to rely on?
Undocumented program internal interfaces are only tested in exactly the context used in the application! Additional testing as required for public APIs will usually not happen. So any unexpected inproper use by other applications might do harmful things to your data. Is this something you would like to rely on?
I personally would never rely on undocumented program internal function calls – even if someone tells me that these are undocumented API calls especially if my application uses business critical data. There are so many unexpected things that can happen to my application and more important: to my business critical data. How do you consider the importance of your business critical data?
Would it be worth to gamble just for the benefit of the features you can get from using undocmented program internal function calls?