alank2 5 Posted December 4 Just now, Remy Lebeau said: Do you have the same problem if you use the WinInet API instead of the WinHTTP API? In any case, at this point does it really matter if the status text is being returned or not? It is arbitrary text determined by the server, so you shouldn't rely on it for any kind of processing logic, only for logging at best. What is important is whether the status code works or not, and it sounds like it does. My big concern isn't the status string, I can ignore it. My concern is that if that is not right, why, and what else might not be right. Share this post Link to post
alank2 5 Posted December 4 Here is some test code that shows it. From the application (returns OK properly): From the service (does not return OK properly, but an empty string instead): result 200 '' The service saves to a file "c:\5\log.txt", but you can change where it saves it if you run the code. Build the service, admin cmd prompt, go win32\debug and run project1 /install, then run net start service1. it will create the c:\5\log.txt (or what you renamed it to) with the results of the GET to google. To uninstall just do net stop service1 followed by a project1 /uninstall. test.zip Share this post Link to post
rvk 44 Posted December 4 Oops. Hadn't noticed this was C++. Because this was posted in "RTL and Delphi Object Pascal" But I'm sure someone can test and confirm this. But am I understanding it correctly that it now always runs correctly as App and only fails as Service? Does the service run as user or admin? Did you test it the other way around? 1 Share this post Link to post
alank2 5 Posted December 5 2 hours ago, rvk said: But am I understanding it correctly that it now always runs correctly as App and only fails as Service? Yes. 2 hours ago, rvk said: Does the service run as user or admin? Did you test it the other way around? I'll give this a try. Share this post Link to post
alank2 5 Posted December 5 2 hours ago, rvk said: Does the service run as user or admin? Did you test it the other way around? Good thinking!!! This is it. When the service is configured to use "Local System Account" It does NOT report "OK". If I change it to administrators or my own user name, it does report "OK". Any ideas why local system account can't retrieve the status text even though it does properly retrieve the status code? Share this post Link to post
rvk 44 Posted December 5 Fun part is that if you do "project /install" (from an admin console) it momentarily runs as administrator. It then also runs the TTimer function and does give the OK correctly. (running in a user console also gives OK but then the service doesn't get installed obviously) You didn't put the TTimer.Enabled only for running the service but for every run, so also for the /install and /uninstall runs. After actually starting the service, it'll run as limited local system account, the TTimer function runs again but now the OK is not shown 😉 So I can confirm this on Windows 10, Delphi 10.2 (object pascal). So it's really the local system account in a service that's the problem here. Might limit the search. 1 Share this post Link to post
alank2 5 Posted December 5 3 hours ago, rvk said: Fun part is that if you do "project /install" (from an admin console) it momentarily runs as administrator. It then also runs the TTimer function and does give the OK correctly. (running in a user console also gives OK but then the service doesn't get installed obviously) I noticed this as well. I don't usually use the /install or /uninstall options but instead use Inno setup and sc.exe to stop/remove/install/start services. I usually (and I don't think it is the right way as Remy pointed out to me in another thread, I still need to do some testing on it to change) implement a ServiceExecute with a message loop that runs until the service is stopped, so something like this; while (!Terminated) //do not quit if process is running until it is finished { ServiceThread->ProcessRequests(true); Sleep(250); } If I add this to the above service, it doesn't add the OK from local execution of "project1 /install", but it does for some reason for "project1 /uninstall". 4 hours ago, rvk said: You didn't put the TTimer.Enabled only for running the service but for every run, so also for the /install and /uninstall runs. How would you do this? 3 hours ago, rvk said: After actually starting the service, it'll run as limited local system account, the TTimer function runs again but now the OK is not shown 😉 So I can confirm this on Windows 10, Delphi 10.2 (object pascal). So it's really the local system account in a service that's the problem here. Might limit the search. Exactly. I know the local system account does change the environment that a service runs it as far as rights go, but I don't know what this would have a change in the WinHttpQueryHeaders(). Share this post Link to post
rvk 44 Posted December 5 39 minutes ago, alank2 said: How would you do this? Only start the timer during the start service sequence. But that's besides the point for this problem. BTW. The reason-phrase is optional in the http-protocol. See https://datatracker.ietf.org/doc/html/rfc9112#name-status-line Also it says that you should ignore it. Quote A client SHOULD ignore the reason-phrase content because it is not a reliable channel for information (it might be translated for a given locale, overwritten by intermediaries, or discarded when the message is forwarded via other versions of HTTP). A server MUST send the space that separates the status-code from the reason-phrase even when the reason-phrase is absent (i.e., the status-line would end with the space). 1 Share this post Link to post
alank2 5 Posted December 5 Thank you for the help rvk (and everyone in this thread!), instead of a loose end I now have a reason for why it is doing what it does. Going forward I'll ignore the status text always and just go with the result code. What made me nervous about this is that the status code itself is also retrieved from the same function as text and then later converted to an integer, so I'm not sure why this is an issue for status text, but not status code. Hopefully going forward it won't be. Share this post Link to post
rvk 44 Posted December 5 Your welcome. BTW. I just tested curl on a Linux machine (just for fun): Quote pi@space01:~ $ sudo curl -I http://www.google.com HTTP/1.1 200 OK Content-Type: text/html; charset=ISO-8859-1 Content-Security-Policy-Report-Only: object-src 'none';base-uri 'self';script-src 'nonce-X-ktTYexJNugET9N6Fa8vQ' 'strict-dynamic' 'report-sample' 'unsafe-eval' 'unsafe-inline' https: http:;report-uri https://csp.withgoogle.com/csp/gws/other-hp Date: Thu, 05 Dec 2024 15:15:54 GMT Server: gws X-XSS-Protection: 0 X-Frame-Options: SAMEORIGIN Transfer-Encoding: chunked Expires: Thu, 05 Dec 2024 15:15:54 GMT Cache-Control: private Set-Cookie: AEC=AZ6Zc-Xn8oa4IZiywmOCd4dkoEHyXgH7rRc_XoRQjDkCGcQkwZ6GlBvsgg; expires=Tue, 03-Jun-2025 15:15:54 GMT; path=/; domain=.google.com; Secure; HttpOnly; SameSite=lax Quote pi@space01:~ $ sudo curl -I https://www.google.com HTTP/2 200 content-type: text/html; charset=ISO-8859-1 content-security-policy-report-only: object-src 'none';base-uri 'self';script-src 'nonce-UW3w19xpBP4YYGNbmXdokw' 'strict-dynamic' 'report-sample' 'unsafe-eval' 'unsafe-inline' https: http:;report-uri https://csp.withgoogle.com/csp/gws/other-hp accept-ch: Sec-CH-Prefers-Color-Scheme p3p: CP="This is not a P3P policy! See g.co/p3phelp for more info." date: Thu, 05 Dec 2024 15:15:59 GMT server: gws x-xss-protection: 0 x-frame-options: SAMEORIGIN expires: Thu, 05 Dec 2024 15:15:59 GMT cache-control: private set-cookie: AEC=AZ6Zc-XkeaKNk-uXqoapVf2puXQG9x0eGErkTj0C7NeZElHIH5Ku75bGoA; expires=Tue, 03-Jun-2025 15:15:59 GMT; path=/; domain=.google.com; Secure; HttpOnly; SameSite=lax set-cookie: __Secure-ENID=24.SE=heUvBvT50RTq1RwovcPhzD6tBNqpGWCpwMoUorKeIKsiwMPnA-97OEpIzRkS96B2OQ5I7eldjw80PzRouMRH55s7Dl08bNfA_hmCBhHyO9tlqLtlpCx9_N1yQVaRs4CRJLk_gYhm03iSBZJl-hgxixiI64A7j2OFon6vX6MKtb4rTyh9C_DM7Vqqb_5Ei_ACoQDqDQ2Lrl2NTdeLo4T2BcG8X-iBiVGZwWyqCe8; expires=Mon, 05-Jan-2026 07:34:17 GMT; path=/; domain=.google.com; Secure; HttpOnly; SameSite=lax alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 Notice the absence of OK on the HTTPS result. HTTP did give OK 😉 HTTPS is HTTP/2 (not 1.1) so maybe we are getting HTTP/2 back. Forcing curl to do http 1.1 will give OK. sudo curl --http1.1 -I https://www.google.com But yes... you don't need to worry about the reason-phrase. It should be ignored anyway. 1 Share this post Link to post
rvk 44 Posted December 5 (edited) I've just tested with a server which can't do HTTP/2 (but only does HTTP 1.1) and it always returns OK inside the service. So I think the problem is that, when running as local system account. the HTTP/2 is requested. If it's not available, you'll get the OK. If HTTP/2 is available, there is no OK. Maybe you can test it with a server where you always get a HTTP1.1 result (and never a HTTP/2 result). You can also test this yourself by logging res.Version. I didn't test it but I'll bet you'll get version 2 back for no OK, and 1.1 for OK. THTTPProtocolVersion = (UNKNOWN_HTTP, HTTP_1_0, HTTP_1_1, HTTP_2_0); Grrr. Nope. Also not it: Quote result 200 / / HTTP_1_1 I give up 🙂 Edited December 5 by rvk 1 Share this post Link to post
Remy Lebeau 1421 Posted December 5 1 hour ago, rvk said: Notice the absence of OK on the HTTPS result. HTTP did give OK 😉 HTTPS is HTTP/2 (not 1.1) so maybe we are getting HTTP/2 back. Good catch! Per RFC 7540: https://datatracker.ietf.org/doc/html/rfc7540#section-8.1.2.4 Quote For HTTP/2 responses, a single ":status" pseudo-header field is defined that carries the HTTP status code field (see [RFC7231], Section 6). This pseudo-header field MUST be included in all responses; otherwise, the response is malformed (Section 8.1.2.6). HTTP/2 does not define a way to carry the version or reason phrase that is included in an HTTP/1.1 status line. 1 1 Share this post Link to post