Archive: CreateNewShare macro does not allow multiple user


CreateNewShare macro does not allow multiple user
Hi,

I am using the macro CreateNewShare to share a folder. when I call this macro first time to share a folder it works fine, but a second call(To add one more user to the share folder list) for the same folder gives me an error message, Saying there was an error creating the share!

Can somebody tell me where I am going wrong.
Here is the code I am using.


!insertmacro CreateNewShare "NSADMIN" "_NS_DATA3" ${STYPE_DISKTREE} "Allows access to data" \
${ACCESS_ALL} ${GENERIC_ALL} -1 2 "D:\books" ""

!insertmacro CreateNewShare "prabhat" "_NS_DATA3"
${STYPE_DISKTREE} "Allows access to data" \
${ACCESS_ALL} ${GENERIC_ALL} -1 2 "D:\books" ""


Thanks in adv,
Prabhat.


Well, the name of the macro suggests it creates a new share, so I wouldn't guess it's also able to add new permissions to an existing one. Isn't there another macro for permissions? Maybe this macro calls another macro that does the permissions bit internally?


If you refer to this macro (taken from this thread) then it is not possible to call it twice in order to add new permissions. The macro constructs a security descriptor structure with an ACL for a user, then calls NetShareAdd to create a share. Calling the macro twice tries to create the share again, hence the error you are getting.

Without testing it, I think that you would need to modify the macro so that the generated ACL would contain more then one EXPLICIT_ACCESS structures (one for each user you want to give access to), then create the share using this ACL.

Complicated as it may sound, it is probably easier then using the Netapi32 NetShareSetInfo in order to set again the security descriptor.

Hope this helps ...
CF


Actually what I wrote is a bit misleading, as it sounds that you should construct an EXPLICIT_ACCESS structure for each user and then generate the ACL.

In fact you should create an array of EXPLICIT_ACCESS structures within the same structure.
So here is the modified macro that you can call for two users instead of one:

!macro CreateNewShare2 NAME1 NAME2 SHARENAME SHARE_TYPE SHARE_COMMENT SHARE_PERMISSIONS ACL_ACCESS MAX_USERS CURRENT_USES SHARE_PATH SHARE_PASS
# Get the 1st user's SID from NAME1
System::Call /NOUNLOAD '*(&w${NSIS_MAX_STRLEN})i.R9'
System::Call /NOUNLOAD 'advapi32::LookupAccountNameA(,t "${NAME1}",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 "${NAME1}" does not exist!$\nAborting...'
System::Free $R9
Quit
${EndIf}
# Get the 2nd user's SID from NAME2
System::Call /NOUNLOAD '*(&w${NSIS_MAX_STRLEN})i.R7'
System::Call /NOUNLOAD 'advapi32::LookupAccountNameA(,t "${NAME2}",i R7,*i ${NSIS_MAX_STRLEN},w .R8,*i ${NSIS_MAX_STRLEN},*i .r4)i.r5'
System::Call /NOUNLOAD 'advapi32::ConvertSidToStringSid(i R7,*t .R8)i.r5'
${If} $R8 == ''
MessageBox MB_OK|MB_ICONSTOP|MB_TOPMOST 'User "${NAME2}" does not exist!$\nAborting...'
System::Free $R9
System::Free $R7
Quit
${EndIf}
# Create an EXPLICIT_ACCESS structure that contains both users and place it on $R6
System::Call /NOUNLOAD '*(i ${ACL_ACCESS},i ${SET_ACCESS},i ${NO_INHERITANCE},i 0,i ${NO_MULTIPLE_TRUSTEE},i ${TRUSTEE_IS_SID},i ${TRUSTEE_IS_USER},i $R9,i ${ACL_ACCESS},i ${SET_ACCESS},i ${NO_INHERITANCE},i 0,i ${NO_MULTIPLE_TRUSTEE},i ${TRUSTEE_IS_SID},i ${TRUSTEE_IS_USER},i $R7)i.R6'
System::Call /NOUNLOAD 'advapi32::SetEntriesInAclA(i 1,i R6,,*i .R5)i.r1'
${If} $1 <> 0
System::Free $R9
System::Free $R7
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 $R7
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 $R7
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 $R7
System::Free $R6
System::Call 'kernel32::LocalFree(i R5)i.r0'
System::Free $R0
!macroend

To use this you need to supply both usernames at the same time, so in your case you should call it like this:
!insertmacro CreateNewShare2 "NSADMIN" "prabhat" "_NS_DATA3" ${STYPE_DISKTREE} "Allows access to data" ${ACCESS_ALL} ${GENERIC_ALL} -1 2 "D:\books" ""

Make sure you include the header with the definitions from the wiki page ...
Hope this helps :)
CF

Oye, Thanks a lot dear....
This forum is really great...
Actually I started solving this problem myself and created a Nsis plugin which does the same, I also borrow some ideas from your implementation for that puspose :)
I will check what you have written and will use whichever is good for my particular case...

Thanks again.
Prabhat.