Hi, My app is a CGI running on Windows2012 (IIS 7.0), it needs to save a file to a remote UNC or Mapped drive, but when I check using DirectoryExists in both cases I get False, but of course the UNC and mapped drive exists.
Any hint?.
Regards,

Mailing lists / lazarus / 2016-05
6 messages · 4 people · –
Reply by email Subscribe to this list Your subscription
Read-only archive. Use j and k to move between messages.
Hi, My app is a CGI running on Windows2012 (IIS 7.0), it needs to save a file to a remote UNC or Mapped drive, but when I check using DirectoryExists in both cases I get False, but of course the UNC and mapped drive exists.
Any hint?.
Regards,
Does it fail only for the root UNC path but works for a path that contains a folder component?
DirectoryExists internally uses GetFileAttributes WinAPI, which states:
If you call GetFileAttributes for a network share, the function fails, and GetLastError returns ERROR_BAD_NETPATH. You must specify a path to a subfolder on that share.
https://msdn.microsoft.com/en-us/library/windows/desktop/aa364944%28v=vs.85%29.aspx
Denis
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20160525/a833eef8/attachment.html>
Hi, My app is a CGI running on Windows2012 (IIS 7.0), it needs to save a file to a remote…
El 24/05/2016 a las 21:46, Leonardo M. Ram? escribi?:
Not sure 100%, but I think that mapped drives only work when a user opens a desktop session. Services don't know about mapped drives. Think of it, in the same server, different users may map the same network resource with a different letter.
Instead of mapped drives I think you should use \\server\resource, and the user who runs the service that calls the CGI must have permission on that resource. If the service is run as "Local system", I don't know how to grant permission in a remote machine.
Correct. Drivemappings are user specific. You get the same if you want to run something as administrator from a mapping.
Depends on windows version, iirc on modern versions local system (or was it local service) it has no network access
Marc
El 25/05/2016 a las 21:48, Marc Weustink escribi?:
Correct. Drivemappings are user specific. You get the same if you want to run something as administrator from a mapping.
More than user specific are desktop session specific.
Depends on windows version, iirc on modern versions local system (or was it local service) it has no network access Marc
I think there is a user named "NetworkService", that at least has access to network. Obviously, it has to open the session on the remote resource.
El 26/05/16 a las 08:22, Santiago A. escribi?:
Thanks to all. The solution was to impersonate the user, then create the mapped drive by code (using the NetUseAdd function, see below), write the files to the destination drive, then NetUseDelete:
function Impersonate(const User, PW: string): Boolean;
var
LogonType : Integer;
LogonProvider : Integer;
TokenHandle : THandle;
strAdminUser : string;
strAdminDomain : string;
strAdminPassword : string;
begin
LogonType := LOGON32_LOGON_INTERACTIVE;
LogonProvider := LOGON32_PROVIDER_DEFAULT;
strAdminUser := USER;
strAdminDomain := '';
strAdminPassword := PW;
Result := LogonUser(PChar(strAdminUser), nil,
PChar(strAdminPassword), LogonType, LogonProvider, TokenHandle);
if Result then
begin
Result := ImpersonateLoggedOnUser(TokenHandle);
end;
end;
function NetUseAdd(const LocalName, RemoteName, UserName, Password:
string; var AccessName: string): DWord;
var
netResource: TNetResource;
dwResult, dwBufSize, dwFlags: DWORD;
hRes: DWORD;
buf: array[0..1024] of Char;
begin
dwFlags := CONNECT_REDIRECT;
ZeroMemory(@netResource, sizeof(TNetResource));
with netResource do begin
dwType := RESOURCETYPE_DISK;
lpLocalName := PAnsiChar(LocalName);
lpRemoteName := PAnsiChar(RemoteName);
lpProvider := nil;
end;
dwBufSize := Sizeof(buf);
result := WNetUseConnection(0, netResource, PAnsiChar(Password),
PAnsiChar(UserName), dwFlags, buf, dwBufSize, dwResult);
if hRes = NO_ERROR then
AccessName := buf;
end;
function NetUseDelete(const LocalName: string): Boolean;
var
hRes: DWORD;
begin
hRes := WNetCancelConnection2(PChar(LocalName),
CONNECT_UPDATE_PROFILE, true);
result := (hres = NO_ERROR);
end;To use these:
var
lAccess: string;
begin
if Impersonate('user', 'pass') then
begin
NetUseAdd('X:', '\\server\directory', 'remoteuser', 'remotepass',
lAccess);
// write files to X:\
NetUseDelete('X:');
end;
end;Regards,