source: trunk/src/kernel32/initsystem.cpp@ 21535

Last change on this file since 21535 was 21535, checked in by dmik, 15 years ago

Deduce Windows Time Zone information from the TZ environment variable.

File size: 13.3 KB
Line 
1/* $Id: initsystem.cpp,v 1.28 2001-06-27 13:35:46 sandervl Exp $ */
2/*
3 * Odin system initialization (registry, directories & environment)
4 *
5 * Called from the WarpIn install program to create the desktop directories and
6 * to setup the registry
7 *
8 * Copyright 1999-2000 Sander van Leeuwen (sandervl@xs4all.nl)
9 *
10 * Project Odin Software License can be found in LICENSE.TXT
11 */
12
13#include <os2win.h>
14#include <ctype.h>
15#include <string.h>
16#include "winreg.h"
17#include "global.h"
18#include "winnt.h"
19#include "winerror.h"
20#include "winreg.h"
21#include "debugtools.h"
22#include "cpuhlp.h"
23#include <odininst.h>
24#include <win/options.h>
25#include <win/winnls.h>
26#include "directory.h"
27#include <versionos2.h>
28
29#define DBG_LOCALLOG DBG_initsystem
30#include "dbglocal.h"
31
32
33//******************************************************************************
34//******************************************************************************
35//Environment variables created by Windows NT:
36//
37//COMPUTERNAME=NTBAK
38//ComSpec=E:\WINNT\system32\cmd.exe
39//CPU=i386
40//HOMEDRIVE=E:
41//HOMEPATH=\
42//LOGONSERVER=\\NTBAK
43//NUMBER_OF_PROCESSORS=2
44//OS=Windows_NT
45//PATHEXT=.COM;.EXE;.BAT;.CMD
46//PROCESSOR_ARCHITECTURE=x86
47//PROCESSOR_IDENTIFIER=x86 Family 6 Model 6 Stepping 5, GenuineIntel
48//PROCESSOR_LEVEL=6
49//PROCESSOR_REVISION=0605
50//SystemDrive=E:
51//SystemRoot=E:\WINNT
52//USERDOMAIN=NTBAK
53//USERNAME=Sander
54//USERPROFILE=E:\WINNT\Profiles\Sander
55//windir=E:\WINNT
56//******************************************************************************
57void InitEnvironment(int nrcpus)
58{
59 char buffer[64];
60 char buffer1[32];
61 char *windir;
62 DWORD signature;
63
64 SetEnvironmentVariableA("CPU", "i386");
65 SetEnvironmentVariableA("PROCESSOR_ARCHITECTURE", "x86");
66 if(SupportsCPUID()) {
67 GetCPUVendorString(buffer1);
68 buffer1[12] = 0;
69 signature = GetCPUSignature();
70 sprintf(buffer, "x86 Family %x Model %x Stepping %x, %s", (signature >> 8)&0xf, (signature >> 4) & 0xf, signature & 0xf, buffer1);
71 SetEnvironmentVariableA("PROCESSOR_IDENTIFIER", buffer);
72 sprintf(buffer, "%x", (signature >> 8)&0xf);
73 SetEnvironmentVariableA("PROCESSOR_LEVEL", buffer);
74 sprintf(buffer, "%02x%02x", (signature >> 4)&0xf, signature & 0xf);
75 SetEnvironmentVariableA("PROCESSOR_REVISION", buffer);
76 }
77 sprintf(buffer, "%d", nrcpus);
78 SetEnvironmentVariableA("NUMBER_OF_PROCESSORS", buffer);
79 SetEnvironmentVariableA("OS", "Windows_NT");
80 SetEnvironmentVariableA("PATHEXT", ".COM;.EXE;.BAT;.CMD");
81 windir = InternalGetWindowsDirectoryA();
82 SetEnvironmentVariableA("windir", windir);
83 SetEnvironmentVariableA("SystemRoot", windir);
84 buffer[0] = windir[0];
85 buffer[1] = windir[1];
86 buffer[2] = 0;
87 SetEnvironmentVariableA("SystemDrive", buffer);
88 SetEnvironmentVariableA("HOMEDRIVE", buffer);
89 SetEnvironmentVariableA("HOMEPATH", "\\");
90
91 //TODO:
92 //COMPUTERNAME=NTBAK
93 //ComSpec=E:\WINNT\system32\cmd.exe
94 //LOGONSERVER=\\NTBAK
95 //USERDOMAIN=NTBAK
96 //USERNAME=Sander
97 //USERPROFILE=E:\WINNT\Profiles\Sander
98}
99//******************************************************************************
100//Create/change keys that may change (i.e. odin.ini keys that affect windows version)
101//******************************************************************************
102void InitDynamicRegistry()
103{
104 OSVERSIONINFOA versioninfo;
105 HKEY hkey;
106 char buf[16] = "";
107
108 versioninfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
109 GetVersionExA(&versioninfo);
110
111 //Set version key:
112 // [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ProductOptions]
113 // "ProductType"="WinNT"
114 if(RegCreateKeyA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Control\\ProductOptions",&hkey)!=ERROR_SUCCESS) {
115 dprintf(("InitRegistry: Unable to register system information (2)"));
116 return;
117 }
118 switch(versioninfo.dwPlatformId) {
119 case VER_PLATFORM_WIN32_WINDOWS:
120 strcpy(buf, "Win98"); //TODO: Correct???????????
121 break;
122 case VER_PLATFORM_WIN32_NT:
123 strcpy(buf, "WinNT"); //TODO: Also correct for Windows 2000???
124 break;
125 default:
126 DebugInt3();
127 break;
128 }
129 RegSetValueExA(hkey,"ProductType",0,REG_SZ, (LPBYTE)buf, strlen(buf)+1);
130 RegCloseKey(hkey);
131
132 // Deduce the Windows time zone from TZ
133 const char *tz = getenv("TZ");
134 if (tz == NULL) {
135 if (RegCreateKeyA(HKEY_LOCAL_MACHINE,
136 "SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation",
137 &hkey) == ERROR_SUCCESS) {
138 // use the last value
139 RegCloseKey(hkey);
140 return;
141 }
142 //default is Central European Time
143 tz = "CET-1CDT";
144 }
145
146 char *tzBuf = strdup(tz);
147 if (!tzBuf) {
148 dprintf(("InitRegistry: Unable to allocate memory"));
149 return;
150 }
151
152 TIME_ZONE_INFORMATION tzi;
153 memset(&tzi, 0, sizeof(tzi));
154 dprintf(("InitRegistry: TZ=%s", tzBuf));
155
156 int state = 0;
157 char *tok = strtok(tzBuf, ",");
158 for (; tok && state != -1; state++, tok = strtok(NULL, ",")) {
159 switch (state) {
160 case 0: {
161 // STD bias(sec) DST
162 char *s = tok;
163 while (isalpha(*s))
164 ++s;
165 if (s - tok == 3) {
166 MultiByteToWideChar(CP_ACP, 0, tok, 3, tzi.StandardName,
167 sizeof(tzi.StandardName));
168 char *fail;
169 long n = strtol(s, &fail, 10);
170 s = fail;
171 if (*s)
172 while (*s && isalpha(*s))
173 ++s;
174 if (!*s) {
175 MultiByteToWideChar(CP_ACP, 0, fail, -1, tzi.DaylightName, sizeof(tzi.DaylightName));
176 tzi.Bias = n * 60;
177 } else {
178 state = -1;
179 }
180 } else {
181 state = -1;
182 }
183 break;
184 }
185 // the rest has the following format:
186 // DST_m,DST_n,DST_w,DST_t,STD_m,STD_n,STD_w,STD_t,DST_bias
187 // where _m is month, _w is day of week, _n is the occurence
188 // of this day, _t is the time (sec)
189 case 1:
190 case 5: {
191 // month
192 char *fail;
193 long n = strtol(tok, &fail, 10);
194 if (*fail == 0 && n >= 1 && n <= 12) {
195 state == 1 ? tzi.DaylightDate.wMonth = n
196 : tzi.StandardDate.wMonth = n;
197 } else {
198 state = -1;
199 }
200 break;
201 }
202 case 2:
203 case 6: {
204 // occurence
205 char *fail;
206 long n = strtol(tok, &fail, 10);
207 if (*fail == 0 && (n >= 1 && n <= 5) || n == -1) {
208 if (n == -1)
209 n = 5; // this is what Windows expect
210 state == 2 ? tzi.DaylightDate.wDay = n
211 : tzi.StandardDate.wDay = n;
212 } else {
213 state = -1;
214 }
215 break;
216 }
217 case 3:
218 case 7: {
219 // day of week
220 char *fail;
221 long n = strtol(tok, &fail, 10);
222 if (*fail == 0 && n >= 0 && n <= 6) {
223 state == 3 ? tzi.DaylightDate.wDayOfWeek = n
224 : tzi.StandardDate.wDayOfWeek = n;
225 } else {
226 state = -1;
227 }
228 break;
229 }
230 case 4:
231 case 8: {
232 // time (sec)
233 char *fail;
234 long n = strtol(tok, &fail, 10);
235 if (*fail == 0 && n >= 0) {
236 SYSTEMTIME *t = state == 4 ? &tzi.DaylightDate
237 : &tzi.StandardDate;
238 t->wHour = n / 3600;
239 t->wMinute = (n % 3600) / 60;
240 } else {
241 state = -1;
242 }
243 break;
244 }
245 case 9: {
246 // daylight bias (sec)
247 char *fail;
248 long n = strtol(tok, &fail, 10);
249 if (*fail == 0) {
250 tzi.DaylightBias = - (n / 60);
251 } else {
252 state = -1;
253 }
254 break;
255 }
256 default:
257 state = -1;
258 break;
259 }
260 }
261
262 free(tzBuf);
263 if (state == -1 || (state != 1 && state != 10)) {
264 dprintf(("InitRegistry: Unable to parse TZ"));
265 return;
266 }
267
268 // apply the daylight bias to the standard start time
269 // (windows expects this)
270 if (tzi.DaylightBias) {
271 DWORD min = tzi.StandardDate.wHour * 60 + tzi.StandardDate.wMinute;
272 min -= tzi.DaylightBias;
273 tzi.StandardDate.wHour = min / 60;
274 tzi.StandardDate.wMinute = min % 60;
275 }
276
277 dprintf(("InitRegistry: Bias %d", tzi.Bias));
278 dprintf(("InitRegistry: StandardName '%ls'", tzi.StandardName));
279 dprintf(("InitRegistry: StandardDate %d,%d,%d,%d:%d",
280 tzi.StandardDate.wMonth, tzi.StandardDate.wDay,
281 tzi.StandardDate.wDayOfWeek,
282 tzi.StandardDate.wHour, tzi.StandardDate.wMinute));
283 dprintf(("InitRegistry: StandardBias %d", tzi.StandardBias));
284 dprintf(("InitRegistry: DaylightName '%ls'", tzi.DaylightName));
285 dprintf(("InitRegistry: DaylightDate %d,%d,%d,%d:%d",
286 tzi.DaylightDate.wMonth, tzi.DaylightDate.wDay,
287 tzi.DaylightDate.wDayOfWeek,
288 tzi.DaylightDate.wHour, tzi.DaylightDate.wMinute));
289 dprintf(("InitRegistry: DaylightBias %d", tzi.DaylightBias));
290
291 struct REG_TZI_FORMAT {
292 LONG Bias;
293 LONG StandardBias;
294 LONG DaylightBias;
295 SYSTEMTIME StandardDate;
296 SYSTEMTIME DaylightDate;
297 } rtzi, rtzitmp;
298
299 memset(&rtzi, 0, sizeof(rtzi));
300 rtzi.Bias = tzi.Bias;
301 rtzi.StandardBias = tzi.StandardBias;
302 rtzi.DaylightBias = tzi.DaylightBias;
303 rtzi.StandardDate = tzi.StandardDate;
304 rtzi.DaylightDate = tzi.DaylightDate;
305
306 DWORD bestMatch = 0;
307 if (RegOpenKeyA(HKEY_LOCAL_MACHINE,
308 "Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
309 &hkey) == ERROR_SUCCESS) {
310 DWORD idx = 0;
311 char name[256];
312 DWORD len;
313 for (;; idx++) {
314 len = sizeof(name);
315 if (RegEnumKeyExA(hkey, idx, name, &len, NULL, NULL, NULL,
316 NULL) != ERROR_SUCCESS)
317 break;
318
319 HKEY hsubkey;
320 DWORD len;
321 if (RegOpenKeyA(hkey, name, &hsubkey) == ERROR_SUCCESS) {
322 len = sizeof(rtzitmp);
323 if (RegQueryValueExA(hsubkey, "TZI", NULL, NULL,
324 (LPBYTE)&rtzitmp, &len) == ERROR_SUCCESS) {
325 DWORD match = 0;
326 if (rtzi.Bias == rtzitmp.Bias) {
327 match = 1;
328 if (rtzi.StandardBias == rtzitmp.StandardBias &&
329 rtzi.DaylightBias == rtzitmp.DaylightBias) {
330 match = 2;
331 if (memcmp(&rtzi.StandardDate, &rtzitmp.StandardDate,
332 sizeof(rtzi.StandardDate)) == 0 &&
333 memcmp(&rtzi.DaylightDate, &rtzitmp.DaylightDate,
334 sizeof(rtzi.DaylightDate)) == 0) {
335 match = 3;
336 }
337 }
338 }
339 if (match > bestMatch) {
340 len = sizeof(tzi.StandardName);
341 if (RegQueryValueExW(hsubkey, (LPCWSTR)L"Std", NULL, NULL,
342 (LPBYTE)tzi.StandardName, &len) == ERROR_SUCCESS) {
343 len = sizeof(tzi.DaylightName);
344 if (RegQueryValueExW(hsubkey, (LPCWSTR)L"Dlt", NULL, NULL,
345 (LPBYTE)tzi.DaylightName, &len) == ERROR_SUCCESS) {
346 tzi.StandardName[sizeof(tzi.StandardName) - 1] = '\0';
347 tzi.DaylightName[sizeof(tzi.DaylightName) - 1] = '\0';
348 // copy the found data over (it may be more precise)
349 tzi.Bias = rtzitmp.Bias;
350 tzi.StandardBias = rtzitmp.StandardBias;
351 tzi.DaylightBias = rtzitmp.DaylightBias;
352 tzi.StandardDate = rtzitmp.StandardDate;
353 tzi.DaylightDate = rtzitmp.DaylightDate;
354
355 bestMatch = match;
356 }
357 }
358 }
359 }
360 RegCloseKey(hsubkey);
361 }
362 }
363 RegCloseKey(hkey);
364 }
365
366 if (bestMatch) {
367 dprintf(("InitRegistry: Found Windows Time Zone (best match %d):", bestMatch));
368 dprintf(("InitRegistry: StandardName '%ls'", tzi.StandardName));
369 dprintf(("InitRegistry: DaylightName '%ls'", tzi.DaylightName));
370 } else {
371 dprintf(("InitRegistry: WARNING: Couldn't match TZ to Windows Time Zone."));
372 dprintf(("InitRegistry: Check 'HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones' key."));
373 }
374
375 SetTimeZoneInformation (&tzi);
376}
377//******************************************************************************
378//******************************************************************************
379
Note: See TracBrowser for help on using the repository browser.