1

I developed a NDIS 6.x LWF kernel driver and wrapped it into an installer using NSIS 2.46. I found that after its installation, Windows will automatically create a system restore point named Device Driver Package Install: Nmap Project Network Service.

However, in fact it turns out that this restore point created by Windows is not good. I tried rolling back to that restore point, and my software is still there, including the driver .sys file and other modifications to the system (like creating an adapter such as Windows Loopback Adapter).

This is understandable because my installer indeed does some modifications before installing the driver, while Windows only takes the snapshot right when the driver is being installed. So my changes prior to the driver installation is not included.

So I decided to create a restore point by myself (using SysRestore provided by NSIS) before all actual installation steps of the installer.

And I want to disable Windows to automatically create the restore point for my driver. What's the best to do this? Thanks!

hsluoyz
  • 2,739
  • 5
  • 35
  • 59

3 Answers3

1

The SysRestore plug-in calls SRSetRestorePoint with BEGIN_SYSTEM_CHANGE but according to MSDN you can call it with BEGIN_NESTED_SYSTEM_CHANGE to only create one restore point. I don't know if this just applies to a single process or if it also applies to any child process you might be using to install the driver but it is perhaps worth a try. The code might look something like this:

!define MAX_DESC 64
!define MAX_DESC_W 256
!define STATEMGRSTATUS i,l
!define RESTOREPOINTINFOA i,i,l,&m${MAX_DESC}
!define RESTOREPOINTINFOW i,i,l,&w${MAX_DESC_W}
!if "${NSIS_CHAR_SIZE}" <= 1
!define RESTOREPOINTINFO "${RESTOREPOINTINFOA}"
!else
!define RESTOREPOINTINFO "${RESTOREPOINTINFOW}"
!endif
!define BEGIN_NESTED_SYSTEM_CHANGE 102
!define END_NESTED_SYSTEM_CHANGE 103
!define DEVICE_DRIVER_INSTALL 10

Section
System::Call 'KERNEL32::LoadLibrary(t "$SysDir\SrClient.dll")'
Var /Global SRSTATUS
System::Call '*(${STATEMGRSTATUS})i.s'
Pop $SRSTATUS
System::Call '*(${RESTOREPOINTINFO})(${BEGIN_NESTED_SYSTEM_CHANGE},${DEVICE_DRIVER_INSTALL},0,&t${MAX_DESC} "Installed driver XYZ")i.r0'
System::Call 'SrClient::SRSetRestorePoint(ir0,i$SRSTATUS)i.r1'
IntCmpU $1 0 "" +2 +2
    System::Call '*$SRSTATUS(${STATEMGRSTATUS})(0)' ; Make sure nStatus is ERROR_SUCCESS
System::Free $0
DetailPrint "SRSetRestorePoint(BEGIN_NESTED_SYSTEM_CHANGE) returned $1"


; TODO: Install driver here


System::Call '*$SRSTATUS(${STATEMGRSTATUS})(.r0,.r1)' ; Extract nStatus and llSequenceNumber
IntCmpU $0 0 "" norpt norpt ; Did the first call to SRSetRestorePoint succeed?
    System::Call '*(${RESTOREPOINTINFO})(${END_NESTED_SYSTEM_CHANGE},${DEVICE_DRIVER_INSTALL},r1)i.r0'
    System::Call 'SrClient::SRSetRestorePoint(ir0,i$SRSTATUS)i.r1'
    System::Free $0
    DetailPrint "SRSetRestorePoint(END_NESTED_SYSTEM_CHANGE) returned $1"
norpt:
System::Free $SRSTATUS
SectionEnd
Anders
  • 97,548
  • 12
  • 110
  • 164
  • I successfully made it using your method. But sometimes the restore point just wasn't created. Do you know why? – hsluoyz Mar 04 '16 at 14:04
  • No, I have never used this API. What does SRSetRestorePoint return when it fails? Try System::Call '*$SRSTATUS(${STATEMGRSTATUS})(.r6)' after SRSetRestorePoint, it should put the error code in $6 and DetailPrint that as well. – Anders Mar 04 '16 at 16:58
0

I don't know whether it's the best way, but you could always stop the System Restore service. In my opinion, this is a delicate issue and probably a bigger intervention than a user would expect from a driver installer.

In any case, you should communicate this to your users in advance and (re)start the service on completion.

Section
    # Stop the service
    nsExec::Exec 'net.exe STOP "srservice"'  

    # Install kernel driver
SectionEnd    

# Restore original setting
Function startSysRestore
    nsExec::Exec 'net.exe START "srservice"'  
FunctionEnd    

# Things go right
Function .onInstSuccess
    Call startSysRestore
FunctionEnd    

# Things might go wrong
Function .onUserAbort
    Call startSysRestore
FunctionEnd    

Function .onInstFailed
    Call startSysRestore
FunctionEnd

Edit: a previous version of this answer described how to disable the ServiceRestore service

idleberg
  • 12,634
  • 7
  • 43
  • 70
  • I can't stop the service. Because my installer itself still needs to create its own restore point. I guess if the service is stopped, my creation will fail? – hsluoyz Mar 03 '16 at 08:16
0

There's a few alternatives to WSR that do the same functionality (i.e. Comodo Time Machine, Shadow Defender, RollbackRx, etc) you may be better off using those to take a snapshot as I'm sure they aren't witheld by the same restrictions.