3

Could you help me with creating Serial Check Function that bases on DLL file? Unfortunately I do not have Function Prototype.

What I have is NSIS version of the function:

SetOutPath $PLUGINSDIR
  File "serialtest.dll"
   System::Call "serialtest::_sn_serialtest(t r1) i .r2 ?u"
  ${If} $2 == 0
   Messagebox MB_OK|MB_ICONSTOP \
    "Invalid Serial Number!"
   Abort
  ${Endif}

t - text, string (LPCSTR, pointer to first character)

r1-r9 - these are $1-$9 for NSIS (can be input or output). In this case r1 is $1 and $1 is Serial Number with delimiters '-'.

i - int (includes char, byte, short, handles, pointers and so on)

. - means no input

u - unload DLL

Additional info: NSIS Script is written in ANSI and I am using Unicode version of Inno Setup.

If possible, Serial Number should be imported from Edit Boxes - I have asked a question regarding Custom Serial Page here: CustomPage for Serial Number in Inno Setup

Community
  • 1
  • 1
RobeN
  • 5,346
  • 1
  • 33
  • 50

2 Answers2

2

I don't know NSIS at all, so the following is just an attempt of the script interpretation:

serialtest::_sn_serialtest(t r1) i .r2 ?u

I understand like this:

serialtest.dll - is the library, where the function is imported from
t - the input string typed as LPCSTR
i - integer result put into the no input variable (so just output variable)

So your prototype might looked like this:

int _sn_serialtest(
  __in LPCSTR sn
);

What am I missing here is some calling convention notation, so the following prototype might not work, if you know that the library were written in C (what are most of the NSIS plugins as I've Googled), then it's probably cdecl, like below, but it's just my guess, it might be different:

function _sn_serialtest(sn: AnsiString): Integer;
  external '_sn_serialtest@files:serialtest.dll cdecl';
TLama
  • 75,147
  • 17
  • 214
  • 392
  • 1
    Yup, this function seems to work! I have called my `SerialEdits` boxes in loop to create full serial string with delimiter '-' and then called `_sn_serialtest` function. If the result is `1`, then the serial number is correct - we can make a use from Next button function here. – RobeN May 07 '12 at 12:12
2

The other answer was accepted before I had a chance to respond so I'll just add some additional information:

While NSIS plugins use cdecl for its exported functions, System::Call by default is stdcall since it is usually used to call the WinAPI. (For cdecl you need ?c at the end)

The t type depends on the NSIS version, in the normal build it is char* and in the unicode build it is WCHAR* (t is like TCHAR, you also have w and m for WCHAR and char).

The C prototype for the function in your question is int WINAPI _sn_serialtest(LPCTSTR); and in your case LPCTSTR = LPCSTR and WINAPI = __stdcall.

Anders
  • 97,548
  • 12
  • 110
  • 164
  • The fact that the function has a underscore prefix does make me suspect that the function is really cdecl and that the system plugin is still able to call it somehow (It probably plays tricks with the stack so it does not matter that you corrupt the stack on return) – Anders May 07 '12 at 13:25
  • It is `cdecl` as with `stdcall` I get Access Violation. The `cdecl` with `String` instead of `AnsiString` causes the check always result in negative. But that is why I have pointed out that I have ANSI NSIS and UNICODE Inno Setup. In this case TLama's solution works perfectly :-) – RobeN May 07 '12 at 13:32
  • 1
    Then if you intend to keep using NSIS you should change ?u to ?uc – Anders May 07 '12 at 13:46