Skip to content
⌘ NSIS Forum Archive

Map Share (WNetAddConnection2) Problem

5 posts

EmL#

Map Share (WNetAddConnection2) Problem

Hi,

years ago I made many things with NSIS, now my scope isn't anymore on writing install scripts. But from time to time i have some tasks, which are ideally for NSIS and at the moment I'm stuck with an implementation of WNetAddConnection2 to map a drive within NSIS. To make the connection persistant, I will also save the credentials in the windows password store (is it the correct name in english? ... control keymgr.dll).

I'd read many things about WNetAddConnection* and my starting point was this thread ...

Are you a developer who uses NSIS to distribute your application? Are you a Winamp plug-in developer who wants to use NSIS to distribute your plug-in? Have suggestions for other people like you? This is the place.


... which points me in the right direction at first. I can initially map the share, but i have 2 serious problems left:

1. My provided logon credentials are not persistent beeing saved in windows password save. When I'm logoff/on again, Explorer shows me the share with the "red cross". When clicking on it, windows aks for the credentials again.

2. If i initially map the drive, sometimes Explorer is not showing the drive, while a NET USE in a dos box tells me, that the drive is already there. Somebody in the following link tells, that ... if i send a WM_DEVICECHANGE message to windows ... Explorer will force a refresh and shows the truth. I've found something about WinMessages.nsh ... can i send such a message with that Header?



So I'm not a full time programmer geek, and maybe somebody is out there, who has a mercy with me and looks over this sample script where i translated the comments in english:

Var SHARE
Var USERNAME
Var PASSWORD
Var DRIVELETTER

RequestExecutionLevel user

; RESOURCETYPE_DISK from Winnetwk.h
; ... value there is 1 ... displayed as 0x00000001
!define RESOURCETYPE_DISK 0x00000001

; RESOURCEDISPLAYTYPE_SHARE from Winnetwk.h
; ... value there is 3 ... displayed as 0x00000003)
!define RESOURCEDISPLAYTYPE_SHARE 0x00000003

; DWFLAGS
; ... Bitmask representing the Connection Options (http://msdn.microsoft.com/en-us/library/windows/desktop/aa385413%28v=vs.85%29.aspx)
; [X] CONNECT_UPDATE_PROFILE 0x00000001 ... The network resource connection should be remembered.
; [ ] CONNECT_UPDATE_RECENT 0x00000002 ... Don't understand really that ... but as of MSDN this should not be used ?!?!?!
; [ ] CONNECT_TEMPORARY 0x00000004 ... The network connection should not be remembered.
; [X] CONNECT_INTERACTIVE 0x00000008 ... OS may interact with the user for authentication purposes.
; [ ] CONNECT_PROMPT 0x00000010 ... Don't use any default settings for user/password credentials without offer the user the opportunity to an alternative (ignored unless CONNECT_INTERACTIVE is set)
; [ ] CONNECT_REDIRECT 0x00000080 ... Don't understand really that ... but I think this shouldn't be activated!
; [ ] CONNECT_CURRENT_MEDIA 0x00000200 ... If activated, connection will be definitely established over existing connections (disables defacto DialUp secenarios etc.)
; [X] CONNECT_COMMANDLINE 0x00000800 ... System is prompting for authentication using the command line instead of a GUI (ignored unless CONNECT_INTERACTIVE is also set)
; [X] CONNECT_CMD_SAVECRED 0x00001000 ... Save Credentials in the "Credential Manager" (ignored unless CONNECT_COMMANDLINE / CONNECT_INTERACTIVE is active)
; [ ] CONNECT_CRED_RESET 0x00002000 ... Evtl. bereits vorhandene Anmeldeinformationen werden zurückgesetzt (CONNECT_COMMANDLINE muss gesetzt sein)
; Sum up the Bitmask from the used flags (those with [X]) and use it for dwFlags of the NETRESSOURCE structure.
; If CONNCET_PROMPT is active (0x00001819)... this seems to be a problem because no password isn't valid anymore!
!define DWFLAGS 0x00001809

; No really idea ... I think ${NR} is representing the NETRESSOURCE structure?!?!?!
!define NR "(i,i,i,i,t,t,t,t) .i"

Section "Main"

StrCpy $SHARE "\\192.168.10.2\temptest"
StrCpy $DRIVELETTER "X:"
StrCpy $USERNAME "sv2\temptest"
StrCpy $PASSWORD "wosAcFe_?"

; To connecting share ...
StrCpy $5 $SHARE
; To using drive letter ...
StrCpy $6 $DRIVELETTER

; No really idea ... I thin the NETRESSOURCE structure is going to be filled with life?!?!?!
System::Call "*${NR}(0,${RESOURCETYPE_DISK},${RESOURCEDISPLAYTYPE_SHARE},0,r6,r5,n,n) .r8"
MessageBox MB_OK "Debug 1. System Call:$\r$\n(Maybe this is the pointer to the NETRESSOURCE structure)$\r$\n$\r$\n$8"

; No really idea ... Seems to be something else with the NETRESSOURCE structure ... don't know what and why?!?!?!
System::Call "*$8${NR}(.r0,.r1,.r2,.r3,.r4,.r7)"
MessageBox MB_OK "Debug 2. System Call:$\r$\n(Something happens with the NETRESSOURCE structure)$\r$\n$\r$\n*$8${NR}($0, $1, $2, $3, $4, $7)"

MessageBox MB_OK 'Debug 3. System Call$\r$\n(Here the drive will be mapped)$\r$\n$\r$\nmpr::WNetAddConnection2(i r8, t "$PASSWORD", t "$USERNAME" , i ${DWFLAGS}) i .r9'
System::Call 'mpr::WNetAddConnection2(i r8, t "$PASSWORD", t "$USERNAME" , i ${DWFLAGS}) i .r9'

; Errormessage if any error occurs
StrCmp $9 0 PassErrorHandler 0
StrCmp $9 85 0 +3
MessageBox MB_OK "Error $9: The local drive $6 is already in use!"
GoTo PassErrorHandler
StrCmp $9 86 0 +3
MessageBox MB_OK "Error $9: Wrong password!"
GoTo PassErrorHandler
StrCmp $9 1219 0 +3
MessageBox MB_OK "Error $9: Windows allows only one simultaneous connection to same server per user!"
GoTo PassErrorHandler
StrCmp $9 1223 0 +3
MessageBox MB_OK "Error $9: Cancelled by user!"
GoTo PassErrorHandler
StrCmp $9 1326 0 +3
MessageBox MB_OK "Error $9: Username and/or password wrong!"
GoTo PassErrorHandler
MessageBox MB_OK "Error $9 occured (http://msdn.microsoft.com/en-us/library/windows/desktop/ms681381(v=vs.85).aspx)!"
PassErrorHandler:

System::Free $8

SectionEnd
I tried the script also with execution level admin, but this is not the problem.

Thx in advance
EmL
Anders#
Please include Windows version and NSIS version details when asking System plugin questions.

'!define NR "(i,i,i,i,t,t,t,t) .i"' is not really valid System struct syntax AFAIK. (The ".i" part at then end, should probably just be "i")

Why are you using CONNECT_COMMANDLINE? It should not be used in GUI apps...
Anders#
!include LogicLib.nsh

!if "${NSIS_PTR_SIZE}" > 4
!define /ifndef ST_P p ; NSIS 3+
!endif
!ifndef ST_P
!define ST_P i
!endif

!define RESOURCETYPE_DISK 1
!define RESOURCEDISPLAYTYPE_SHARE 3
!define CONNECT_UPDATE_PROFILE 0x00000001
!define CONNECT_INTERACTIVE 0x00000008
!define CONNECT_PROMPT 0x00000010
!define CONNECT_REDIRECT 0x00000080

!define SYSTYP_NETRESOURCE (i,i,i,i,${ST_P},${ST_P},${ST_P},${ST_P}) ; You might get away with using t and not a plain pointer type here

Section
Var /GLOBAL Share
Var /GLOBAL DriveLetter
StrCpy $Share "\\MyServer\MyShare"
StrCpy $DriveLetter "X:"
StrCpy $8 "MyUsername"
StrCpy $9 "MyPassword"


System::Call '*${SYSTYP_NETRESOURCE}(0,${RESOURCETYPE_DISK},${RESOURCEDISPLAYTYPE_SHARE},0,t "$DriveLetter",t "$Share",0,0)${ST_P}.r1' ; Create and initialize a NETRESOURCE struct

System::Call 'MPR::WNetAddConnection3(${ST_P}$HWNDPARENT, ${ST_P}r1, tr9, tr8, i ${CONNECT_INTERACTIVE}|${CONNECT_UPDATE_PROFILE}|${CONNECT_REDIRECT})i.r0' ; Play with the CONNECT_* flags here if it does not persist your connection
DetailPrint "WNetAddConnection3 returned $0"
${If} $0 = 0
System::Call '*$1${SYSTYP_NETRESOURCE}(i,i,i,i,t.r2,t.r3)' ; I could not get the system to automatically assign a letter so these are always the same as the input, if the return value is 85, try a new drive letter
DetailPrint " $2 --> $3"
${EndIf}
System::Free $1
SectionEnd

When I execute this on my system (Windows 8 AMD64, NSIS v3.0b1 x86-ansi) it prints:

WNetAddConnection3 returned 0
X: --> \\MyServer\MyShare
Completed
And it also correctly broadcasts this with me having to manually do it:

WM_DEVICECHANGE: DBT_DEVICEARRIVAL: DBT_DEVTYP_VOLUME: [DBTF_NET] X:\
EmL#
I was a few days away so i couldn't answer. But i got same results with your WNetAddConnection3 than i got with WNetAddConnection2. I can bring up the mapping, but it's newer displayed proper in credential manager, however after a logoff/logon the share is displayed with red cross in explorer, and asks me for credentials.

The crazy thing is ... if i provide the credentials after the logon into the regular displays credential form and activate the save credentials checkbox. Then they seem to be saved in the credential manager. If logging of/on again ... these credentials dont work. When looking at the credentials, they look ok.

If deleting these credentials and type the server IP into explorers addressbar, explorer is asking me for the credentials too ... and these credentials are beeing stored and are working!!! In other words: If I'm not creating the mapping programmatically, if I'm setup manual the connection ... there is no problem!

Tried with W7 Pro in company, W7 Pro at home, XP Pro in company. Also a "net use x: \\server\share password /user:domain\user /persistant:yes" only creates the share, but doesn't save the credentials.

As a server i tried a windows server and a samba cifs share ... same same! I'm a little confused now. I know, that mapping with net use years ago definitely work via commandline. Maybe it's some new sort of security settings in registry, which avoid me to save the credentials properly, but i couldn't find anything in that direction.

Maybe someone got a hint wich is pointing in the right direction ... and if I ever will find a solution (or reason of this behaviour), I'll post it here ...
Anders#
Yeah I did not really expect my version to work since it is mostly just System syntax tweaks. The big question is which flags are you supposed to pass and even if we use the correct flags can it still be broken on some versions of Windows?

You might get more help if you ask a generic question about WNetAddConnection2/3 on Stackoverflow leaving out the NSIS parts. If this is really important to you then you might want to consider contacting Microsoft support...