Sharing Folders

From NSIS Wiki

Description

These macros will share a folder on the local network giving either full access (1st macro) or user-specified permissions on a per-user level (2nd macro)

Macro

These macros has been tested in Windows 2000 and XP and should be working in Windows NT and 2003 as well.

(1st macro) doesn't properly work on Windows 2008.

(2nd macro) works on Windows 2008.

Header and definitions

# Header Files
  !include "LogicLib.nsh"
 
# Definitions and user flags
  !define STYPE_DISKTREE                  0
  !define ACCESS_READ                     0x01
  !define ACCESS_WRITE                    0x02
  !define ACCESS_CREATE                   0x04
  !define ACCESS_EXEC                     0x08
  !define ACCESS_DELETE                   0x10
  !define ACCESS_ATRIB                    0x20
  !define ACCESS_PERM                     0x40
  !define ACCESS_ALL                      0x7F
  !define GENERIC_READ                    0x80000000
  !define GENERIC_WRITE                   0x40000000
  !define GENERIC_EXECUTE                 0x20000000
  !define GENERIC_ALL                     0x10000000
  !define NO_INHERITANCE                  0x0
  !define SECURITY_DESCRIPTOR_REVISION    1
# ACCESS_MODE values
  !define NOT_USED_ACCESS                       0
  !define GRANT_ACCESS                          1
  !define SET_ACCESS                            2
  !define DENY_ACCESS                           3
  !define REVOKE_ACCESS                         4
  !define SET_AUDIT_SUCCESS                     5
  !define SET_AUDIT_FAILURE                     6
# MULTIPLE_TRUSTEE_OPERATION values
  !define NO_MULTIPLE_TRUSTEE                   0
  !define TRUSTEE_IS_IMPERSONATE                1
# TRUSTEE_FORM values
  !define TRUSTEE_IS_SID                        0
  !define TRUSTEE_IS_NAME                       1
  !define TRUSTEE_BAD_FORM                      2
  !define TRUSTEE_IS_OBJECTS_AND_SID            3
  !define TRUSTEE_IS_OBJECTS_AND_NAME           4
# TRUSTEE_TYPE values
  !define TRUSTEE_IS_UNKNOWN                    0
  !define TRUSTEE_IS_USER                       1
  !define TRUSTEE_IS_GROUP                      2
  !define TRUSTEE_IS_DOMAIN                     3
  !define TRUSTEE_IS_ALIAS                      4
  !define TRUSTEE_IS_WELL_KNOWN_GROUP           5
  !define TRUSTEE_IS_DELETED                    6
  !define TRUSTEE_IS_INVALID                    7
  !define TRUSTEE_IS_COMPUTER                   8
# Structure Definitions
  !define strSHARE_INFO_2 '(w,i,w,i,i,i,w,w)i'
  !define strSHARE_INFO_502 '(w,i,w,i,i,i,w,w,i,i)i'
  !define strEXPLICIT_ACCESS '(i,i,i,i,i,i,i,i)i'

Macro 1 [basic share]

!macro CreateNewFullShare SHARENAME SHARE_TYPE SHARE_COMMENT SHARE_PERMISSIONS MAX_USERS CURRENT_USES SHARE_PATH SHARE_PASS
  System::Call /NOUNLOAD '*${strSHARE_INFO_2}("${SHARENAME}",${SHARE_TYPE},"${SHARE_COMMENT}",${SHARE_PERMISSIONS},${MAX_USERS},${CURRENT_USES},"${SHARE_PATH}","${SHARE_PASS}")i.R0'
  System::Call /NOUNLOAD 'netapi32::NetShareAdd(,i 2,i R0,*i .R1)i .r1'
  ${If} $1 = 2118
    MessageBox MB_OK|MB_ICONSTOP|MB_TOPMOST 'Folder "${SHARE_PATH}" has already been shared!'
  ${EndIf}
  ${If} $1 <> 0
  ${AndIf} $1 <> 2118
    MessageBox MB_OK|MB_ICONSTOP|MB_TOPMOST 'There was an error creating the share!'
  ${EndIf}
  System::Free $R0
!macroend

Usage

Use the above macro from your NSIS installer if you want to create a share with full access for everyone

!insertmacro CreateNewFullShare "Share Name" ${STYPE_DISKTREE} "Share Description" 0 -1 0 "X:\<folder_to_share>" ""

Macro 2 [advanced share]

!macro CreateNewShare  ACCOUNTNAME ACCOUNTTYPE SHARENAME SHARE_TYPE SHARE_COMMENT SHARE_PERMISSIONS ACL_ACCESS MAX_USERS CURRENT_USES SHARE_PATH SHARE_PASS
# Get the user's SID from the username
  System::Call /NOUNLOAD '*(&w${NSIS_MAX_STRLEN})i.R9'
  System::Call /NOUNLOAD 'advapi32::LookupAccountNameA(,t "${ACCOUNTNAME}",i R9,*i ${NSIS_MAX_STRLEN},w .R8,*i ${NSIS_MAX_STRLEN},*i .r4)i.r5'
  System::Call /NOUNLOAD 'advapi32::ConvertSidToStringSid(i R9,*t .R8)i.r5'
${If} $R8 == ''
  MessageBox MB_OK|MB_ICONSTOP|MB_TOPMOST 'User "${ACCOUNTNAME}" does not exist!$\nAborting...'
  System::Free $R9
  Quit
${EndIf}
# Create an EXPLICIT_ACCESS structure and place it on $R6
  System::Call /NOUNLOAD '*${strEXPLICIT_ACCESS}(${ACL_ACCESS},${SET_ACCESS},${NO_INHERITANCE},0,${NO_MULTIPLE_TRUSTEE},${TRUSTEE_IS_SID},${ACCOUNTTYPE},$R9).R6'
  System::Call /NOUNLOAD 'advapi32::SetEntriesInAclA(i 1,i R6,,*i .R5)i.r1'
  ${If} $1 <> 0
    System::Free $R9
    System::Free $R6
    Quit
  ${EndIf}
# Create an empty security descriptor and place it in R4.
  System::Alloc ${NSIS_MAX_STRLEN}
  Pop $R4
  System::Call /NOUNLOAD 'advapi32::InitializeSecurityDescriptor(i R4,i ${SECURITY_DESCRIPTOR_REVISION})i.r1'
  ${If} $1 == 0
    System::Free $R9
    System::Free $R6
    System::Call 'kernel32::LocalFree(i R5)i.r0'
    Quit
  ${EndIf}
# Add the ACL to the security descriptor
  System::Call /NOUNLOAD 'advapi32::SetSecurityDescriptorDacl(i R4,i 1,i R5,i 0)i.r1'
  ${If} $1 == 0
    System::Free $R9
    System::Free $R6
    System::Call 'kernel32::LocalFree(i R5)i.r0'
    Quit
  ${EndIf}
# Generate the structure that holds the share info and place it on $R0
  System::Call /NOUNLOAD '*${strSHARE_INFO_502}("${SHARENAME}",${SHARE_TYPE},"${SHARE_COMMENT}",${SHARE_PERMISSIONS},${MAX_USERS},${CURRENT_USES},"${SHARE_PATH}","${SHARE_PASS}",0,R4).R0'
  System::Call /NOUNLOAD 'netapi32::NetShareAdd(, i 502, i R0, *i .R1) i .r1'
  ${If} $1 = 2118
    MessageBox MB_OK|MB_ICONSTOP|MB_TOPMOST 'Folder "${SHARE_PATH}" has already been shared!'
  ${EndIf}
  ${If} $1 <> 0
  ${AndIf} $1 <> 2118
    MessageBox MB_OK|MB_ICONSTOP|MB_TOPMOST 'There was an error creating the share!'
  ${EndIf}
# Cleanup
  System::Free $R9
  System::Free $R6
  System::Call 'kernel32::LocalFree(i R5)i.r0'
  System::Free $R0
!macroend

Usage

Use the above macro from your NSIS installer if you want to create a share with read access for user jdoe

!insertmacro CreateNewShare "jdoe" ${TRUSTEE_IS_USER} "Name for the share" ${STYPE_DISKTREE} "share description" ${ACCESS_ALL} ${GENERIC_READ}|${GENERIC_EXECUTE} -1 0 "X:\<folder_to_share>" ""

Use the above macro from your NSIS installer if you want to create a share with read access for everyone (even on Windows 2008)

!insertmacro CreateNewShare "Everyone" ${TRUSTEE_IS_GROUP} "Name for the share" ${STYPE_DISKTREE} "share description" ${ACCESS_ALL} ${GENERIC_READ}|${GENERIC_EXECUTE} -1 0 "X:\<folder_to_share>" ""

Macro 3 [remove share]

!macro RemoveShare SHARENAME
  System::Call /NOUNLOAD 'netapi32::NetShareDel(, w "${SHARENAME}",i 0) i .r1'
  ${If} $1 <> 0
    MessageBox MB_OK|MB_ICONSTOP|MB_TOPMOST 'There was an error removing the share!"'
  ${EndIf}
!macroend

Usage

Use the above macro from your NSIS installer if you want to remove a share with name ShareName

!insertmacro RemoveShare "ShareName"

Resources and Links

API Functions used:

CancerFace

Personal tools
donate