- NSIS Discussion
- Problem with System::Call
Archive: Problem with System::Call
AxelMock
20th April 2007 16:31 UTC
Problem with System::Call
Hi,
I'm having a problem with a System::Call to an external DLL.
What I want to do is to port an existing InstallShield installer
for a driver to NSIS.
I've read the Readme, studied several examples but can't found what's wrong.
In a custom action of IS a SetupAPI calls are performed to copy/uninstall
an OEM inffile.
SetupCopyOEMInf/SetupUninstallOEMInf are declared as follows:
BOOL WINAPI SetupCopyOEMInf(
PCTSTR SourceInfFileName,
PCTSTR OEMSourceMediaLocation,
DWORD OEMSourceMediaType,
DWORD CopyStyle,
PTSTR DestinationInfFileName,
DWORD DestinationInfFileNameSize,
PDWORD RequiredSize,
PTSTR DestinationInfFileNameComponent
);
BOOL SetupUninstallOEMInf(
PCWSTR InfFileName,
DWORD Flags,
PVOID Reserved
);
I translated these into:
!define SETUP_COPY_OEM_INFA "SetupAPI::SetupCopyOEMInfA (t, t, i, i, *t, i, i, *t) i"
!define SETUP_UNINSTALL_OEM_INFA "SetupAPI::SetupUninstallOEMInfA (t, i, *i) i"
with the calls being:
System::Call '${SETUP_COPY_OEM_INFA} (r0,,0, 2, .r2, ${NSIS_MAX_STRLEN},, )'
System::Call "${SETUP_UNINSTALL_OEM_INFA} i(r1, 1, 0) .r3"
These calls don't work. :-(
I don't even get a return value except for "error" from GetLastError....
I've added Dumpstate::debug calls and MessageBox output to see stack and variables,
but it seems that the call is aborted before setting any return code.
Can somebody point out what I'm doing wrong?
I do have "SetPluginUnload alwaysoff" and "SetPluginUnload manual" and "System::Free 0"
of course, globally/in the respective section.
If I get this working I can start work on a NSIS module implementing/using
Microsoft DIF (Driver Installation Framework), which would really simplify
driver installations.
Here are the relevant code snippets:
Quote:
Function RegisterInf ;prototype BOOL WINAPI SetupCopyOEMInf( ; PCTSTR SourceInfFileName, ; PCTSTR OEMSourceMediaLocation, ; DWORD OEMSourceMediaType, ; DWORD CopyStyle, ; PTSTR DestinationInfFileName, ; DWORD DestinationInfFileNameSize, ; PDWORD RequiredSize, ; PTSTR DestinationInfFileNameComponent ;); Exch $0 ; passed path to inf file Push $1 Push $2 Push $3
SetOutPath $SYSDIR ${GetFileName} $0 $1 ; get filename part of path Dumpstate::debug System::Call '${SETUP_COPY_OEM_INFA} (r0,,0, 2, .r2, ${NSIS_MAX_STRLEN},, )' Dumpstate::debug Call CheckError
; return code is in $3 MessageBox MB_ICONINFORMATION|MB_OK "SetupCopyOEMInf ($0 / $2) returned $3 " IntCmp $3 0 WriteToReg StrCpy $2 "" WriteToReg: ; result is in $2 WriteRegStr ${NSIS_REGISTRY_ROOT} "Software\${OEM}\${PRODUCT}" "$1" "$2"
Pop $3 Pop $2 Pop $1 Exch $0
FunctionEnd
Function un.RegisterInf ;prototype BOOL SetupUninstallOEMInf( ; PCWSTR InfFileName, ; DWORD Flags, ; PVOID Reserved ;); Exch $0 ; passed path inf file name Push $1 Push $2 Push $3
; result is in $1 ReadRegStr $1 ${NSIS_REGISTRY_ROOT} "${NSIS_REGISTRY_PRODUCTPATH}" "$0" ${un.GetFileName} $1 $2 ; get filename part of path
StrCmp $OSVersion 'W2K' Case_W2K
System::Call "${SETUP_UNINSTALL_OEM_INFA} i(r1, 1, 0) .r3" ; return code is in $3 MessageBox MB_ICONINFORMATION|MB_OK "SetupUninstallOEMInfA ($0 / $1) returned $3 " StrCpy $0 $3 IntCmp $3 0 Done goto Done
Case_W2K: StrCpy $0 "" SetFileAttributes $1 FILE_ATTRIBUTE_NORMAL Delete $1 IfErrors 0 Done StrCpy $0 "1"
Done: Pop $3 Pop $2 Pop $1 Exch $0
FunctionEnd
Function CheckError Push $0 System::Call "Kernel32::GetLastError ()i ().r0" Dumpstate::debug MessageBox MB_ICONINFORMATION|MB_OK "Error code: $0 " Pop $0 FunctionEnd Call in section:
: StrCpy $0 "$INSTDIR\${MY_DRIVERNAME}.inf" Push $0 Call RegisterInf Pop $R0 IntCmpU $R0 0 InfError InfError : |
CancerFace
20th April 2007 16:55 UTC
Have a look at SetupCopyOEMInf and SetupUninstallOEMInf
I would define the calls as:
System::Call 'Setupapi.dll::SetupCopyOEMInfA(t r1,t r2,i r3, i r4,*t .r5,i r6,*i .r7,*t .r8)i.r9'
System::Call 'Setupapi.dll::SetupUninstallOEMInfA(t R1,i R2,)i.R3'
So in your case it would become
System::Call 'Setupapi.dll::SetupCopyOEMInfA(t r0,t "",i 0, i 2,*t .r2,i ${NSIS_MAX_STRLEN},*i .r3,*t .r4)i.R0'
System::Call 'Setupapi.dll::SetupUninstallOEMInfA(t r1,i 2,)i.R1'
The first one should give you 1 (success) or 0 (fail) on $R0 and the second one should give you 1 (success) or 0 (fail) on $R1 and GetLastError will give you extended info in either case
Hope this helps
CF
PS note that you should have admin privileges to call these functions, so you may want to add the appropriate code to make sure that the user running your app has sufficient privileges.
AxelMock
26th April 2007 08:49 UTC
Hi,
thanks to your example i was able to resolve the problem.
Originally posted by CancerFace
Have a look at SetupCopyOEMInf and SetupUninstallOEMInf
Although the calls do NOT return the values in the variables as described by MS, using Dumpstate::debug I was able to find out which variables to use.
No I'm out for implementing the interface to DIF.
Regards,
Axel