I'm developing my first ISAPI web module with Delphi 11.1 and WebBroker, and want to write logs to the file system. For testing purposes I made the following procedure TryWriteFile, testing if I can create a file in the WebApplicationDirectory:
procedure WriteMyFile;
var
fname: string;
fs: TFileStream;
begin
fname := TPath.Combine(WebApplicationDirectory, 'myfile.log');
fs := TFileStream.Create(fname, fmCreate or fmOpenWrite or fmShareDenyNone);
fs.Write([$54,$65,$73,$74,$0D,$0A], 6); { T e s t CR LF }
fs.Free;
end;
Now, I try calling WriteMyFile in the DefaultHandler action, but get an "access denied" Exception:
procedure TWebModule1.WebModule1DefaultHandlerAction(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
WriteMyFile; //==> exception: access denied!
Response.Content := 'no error!';
end;
When I call WriteMyFile from a separate thread instead, it works. The file is created correctly:
procedure TWebModule1.WebModule1DefaultHandlerAction(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
thr: TThread;
begin
//WriteMyFile; //==> exception: access denied!
thr := TThread.CreateAnonymousThread(WriteMyFile); //works, file is created!
thr.FreeOnTerminate := False;
thr.Start;
thr.WaitFor;
thr.Free;
Response.Content := 'no error!';
end;
So my question is: Why? Does it have something to do with Windows folder permissions? And if so, how can those be different in different threads?
My configuration
IIS configuration:
- ISAPI restrictions set to "Allow unspecified ISAPI modules"
- new application pool
MYPOOL- no managed code
- 32bit enabled (since my dll is compiled to 32bit)
- new Website "My Website"
- physical path
C:\inetpub\wwwroot\MYPOOL\with added "Modify" permission forIIS AppPool\MYPOOL - Handler Mappings: Execution allowed.
- physical path
Both IIS and Delphi 11.1 Alexandria are running on my Windows 10 machine.
I found the culprit: it was an IIS configuration problem. I didn't configure Authentication for my virtual directory (which is a different thing than Authentication for the physical path).
WriteMyFilealways works, regardless of which thread is calling it.The original behavior is still weird, though. But that "just" seems to be an IIS quirk, not related to my code (nor Delphi).
Update
Thank you Peter Wolf for providing a method to confirm this! The default Authentication for my virtual directory was
IUSR, which is exactly, whatGetUserNamespits out:So apparently, different threads can be associated with different authentication identities.