diff --git a/misc/version.c b/misc/version.c
index ea09adf5e0676cf3e5b899447a55ad636c9726ba..5e5161dba7189e3a5b38a68e921fd10c8b991d03 100644
--- a/misc/version.c
+++ b/misc/version.c
@@ -88,11 +88,23 @@ static const char *WinVersionNames[NB_WINDOWS_VERSIONS] =
     "nt40"
 };
 
+/* if one of the following dlls is importing ntdll the windows
+version autodetection switches wine to unicode (nt 3.51 or 4.0) */
+static char * special_dlls[] =
+{
+	"COMDLG32",
+	"COMCTL32",
+	"SHELL32",
+	"USER32",
+	"OLE32",
+	"RPCRT4",
+	NULL
+};
+
 /* the current version has not been autodetected but forced via cmdline */
 static BOOL versionForced = FALSE;
 static WINDOWS_VERSION defaultWinVersion = WIN31;
 
-
 /**********************************************************************
  *         VERSION_ParseWinVersion
  */
@@ -132,108 +144,150 @@ void VERSION_ParseDosVersion( const char *arg )
         fprintf( stderr, "-dosver: Wrong version format. Use \"-dosver x.xx\"\n");
 }
 
-
-WINDOWS_VERSION VERSION_GetImageVersion(PDB *pdb)
+/**********************************************************************
+ *	VERSION_GetSystemDLLVersion
+ *
+ * This function tryes to figure out if a given (native) dll comes from
+ * win95/98 or winnt. Since all values in the OptionalHeader are not a 
+ * usable hint, we test if a dll imports the ntdll.
+ * This is at least working for all system-dlls like comctl32, comdlg32 and
+ * shell32.
+ * If you have a better idea to figure this out...
+ */
+DWORD VERSION_GetSystemDLLVersion (WINE_MODREF * wm)
 {
-    PIMAGE_NT_HEADERS peheader;
-
-	if (!pdb->exe_modref)
-	{
-		/* HACK: if we have loaded a PE image into this address space,
-		 * we are probably using thunks, so Win95 is our best bet
-		 */
-		if (pdb->modref_list)
-			return WIN95;
-		/* FIXME: hmm, do anything else ?
-		   TDB.version doesn't help here
-		   as it always holds version 3.10 */
-			return WIN31;
-	}
-	else
+	PE_MODREF * pem = &(wm->binfmt.pe);
+	
+	if (pem->pe_import)
 	{
-		peheader = PE_HEADER(pdb->exe_modref->module);
-#define OPTHD peheader->OptionalHeader
-
-		TRACE("%02x.%02x/%02x.%02x/%02x.%02x/%02x.%02x\n",
-			  OPTHD.MajorLinkerVersion,
-			  OPTHD.MinorLinkerVersion,
-			  OPTHD.MajorOperatingSystemVersion,
-			  OPTHD.MinorOperatingSystemVersion,
-			  OPTHD.MajorImageVersion,
-			  OPTHD.MinorImageVersion,
-			  OPTHD.MajorSubsystemVersion,
-			  OPTHD.MinorSubsystemVersion);
-
-        switch (OPTHD.MajorSubsystemVersion)
-		{
-			case 4:
-				switch (OPTHD.MajorOperatingSystemVersion)
-				{
-					case 5:
-						return NT40; /* FIXME: this is NT 5, isn't it ? */
-					case 4:
-						if ((OPTHD.MajorImageVersion == 0) &&
-							(OPTHD.SectionAlignment == 4096))
-							return WIN95;
-						else
-							return NT40;
-					case 1:
-						return WIN95;
-					default:
-						return WIN95; /* FIXME ? */
-				}
-			case 3:
-				/* 3.1x versions */
-				if (OPTHD.MinorSubsystemVersion <= 11)
-				{
-					if (OPTHD.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI)
-						return NT351; /* FIXME: NT 3.1 */
-					else
-						return WIN31;
-				}
-				else
-				{
-					/* NT 3.51 */
-					if (OPTHD.MinorSubsystemVersion == 50)
-						return NT351;
-					else
-					if (OPTHD.MinorSubsystemVersion == 51)
-						return NT351;
-				}
-			default:
-				if (OPTHD.MajorSubsystemVersion)
-				ERR("unknown subsystem version: %04x.%04x, please report.\n",
-					OPTHD.MajorSubsystemVersion,
-					OPTHD.MinorSubsystemVersion );
-				return defaultWinVersion;
-		}
-#undef OPTHD
+	  IMAGE_IMPORT_DESCRIPTOR * pe_imp;
+
+	  for ( pe_imp = pem->pe_import; pe_imp->Name; pe_imp++)
+	  {
+	    char * name = (char*)((unsigned int)wm->module+(unsigned int)(pe_imp->Name));
+	    TRACE("%s\n", name);
+	    
+	    if (!lstrncmpiA(name, "ntdll", 5))
+	    {
+	      if (3 == PE_HEADER(wm->module)->OptionalHeader.MajorOperatingSystemVersion)
+	        return NT351;
+	      else
+	        return NT40;
+	    }
+	  }
 	}
+	return WIN95;
 }
-
-
 /**********************************************************************
+ *	VERSION_GetLinkedDllVersion
+ *
+ * Some version data (not reliable!):
+ * linker/OS/image/subsys
  *
- * Check the version of COMDLG32, SHELL32, COMCTL32 and CTL3D32.
- * Not functional yet.
+ * x.xx/1.00/0.00/3.10	Win32s		(any version ?)
+ * 2.39/1.00/0.00/3.10	Win32s		freecell.exe (any version)
+ * 2.50/1.00/4.00/4.00	Win32s 1.30	winhlp32.exe	
+ * 2.60/3.51/3.51/3.51	NT351SP5	system dlls 
+ * 2.60/3.51/3.51/4.00	NT351SP5	comctl32 dll
+ * 2.xx/1.00/0.00/4.00	Win95 		system files
+ * x.xx/4.00/0.00/4.00	Win95		most applications
+ * 3.10/4.00/0.00/4.00	Win98		notepad
+ * x.xx/5.00/5.00/4.00	Win98 		system dlls
+ * x.xx/4.00/4.00/4.00	NT 4 		most apps
+ * 5.12/5.00/5.00/4.00	NT4+IE5		comctl32.dll
+ * 5.12/5.00/5.00/4.00	Win98		calc
+ * x.xx/5.00/5.00/4.00	win95/win98/NT4	IE5 files
  */
 DWORD VERSION_GetLinkedDllVersion(PDB *pdb)
 {
 	WINE_MODREF *wm;
-    WORD VersionCounter[NB_WINDOWS_VERSIONS];
+	DWORD WinVersion = NB_WINDOWS_VERSIONS;
+	PIMAGE_OPTIONAL_HEADER ophd;
 
-    memset(VersionCounter, 0, sizeof(VersionCounter));
-
-	VersionCounter[WIN95] = 1;
-	for ( wm = PROCESS_Current()->modref_list; wm; wm=wm->next ) {
-	    if (!(lstrncmpiA(wm->modname, "CTL3D32", 7)))
-			VersionCounter[WIN95]++;
+	if (!pdb->exe_modref)
+	{
+	  /* winn311 progs only link to user32 */
+	  if (pdb->modref_list && pdb->modref_list->next)
+            return WIN95;
+	  return WIN31;
+	}
+	/* First check the native dlls provided. These have to be
+	from one windows version */
+	for ( wm = pdb->modref_list; wm; wm=wm->next )
+	{
+	  ophd = &(PE_HEADER(wm->module)->OptionalHeader);
+
+	  TRACE("%s: %02x.%02x/%02x.%02x/%02x.%02x/%02x.%02x\n",
+	    wm->modname,
+	    ophd->MajorLinkerVersion, ophd->MinorLinkerVersion,
+	    ophd->MajorOperatingSystemVersion, ophd->MinorOperatingSystemVersion,
+	    ophd->MajorImageVersion, ophd->MinorImageVersion,
+	    ophd->MajorSubsystemVersion, ophd->MinorSubsystemVersion);
+
+	  /* test if it a external dll */
+	  if ( !(wm->flags & WINE_MODREF_INTERNAL) )
+	  {
+	    int i;
+	    for (i = 0; special_dlls[i]; i++)
+	    {
+	      /* test if it a special dll */
+	      if (!lstrncmpiA(wm->modname, special_dlls[i], strlen(special_dlls[i]) ))
+	      {
+	        DWORD DllVersion = VERSION_GetSystemDLLVersion(wm);
+	        if (WinVersion == NB_WINDOWS_VERSIONS) 
+	        {
+	          WinVersion = DllVersion;
+	        }
+	        else
+	        {
+	          if (WinVersion != DllVersion)
+	          {
+	            ERR("You mixed system dlls from different windows versions! Expect a chrash!\n");
+	            return WIN31; /* this may let the exe exiting */
+	          }
+	        }
+	        break;
+	      }
+	    }
+	  }
+	}
+	
+	if(WinVersion != NB_WINDOWS_VERSIONS) return WinVersion;
+	
+	/* we are using no external system dlls, look at the exe */
+	ophd = &(PE_HEADER(pdb->exe_modref->module)->OptionalHeader);
+	
+	TRACE("-%s: %02x.%02x/%02x.%02x/%02x.%02x/%02x.%02x\n",
+	    pdb->exe_modref->modname,
+	    ophd->MajorLinkerVersion, ophd->MinorLinkerVersion,
+	    ophd->MajorOperatingSystemVersion, ophd->MinorOperatingSystemVersion,
+	    ophd->MajorImageVersion, ophd->MinorImageVersion,
+	    ophd->MajorSubsystemVersion, ophd->MinorSubsystemVersion);
+
+	/* special nt 3.51 */
+	if (3 == ophd->MajorOperatingSystemVersion && 51 == ophd->MinorOperatingSystemVersion)
+	{
+	    return NT351;
 	}
 
-	return MAKELONG(WIN95, VersionCounter[WIN95]);
+	/* the MajorSubsystemVersion is the only usable singn */
+	if (ophd->MajorSubsystemVersion < 4)
+	{
+	  if ( ophd->MajorOperatingSystemVersion == 1 
+	    && ophd->MinorOperatingSystemVersion == 0)
+	  {
+	    return WIN31; /* win32s */
+	  }
+	  
+	  if (ophd->Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI)
+	    return NT351; /* FIXME: NT 3.1, not tested */
+	  else
+	    return WIN95;
+	}	
+
+	return WIN95;
 }
 
-
 /**********************************************************************
  *         VERSION_GetVersion
  *
@@ -246,42 +300,18 @@ DWORD VERSION_GetLinkedDllVersion(PDB *pdb)
  * This can happen much easier than you might think, as this function
  * is called by EVERY GetVersion*() API !
  *
- * Some version data:
- * linker/OS/image/subsys	Name			Intended for
- *
- * 2.39/1.00/0.00/3.10		freecell.exe	Win32s (any version)
- * 2.55/1.00/0.00/4.00		acrord32.exe	Win32s, Win95 supported (?)
- * 
- * 2.50/1.00/4.00/4.00		winhlp32.exe	Win32s 1.30
- * 4.20/4.00/1.00/4.00		Asuslm.exe		Win95 (Aaargh !)
- * 5.12/4.00/1.07/4.00      clikfixi.exe    NT 4 (service pack files)
- * 3.10/4.00/4.00/4.00		PLUMBING.EXE	NT
- * ?.??/4.00/97.01/4.00		sse.exe			huh ?? (damn crackerz ;)
- * 5.12/5.00/5.00/4.00		comctl32.dll	NT4 / IE 5.0
- * 6.00/5.00/5.00/4.00						NT 4 driver update (strange numbers)
- * 
- * Common versions:
- * x.xx/1.00/0.00/3.10						Win32s (any version ?)
- * 2.xx/1.00/0.00/4.00						Win95 (Microsoft/system files) 
- * x.xx/4.00/0.00/4.00						Win95 (most applications !)
- * x.xx/4.00/4.00/4.00						NT 4 (most apps)
- * x.xx/5.00/5.00/4.00						NT 4 newer files / NT 5 ??
  */
 WINDOWS_VERSION VERSION_GetVersion(void)
 {
-    PDB *pdb = PROCESS_Current();
-    DWORD DllVer;
-
-    if (versionForced) /* user has overridden any sensible checks */
-        return defaultWinVersion;
+	PDB *pdb = PROCESS_Current();
+    
+	if (versionForced) /* user has overridden any sensible checks */
+	  return defaultWinVersion;
 
-    if (pdb->winver == 0xffff) /* to be determined */
-        {
-		DllVer = 0/*VERSION_GetLinkedDllVersion(pdb)*/;
-		if (HIWORD(DllVer) > 1)
-			pdb->winver = LOWORD(DllVer);
-            else
-			pdb->winver = VERSION_GetImageVersion(pdb);
+	if (pdb->winver == 0xffff) /* to be determined */
+	{
+	  pdb->winver = VERSION_GetLinkedDllVersion(pdb);
+	  TRACE("Autodetected: %s\n", VERSION_GetVersionName());
         }
 
 	return pdb->winver;
@@ -340,8 +370,7 @@ BOOL16 WINAPI GetVersionEx16(OSVERSIONINFO16 *v)
     WINDOWS_VERSION ver = VERSION_GetVersion();
     if (v->dwOSVersionInfoSize != sizeof(OSVERSIONINFO16))
     {
-        WARN("wrong OSVERSIONINFO size from app (got: %ld, expected: %d)",
-                        v->dwOSVersionInfoSize, sizeof(OSVERSIONINFO16));
+        WARN("wrong OSVERSIONINFO size from app");
         SetLastError(ERROR_INSUFFICIENT_BUFFER);
         return FALSE;
     }