Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Add Windows 2000 support #212

Closed
wants to merge 2 commits into from

6 participants

Denis Shelomovskij Jonathan M Davis Andrei Alexandrescu Adam Wilson Alex Rønne Petersen Martin Nowak
Denis Shelomovskij
  • Windows 2000 doesn't have RtlCaptureContext

RtlCaptureContext from core.sys.windows.stacktrace makes every D progrum unlaunchable on Windows 2000 for a long time (see Issue 6024).

TODO: There is no TzSpecificLocalTimeToSystemTime in Windows 2000 too. Something with it must be done in this pull.

Denis Shelomovskij

@jmdavis, is there any easy way to not use TzSpecificLocalTimeToSystemTime in std.datetime on Win2k? If there is no easy workaround, I'll just add throwing dummy to this pull.

Jonathan M Davis
Collaborator
jmdavis commented May 11, 2012

No, there is no easy way not to use it. If you do much of anything with SysTime on Windows, it's going to get called. Depending on what Win2K does, it might be possible to implement it, but that's not exactly fun. But that's really bizarre that SystemTimeToTzSpecificLocalTime is available on Win2K, but TzSpecificLocalTimeToSystemTime isn't. That's one more reason why it would be nice to just say that you need XP or newer.

Denis Shelomovskij

By the way, SysTime.fromISOExtString (from the first docs example) fails on Win2k with assert(0) or HLT instruction so lack of TzSpecificLocalTimeToSystemTime isn't a biggest problem (I haven't managed to call it from std.datetime API in five minutes).

Since std.datetime is the only module affected by Win2k I vote for restoring its partial support and marking std.datetime as "Unstable on Windows 2000 because of lack of system API in this OS".

P.S.
I'm not a fan of Win2k, but it just wasn't pleasant when its support was silently broken.

Jonathan M Davis
Collaborator
jmdavis commented May 12, 2012

Any function call on SysTime which requires converting it to its time zone rather than leaving it in UTC (which includes all of the property functions for parts of the date/time - year, hour, minute, etc. - as well as the various toXString functions, among others) will fail on Windows without TzSpecificLocalTimeToSystemTime. If you haven't been able to get it to blow up much, you haven't try very many of SysTime's functions. _dstInEffect requires TzSpecificLocalTimeToSystemTime, and _utcToTZ requires _dstInEffect, and LocalTime's and WindowsTimeZone's utcToTZ require _utcToTZ, and utcToTZ is used in SysTime's adjTime, which is called all over the place in SysTime.

If we want to mark std.datetime as not working properly on Win2K, that's fine, since it doesn't, but it's worse than unstable. SysTime is useless on Win2K if you ever want any kind of presentation time or ever care about how a time correlates to any time zone other than UTC.

Denis Shelomovskij

Another 5 minutes, no TzSpecificLocalTimeToSystemTime hit. Only other Win2K failures. My example:

import std.stdio;
import std.datetime;
void main()
{
    writeln(WindowsTimeZone.getInstalledTZNames());
    // n = 0, 2 - passes
    // n = 1, 3 - fails in tzToUTC with `assert(0) or HLT instruction`
    enum n = 1;
    auto tz = WindowsTimeZone.getTimeZone(WindowsTimeZone.getInstalledTZNames()[n]);
    auto k = tz.utcToTZ(123);
    writeln("TZ: ", k);
    writeln("UTC: ", tz.tzToUTC(k));
    readln();
}

I just want to say that even if some hero will implement TzSpecificLocalTimeToSystemTime by hands it will not help at all.

And thanks for your quick replies!

Denis Shelomovskij

Damn, I've got it just now. TzSpecificLocalTimeToSystemTime call is wrapped in try .. catch assert(0) and HLT instruction is the result of thrown exception.

May I ask why?

Jonathan M Davis
Collaborator
jmdavis commented May 12, 2012

The function the call is in is nothrow, so it can't throw, and nothing inside of that try-catch block should ever throw.

Oh, and it looks like you're not seeing as many failures as I thought that you should, because I was looking at the wrong function (SystemTimeToTzSpecificLocalTime instead of TzSpecificLocalTimeToSystemTime), but stuff is still going to fail if either of those functions is not available. And there are assertions which will fail if either of those functions fail, because they should never fail (though most of them aren't assert(0)). Those functions are required. If they're missing, you can't expect anything using them not to blow up.

Martin Nowak MartinNowak commented on the diff May 21, 2012
src/core/sys/windows/stacktrace.d
... ...
@@ -27,12 +27,61 @@ import core.stdc.stdio;
27 27
 extern(Windows)
28 28
 {
29 29
     DWORD GetEnvironmentVariableA(LPCSTR lpName, LPSTR pBuffer, DWORD nSize);
30  
-    void  RtlCaptureContext(CONTEXT* ContextRecord);
  30
+    version(Win32) // For Windows 2000 support
  31
+    {
  32
+        alias void function(CONTEXT* ContextRecord) RtlCaptureContextFunc;
  33
+
  34
+        void m_RtlCaptureContext(CONTEXT* ContextRecord)
2
Martin Nowak Collaborator
MartinNowak added a note May 21, 2012

How about adding version(D_InlineAsm_X86) in front of the function?

Denis Shelomovskij
denis-sh added a note May 21, 2012

Done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Denis Shelomovskij

By the way, TLS fixing algorithm (core.sys.windows.dll.addTlsListEntry) should fail on Windows 2000.

Denis Shelomovskij

So what we will do with Windows 2000? Personally I don't like this pull request. It makes not-very-good-looking druntime uglier. I'd like voting about this to be done. Something like:

  1. Officially announce that minimum supported Windows version is 5.1 (aka XP) since v2.053
    1. Add link like "Email @denis-sh to get D stuff with partial support for Windows 2000".
    2. Just call all Windows 2000 users dinosaurs.
  2. [A bit improve and] Merge this pull and officially announce that Windows 2000 is partially supported.
  3. Maniacally add full Windows 2000 support.
  4. Leave Issue 6024 opened forever.
Denis Shelomovskij

Oh, it's few days more than a year Windows 2000 is silently unsupported!

Andrei Alexandrescu
Owner

So should I just close this? @denis-sh sorry for neglecting your work... but probably we should go with the times and repudiate Windows 2000.

Jonathan M Davis
Collaborator

I say close it.

Adam Wilson

I would go with closing this AND Issue 6024
Windows 2000 is no longer supported by MS and is only a minute fraction of the windows install base.

Alex Rønne Petersen
Collaborator
alexrp commented July 08, 2012

I vote for just killing Windows 2000 support.

Jonathan M Davis
Collaborator

Certainly, taking the approach of saying that we only support versions of Windows that Microsoft still supports simplifies things. I'll close this then. There hasn't exactly been huge support behind keeping Win2k support when it's been discussed in the newsgroup either.

Jonathan M Davis jmdavis closed this July 08, 2012
Denis Shelomovskij

Excellent! We finally agree to stop Win2k support.
But Issue 6024 require us to note this in changelog/download pages to be closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 2 unique commits by 1 author.

May 21, 2012
Denis Shelomovskij Don't require RtlCaptureContext for Windows 2000 support
* added full-scale analog
845685e
Denis Shelomovskij Don't require TzSpecificLocalTimeToSystemTime for Windows 2000 support
* added throwing dummy
7c0fc15
This page is out of date. Refresh to see the latest.
71  src/core/sys/windows/stacktrace.d
@@ -27,12 +27,73 @@ import core.stdc.stdio;
27 27
 extern(Windows)
28 28
 {
29 29
     DWORD GetEnvironmentVariableA(LPCSTR lpName, LPSTR pBuffer, DWORD nSize);
30  
-    void  RtlCaptureContext(CONTEXT* ContextRecord);
  30
+    version(Win32) // For Windows 2000 support
  31
+    {
  32
+        alias void function(CONTEXT* ContextRecord) RtlCaptureContextFunc;
  33
+
  34
+        void m_RtlCaptureContext(CONTEXT* ContextRecord)
  35
+        {
  36
+            version(D_InlineAsm_X86) with(CONTEXT) asm
  37
+            {
  38
+                naked;
  39
+                push EBX;
  40
+                mov EBX, [ESP + 8];
  41
+
  42
+                // General-purpose registers
  43
+                mov Eax.offsetof[EBX], EAX;
  44
+                mov EAX, [ESP];
  45
+                mov Ebx.offsetof[EBX], EAX;
  46
+                mov Ecx.offsetof[EBX], ECX;
  47
+                mov Edx.offsetof[EBX], EDX;
  48
+                mov Esi.offsetof[EBX], ESI;
  49
+                mov Edi.offsetof[EBX], EDI;
  50
+                lea EAX, [EBP + 8];
  51
+                mov Esp.offsetof[EBX], EAX;
  52
+                mov EAX, [EBP];
  53
+                mov Ebp.offsetof[EBX], EAX;
  54
+
  55
+                // Instruction pointer
  56
+                mov EAX, [EBP + 4];
  57
+                mov Eip.offsetof[EBX], EAX;
  58
+
  59
+                // Flags: push, mov, lea, and call (if a task switch does not occur)
  60
+                // doesn't affect any flags
  61
+                pushfd;
  62
+                pop dword ptr EFlags.offsetof[EBX];
  63
+
  64
+                // Segment registers
  65
+                mov SegCs.offsetof[EBX], CS;
  66
+                mov SegDs.offsetof[EBX], DS;
  67
+                mov SegSs.offsetof[EBX], SS;
  68
+                mov SegEs.offsetof[EBX], ES;
  69
+                mov SegFs.offsetof[EBX], FS;
  70
+                mov SegGs.offsetof[EBX], GS;
  71
+
  72
+                pop EBX;
  73
+                ret 0x4;
  74
+            }
  75
+            else
  76
+            {
  77
+                static RtlCaptureContextFunc f;
  78
+                if(!f)
  79
+                {
  80
+                    f = cast(RtlCaptureContextFunc)
  81
+                        GetProcAddress(GetModuleHandleA("Kernel32"), "RtlCaptureContext");
  82
+                    if(!f)
  83
+                        throw new Exception("There is no RtlCaptureContext in Windows 2000 or older");
  84
+                }
  85
+                f(ContextRecord);
  86
+            }
  87
+        }
  88
+    }
  89
+    else
  90
+        void  RtlCaptureContext(CONTEXT* ContextRecord);
31 91
 
32 92
     alias LONG function(void*) UnhandeledExceptionFilterFunc;
33 93
     void* SetUnhandledExceptionFilter(void* handler);
34 94
 }
35 95
 
  96
+version(Win32) RtlCaptureContextFunc RtlCaptureContext;
36 97
 
37 98
 enum : uint
38 99
 {
@@ -285,6 +346,14 @@ private:
285 346
         CONTEXT      c;
286 347
 
287 348
         c.ContextFlags = CONTEXT_FULL;
  349
+
  350
+        version(Win32) if(!RtlCaptureContext)
  351
+        {
  352
+            if(auto f = GetProcAddress(GetModuleHandleA("Kernel32"), "RtlCaptureContext"))
  353
+                RtlCaptureContext = cast(RtlCaptureContextFunc) f;
  354
+            else
  355
+                RtlCaptureContext = &m_RtlCaptureContext;
  356
+        }
288 357
         RtlCaptureContext( &c );
289 358
 
290 359
         //x86
21  src/core/sys/windows/windows.d
@@ -917,7 +917,10 @@ export BOOL SetFileTime(HANDLE hFile, in FILETIME *lpCreationTime, in FILETIME *
917 917
 export void GetLocalTime(SYSTEMTIME* lpSystemTime);
918 918
 export BOOL SetLocalTime(SYSTEMTIME* lpSystemTime);
919 919
 export BOOL SystemTimeToTzSpecificLocalTime(TIME_ZONE_INFORMATION* lpTimeZoneInformation, SYSTEMTIME* lpUniversalTime, SYSTEMTIME* lpLocalTime);
920  
-export BOOL TzSpecificLocalTimeToSystemTime(TIME_ZONE_INFORMATION* lpTimeZoneInformation, SYSTEMTIME* lpLocalTime, SYSTEMTIME* lpUniversalTime);
  920
+version(Win32) // For Windows 2000 support
  921
+    alias extern(Windows) BOOL function(TIME_ZONE_INFORMATION* lpTimeZoneInformation, SYSTEMTIME* lpLocalTime, SYSTEMTIME* lpUniversalTime) TzSpecificLocalTimeToSystemTimeFunc;
  922
+else
  923
+    export BOOL TzSpecificLocalTimeToSystemTime(TIME_ZONE_INFORMATION* lpTimeZoneInformation, SYSTEMTIME* lpLocalTime, SYSTEMTIME* lpUniversalTime);
921 924
 export DWORD GetTimeZoneInformation(TIME_ZONE_INFORMATION* lpTimeZoneInformation);
922 925
 export BOOL SetTimeZoneInformation(TIME_ZONE_INFORMATION* lpTimeZoneInformation);
923 926
 
@@ -3365,3 +3368,19 @@ BOOL TlsFree(DWORD);
3365 3368
 HINSTANCE ShellExecuteA(HWND hwnd, LPCSTR lpOperation, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, INT nShowCmd);
3366 3369
 HINSTANCE ShellExecuteW(HWND hwnd, LPCWSTR lpOperation, LPCWSTR lpFile, LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd);
3367 3370
 }
  3371
+
  3372
+version(Win32) // For Windows 2000 support
  3373
+{
  3374
+    BOOL TzSpecificLocalTimeToSystemTime(TIME_ZONE_INFORMATION* lpTimeZoneInformation, SYSTEMTIME* lpLocalTime, SYSTEMTIME* lpUniversalTime)
  3375
+    {
  3376
+        static TzSpecificLocalTimeToSystemTimeFunc f;
  3377
+        if(!f)
  3378
+        {
  3379
+            f = cast(TzSpecificLocalTimeToSystemTimeFunc)
  3380
+                GetProcAddress(GetModuleHandleA("Kernel32"), "TzSpecificLocalTimeToSystemTime");
  3381
+            if(!f)
  3382
+                throw new Exception("There is no TzSpecificLocalTimeToSystemTime in Windows 2000 or older");
  3383
+        }
  3384
+        return f(lpTimeZoneInformation, lpLocalTime, lpUniversalTime);
  3385
+    }
  3386
+}
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.