Building .NET applications for the App Store is not currently supported. If you are like me, building user interfaces with .NET is quick and easy and so, it would be nice to submit .NET applications. I did manage to submit an application that was built in .NET and also supports the Atom SDK, still remains to be seen if it will be approved but I want to post about how I managed to use the Atom SDK in C#. We also want to provide some level of security, so this topic will be addressed.
The SDK provides a really nice .lib file with a C interface that is really simple to use. Just a few methods. I have not looked at the C++ interface since the C version is so easy. The first thing to do is to build a small .dll wrapper for the .lib file. You don't need to put almost any code, just re-export the C methods into DLL methods. Just go in Visual Studio and create a empty .DLL project. I called mine "AdpWrapper". You just add the following exports to the definition (.def ) file:
LIBRARY "AdpWrapper"
EXPORTS
ADP_Get_API_VERSION
ADP_Get_API_LEVEL
ADP_Get_ADP_DEBUG_APPLICATIONID
ADP_Get_ADP_DEBUG_COMPONENTID
ADP_Get_ADP_EXPIRED_APPLICATIONID
ADP_Get_ADP_EXPIRED_COMPONENTID
ADP_Initialize
ADP_Close
ADPW_IsAuthorized
ADPW_IsAppAuthorized
ADP_ReportCrash
ADP_ApplicationBeginEvent
ADP_ApplicationEndEvent
Ok, now in the DLL C file, I did add a little bit of code, but it's as little as you can get. It's just a question of re-exporting the C functions as DLL functions. There are many ways of doing this. Of course, don't forget to include the adpcore.h and adpcore.lib in your project.
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { return TRUE; }
const wchar_t* __stdcall ADP_Get_API_VERSION() { return ADP_API_VERSION; }
const unsigned long __stdcall ADP_Get_API_LEVEL() { return ADP_API_LEVEL; }
char* __stdcall ADP_Get_ADP_DEBUG_APPLICATIONID() { return (char*)&ADP_DEBUG_APPLICATIONID; }
char* __stdcall ADP_Get_ADP_DEBUG_COMPONENTID() { return (char*)&ADP_DEBUG_COMPONENTID; }
char* __stdcall ADP_Get_ADP_EXPIRED_APPLICATIONID() { return (char*)&ADP_EXPIRED_APPLICATIONID; }
char* __stdcall ADP_Get_ADP_EXPIRED_COMPONENTID() { return (char*)&ADP_EXPIRED_COMPONENTID; }
const int __stdcall ADPW_IsAuthorized(char* id) { ADP_APPLICATIONID id2; memcpy(&id2, id, 16); return ADP_IsAuthorized(id2); }
const int __stdcall ADPW_IsAppAuthorized(char* id) { ADP_COMPONENTID id2; memcpy(&id2, id, 16); return ADP_IsAppAuthorized(id2); }
Ok, so you got everything ready and compiled your first AdpWrapper.dll. Now it's time to head over to C# and write a little code to use this new DLL. You will need to copy the dll into the same folder as your C# binary so the .NET executable can find it. On the C# class you need to use the "System.Runtime.InteropServices" library to import all of the methods. If you add a little code, you can turn all the GUID's into native .NET GUID types. Makes it really easy and you don't need to deal with byte arrays anymore. Here is sample C# code, note the "PerformCheck" at the bottom, we will come back to that.
public class AdpWrapperClass
{
public enum ReturnCode
{
ADP_FAILURE = -1,
ADP_SUCCESS,
ADP_NOT_INITIALIZED,
ADP_NOT_AVAILABLE,
ADP_INCOMPATIBLE_VERSION,
ADP_ERR_DATA_TOO_BIG,
ADP_AUTHORIZED,
ADP_NOT_AUTHORIZED,
ADP_AUTHORIZATION_EXPIRED,
ADP_NO_APP_BEGIN_EVENT
}
[DllImport("AdpWrapper.dll")]
private static extern ReturnCode ADP_Initialize();
[DllImport("AdpWrapper.dll")]
private static extern ReturnCode ADP_Close();
[DllImport("AdpWrapper.dll")]
private static extern ReturnCode ADPW_IsAuthorized(byte[] id);
[DllImport("AdpWrapper.dll")]
private static extern ReturnCode ADPW_IsAppAuthorized(byte[] id);
// ADP_ReportCrash
[DllImport("AdpWrapper.dll")]
private static extern ReturnCode ADP_ApplicationBeginEvent();
[DllImport("AdpWrapper.dll")]
private static extern ReturnCode ADP_ApplicationEndEvent();
[DllImport("AdpWrapper.dll")]
private static extern IntPtr ADP_Get_API_VERSION();
[DllImport("AdpWrapper.dll")]
private static extern ulong ADP_Get_API_LEVEL();
[DllImport("AdpWrapper.dll")]
private static extern IntPtr ADP_Get_ADP_DEBUG_APPLICATIONID();
[DllImport("AdpWrapper.dll")]
private static extern IntPtr ADP_Get_ADP_DEBUG_COMPONENTID();
[DllImport("AdpWrapper.dll")]
private static extern IntPtr ADP_Get_ADP_EXPIRED_APPLICATIONID();
[DllImport("AdpWrapper.dll")]
private static extern IntPtr ADP_Get_ADP_EXPIRED_COMPONENTID();
public static ReturnCode Initialize() { if (!PerformCheck()) return ReturnCode.ADP_FAILURE; else return ADP_Initialize(); }
public static ReturnCode Close() { return ADP_Close(); }
public static ReturnCode IsAuthorized(Guid applicationid) { return ADPW_IsAuthorized(applicationid.ToByteArray()); }
public static ReturnCode IsAppAuthorized(Guid componentid) { return ADPW_IsAppAuthorized(componentid.ToByteArray()); }
public static ReturnCode ApplicationBeginEvent() { return ADP_ApplicationBeginEvent(); }
public static ReturnCode ApplicationEndEvent() { return ADP_ApplicationEndEvent(); }
public static string ApiVersion { get { return Marshal.PtrToStringUni(ADP_Get_API_VERSION()); } }
public static ulong Apilevel { get { return ADP_Get_API_LEVEL(); } }
public static Guid DebugApplicationId { get { byte[] id = new byte[16]; Marshal.Copy(ADP_Get_ADP_DEBUG_APPLICATIONID(), id, 0, 16); return new Guid(id); } }
public static Guid DebugComponentId { get { byte[] id = new byte[16]; Marshal.Copy(ADP_Get_ADP_DEBUG_COMPONENTID(), id, 0, 16); return new Guid(id); } }
public static Guid ExpiredApplicationId { get { byte[] id = new byte[16]; Marshal.Copy(ADP_Get_ADP_EXPIRED_APPLICATIONID(), id, 0, 16); return new Guid(id); } }
public static Guid ExpiredComponentId { get { byte[] id = new byte[16]; Marshal.Copy(ADP_Get_ADP_EXPIRED_COMPONENTID(), id, 0, 16); return new Guid(id); } }
private static bool PerformCheck()
{
FileStream fs = new FileStream(System.Windows.Forms.Application.StartupPath + "\\AdpWrapper.dll", FileMode.Open, FileAccess.Read);
if (fs == null) return false;
byte[] buf = new byte[(int)fs.Length];
fs.Read(buf, 0, buf.Length);
fs.Close();
SHA256 hash = SHA256.Create();
string str = BitConverter.ToString(hash.ComputeHash(buf));
return str.Equals("95-60-40-A3-12-B3-E2-94-92-32-5A-54-5D-53-FD-EC-BD-DD-8F-EF-3C-87-B2-3B-40-8B-1E-55-05-37-D7-31");
}
}
Ok, so pretty easy so far. You create that C# wrapper class and when you call methods it forward the call into the AdpWrapper.dll. Now, there is still a problem. Someone could swap the wrapper.dll with another one. This is always going to be possible, but we can make it a little more difficult by running a hash on the DLL. The PerformCheck method runs a SHA256 integrity hash on the DLL and returns the result. You then have to hard code the result you expect. Unless your AdpWrapper.dll is byte-per-byte identical to my version, you will get a different hash. That's ok, I just put a break point at the last line, copy the computed hash and paste it in the code. Ok, that's it. It should take no more than 30 minutes to do and there are probably other ways of doing this, just don't forget to run the hash at the end.
Happy coding!
Ylian 
Comments
Yes, you put the .DLL in the same folder as your executable. It should find it and make the calls. I am still working on an issue with this system. Seems the app store gives 4 small-endian values, so you have to reverse each group of four bytes. I am still working on getting things confirmed.
I think we have the option to add our Application GUID in the wrapper.It might compile successfully but might not run as mentioned in one of the IADP forum. The application GUID can be used only to submit.
Thanks,
Vijay
Hello All,
as shown in the SDK example applications the IADP currently expects that software will be written in C or C++ and has the SDK code integrated directly into the submitted application/component binary.
The whole "wrapper" discussion started as a technical workaround to enable the use of other programming languages and runtimes but this has not been officially approved for validation.
As the community feedback seems to be that wrappers are wanted for more flexibility we currently discuss if wrapper can be accepted. There are serious security concerns and other issues. A statement will be posted into the SDK forum once we made a decision. Please continue discussions about wrappers in the SDK forum.
Best Regards,
Andre B.
Intel® Atom™ Developer Program
Hi Andre,
I tried using the Wrapper dll in my visual studio vb.net/c#.net windows application using the Default debug id and wrote the ADP_Initialize.
This way i get the response and request in the start ATDS.
I hop that i am right in integrating the ATOM SDK with my project. What are all the other validation? I just replaced the original GUID from my application in the dashboard. the application doesn't initialize as i saw in a forum, the debug mode will work and for the original GUID, it won't initialize, still we can submit to the Intel ATOM store.
If a end user doesn't get the genuine app from INTEL ATOM Store, then we will not be able to initialize the SDK through the code. so we will give the end user a message as "this is not properly installed from Intel ATOM store, please contact intel Atom or the provider of the application" and exit the application.
I hope the above steps are right?
Thanks,
Vijay
Hi,
We required AdpWrapper.dll for making this c# wrapper class to work.
As of now we don’t have c / c++ environment to make this AdpWrapper.dll . Please Help.
{
public enum ReturnCode
{
ADP_FAILURE = -1,
ADP_SUCCESS,
ADP_NOT_INITIALIZED,
ADP_NOT_AVAILABLE,
ADP_INCOMPATIBLE_VERSION,
ADP_ERR_DATA_TOO_BIG,
ADP_AUTHORIZED,
ADP_NOT_AUTHORIZED,
ADP_AUTHORIZATION_EXPIRED,
ADP_NO_APP_BEGIN_EVENT
}
[DllImport("AdpWrapper.dll")]
private static extern ReturnCode ADP_Initialize();
[DllImport("AdpWrapper.dll")]
private static extern ReturnCode ADP_Close();
Hi,
Can anybody reply to priya's post :
or can anybody make this project / AdpWrapper.dll for download ?
Can Anybody make this Adpwrapper.dll for download?
can i simply copy paste above code to .dll file?
Hello Vijay,
if your software works fine with in debug version, just implement the GUID from the Dashboard, recompile and submit it for validation.
Thats all you need to do.
The error messages looks good, just include a link to this website or your EMail address for support.
Best Regards,
Andre B.
Intel® Atom™ Developer Program
Hi,
Since there is so much work going in for building .net applications for IADP, although we have no support right now from the SDK. If someone could write a hellow world program and publish it here or as a seperate blog, it just adds the fire under the kettle to see .net apps on IADP.
Cheers!
Pages