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

Last change on this file since 22018 was 22002, checked in by dmik, 13 years ago

kernel32: Derive HOMEDRIVE/HOMEPATH environment vars from HOME.

Previously it was set to the root of the drive containing KERNEL32.DLL
which led to polluting it with temporary files in some cases.

File size: 13.7 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
89 // try to derive HOMEDRIVE/HOMEPATH from HOME
90 const char *home = getenv("HOME");
91 if (home && home[0] && home[1] == ':')
92 {
93 buffer[0] = home[0];
94 buffer[1] = home[1];
95 buffer[2] = 0;
96 SetEnvironmentVariableA("HOMEDRIVE", buffer);
97 if (home[2])
98 SetEnvironmentVariableA("HOMEPATH", &home[2]);
99 else
100 SetEnvironmentVariableA("HOMEPATH", "\\");
101 }
102 else
103 {
104 SetEnvironmentVariableA("HOMEDRIVE", buffer);
105 SetEnvironmentVariableA("HOMEPATH", "\\");
106 }
107
108 //TODO:
109 //COMPUTERNAME=NTBAK
110 //ComSpec=E:\WINNT\system32\cmd.exe
111 //LOGONSERVER=\\NTBAK
112 //USERDOMAIN=NTBAK
113 //USERNAME=Sander
114 //USERPROFILE=E:\WINNT\Profiles\Sander
115}
116//******************************************************************************
117//Create/change keys that may change (i.e. odin.ini keys that affect windows version)
118//******************************************************************************
119void InitDynamicRegistry()
120{
121 OSVERSIONINFOA versioninfo;
122 HKEY hkey;
123 char buf[16] = "";
124
125 versioninfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
126 GetVersionExA(&versioninfo);
127
128 //Set version key:
129 // [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ProductOptions]
130 // "ProductType"="WinNT"
131 if(RegCreateKeyA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Control\\ProductOptions",&hkey)!=ERROR_SUCCESS) {
132 dprintf(("InitRegistry: Unable to register system information (2)"));
133 return;
134 }
135 switch(versioninfo.dwPlatformId) {
136 case VER_PLATFORM_WIN32_WINDOWS:
137 strcpy(buf, "Win98"); //TODO: Correct???????????
138 break;
139 case VER_PLATFORM_WIN32_NT:
140 strcpy(buf, "WinNT"); //TODO: Also correct for Windows 2000???
141 break;
142 default:
143 DebugInt3();
144 break;
145 }
146 RegSetValueExA(hkey,"ProductType",0,REG_SZ, (LPBYTE)buf, strlen(buf)+1);
147 RegCloseKey(hkey);
148
149 // Deduce the Windows time zone from TZ
150 const char *tz = getenv("TZ");
151 if (tz == NULL) {
152 if (RegOpenKeyA(HKEY_LOCAL_MACHINE,
153 "SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation",
154 &hkey) == ERROR_SUCCESS) {
155 // use the last value
156 RegCloseKey(hkey);
157 return;
158 }
159 //default is Central European Time
160 tz = "CET-1CDT";
161 }
162
163 char *tzBuf = strdup(tz);
164 if (!tzBuf) {
165 dprintf(("InitRegistry: Unable to allocate memory"));
166 return;
167 }
168
169 TIME_ZONE_INFORMATION tzi;
170 memset(&tzi, 0, sizeof(tzi));
171 dprintf(("InitRegistry: TZ=%s", tzBuf));
172
173 int state = 0;
174 char *tok = strtok(tzBuf, ",");
175 for (; tok && state != -1; state++, tok = strtok(NULL, ",")) {
176 switch (state) {
177 case 0: {
178 // STD bias(sec) DST
179 char *s = tok;
180 while (isalpha(*s))
181 ++s;
182 if (s - tok == 3) {
183 MultiByteToWideChar(CP_ACP, 0, tok, 3, tzi.StandardName,
184 sizeof(tzi.StandardName));
185 char *fail;
186 long n = strtol(s, &fail, 10);
187 s = fail;
188 if (*s)
189 while (*s && isalpha(*s))
190 ++s;
191 if (!*s) {
192 MultiByteToWideChar(CP_ACP, 0, fail, -1, tzi.DaylightName, sizeof(tzi.DaylightName));
193 tzi.Bias = n * 60;
194 } else {
195 state = -1;
196 }
197 } else {
198 state = -1;
199 }
200 break;
201 }
202 // the rest has the following format:
203 // DST_m,DST_n,DST_w,DST_t,STD_m,STD_n,STD_w,STD_t,DST_bias
204 // where _m is month, _w is day of week, _n is the occurence
205 // of this day, _t is the time (sec)
206 case 1:
207 case 5: {
208 // month
209 char *fail;
210 long n = strtol(tok, &fail, 10);
211 if (*fail == 0 && n >= 1 && n <= 12) {
212 state == 1 ? tzi.DaylightDate.wMonth = n
213 : tzi.StandardDate.wMonth = n;
214 } else {
215 state = -1;
216 }
217 break;
218 }
219 case 2:
220 case 6: {
221 // occurence
222 char *fail;
223 long n = strtol(tok, &fail, 10);
224 if (*fail == 0 && (n >= 1 && n <= 5) || n == -1) {
225 if (n == -1)
226 n = 5; // this is what Windows expect
227 state == 2 ? tzi.DaylightDate.wDay = n
228 : tzi.StandardDate.wDay = n;
229 } else {
230 state = -1;
231 }
232 break;
233 }
234 case 3:
235 case 7: {
236 // day of week
237 char *fail;
238 long n = strtol(tok, &fail, 10);
239 if (*fail == 0 && n >= 0 && n <= 6) {
240 state == 3 ? tzi.DaylightDate.wDayOfWeek = n
241 : tzi.StandardDate.wDayOfWeek = n;
242 } else {
243 state = -1;
244 }
245 break;
246 }
247 case 4:
248 case 8: {
249 // time (sec)
250 char *fail;
251 long n = strtol(tok, &fail, 10);
252 if (*fail == 0 && n >= 0) {
253 SYSTEMTIME *t = state == 4 ? &tzi.DaylightDate
254 : &tzi.StandardDate;
255 t->wHour = n / 3600;
256 t->wMinute = (n % 3600) / 60;
257 } else {
258 state = -1;
259 }
260 break;
261 }
262 case 9: {
263 // daylight bias (sec)
264 char *fail;
265 long n = strtol(tok, &fail, 10);
266 if (*fail == 0) {
267 tzi.DaylightBias = - (n / 60);
268 } else {
269 state = -1;
270 }
271 break;
272 }
273 default:
274 state = -1;
275 break;
276 }
277 }
278
279 free(tzBuf);
280 if (state == -1 || (state != 1 && state != 10)) {
281 dprintf(("InitRegistry: Unable to parse TZ"));
282 return;
283 }
284
285 // apply the daylight bias to the standard start time
286 // (windows expects this)
287 if (tzi.DaylightBias) {
288 DWORD min = tzi.StandardDate.wHour * 60 + tzi.StandardDate.wMinute;
289 min -= tzi.DaylightBias;
290 tzi.StandardDate.wHour = min / 60;
291 tzi.StandardDate.wMinute = min % 60;
292 }
293
294 dprintf(("InitRegistry: Bias %d", tzi.Bias));
295 dprintf(("InitRegistry: StandardName '%ls'", tzi.StandardName));
296 dprintf(("InitRegistry: StandardDate %d,%d,%d,%d:%d",
297 tzi.StandardDate.wMonth, tzi.StandardDate.wDay,
298 tzi.StandardDate.wDayOfWeek,
299 tzi.StandardDate.wHour, tzi.StandardDate.wMinute));
300 dprintf(("InitRegistry: StandardBias %d", tzi.StandardBias));
301 dprintf(("InitRegistry: DaylightName '%ls'", tzi.DaylightName));
302 dprintf(("InitRegistry: DaylightDate %d,%d,%d,%d:%d",
303 tzi.DaylightDate.wMonth, tzi.DaylightDate.wDay,
304 tzi.DaylightDate.wDayOfWeek,
305 tzi.DaylightDate.wHour, tzi.DaylightDate.wMinute));
306 dprintf(("InitRegistry: DaylightBias %d", tzi.DaylightBias));
307
308 struct REG_TZI_FORMAT {
309 LONG Bias;
310 LONG StandardBias;
311 LONG DaylightBias;
312 SYSTEMTIME StandardDate;
313 SYSTEMTIME DaylightDate;
314 } rtzi, rtzitmp;
315
316 memset(&rtzi, 0, sizeof(rtzi));
317 rtzi.Bias = tzi.Bias;
318 rtzi.StandardBias = tzi.StandardBias;
319 rtzi.DaylightBias = tzi.DaylightBias;
320 rtzi.StandardDate = tzi.StandardDate;
321 rtzi.DaylightDate = tzi.DaylightDate;
322
323 DWORD bestMatch = 0;
324 if (RegOpenKeyA(HKEY_LOCAL_MACHINE,
325 "Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
326 &hkey) == ERROR_SUCCESS) {
327 DWORD idx = 0;
328 char name[256];
329 DWORD len;
330 for (;; idx++) {
331 len = sizeof(name);
332 if (RegEnumKeyExA(hkey, idx, name, &len, NULL, NULL, NULL,
333 NULL) != ERROR_SUCCESS)
334 break;
335
336 HKEY hsubkey;
337 DWORD len;
338 if (RegOpenKeyA(hkey, name, &hsubkey) == ERROR_SUCCESS) {
339 len = sizeof(rtzitmp);
340 if (RegQueryValueExA(hsubkey, "TZI", NULL, NULL,
341 (LPBYTE)&rtzitmp, &len) == ERROR_SUCCESS) {
342 DWORD match = 0;
343 if (rtzi.Bias == rtzitmp.Bias) {
344 match = 1;
345 if (rtzi.StandardBias == rtzitmp.StandardBias &&
346 rtzi.DaylightBias == rtzitmp.DaylightBias) {
347 match = 2;
348 if (memcmp(&rtzi.StandardDate, &rtzitmp.StandardDate,
349 sizeof(rtzi.StandardDate)) == 0 &&
350 memcmp(&rtzi.DaylightDate, &rtzitmp.DaylightDate,
351 sizeof(rtzi.DaylightDate)) == 0) {
352 match = 3;
353 }
354 }
355 }
356 if (match > bestMatch) {
357 len = sizeof(tzi.StandardName);
358 if (RegQueryValueExW(hsubkey, (LPCWSTR)L"Std", NULL, NULL,
359 (LPBYTE)tzi.StandardName, &len) == ERROR_SUCCESS) {
360 len = sizeof(tzi.DaylightName);
361 if (RegQueryValueExW(hsubkey, (LPCWSTR)L"Dlt", NULL, NULL,
362 (LPBYTE)tzi.DaylightName, &len) == ERROR_SUCCESS) {
363 tzi.StandardName[sizeof(tzi.StandardName) - 1] = '\0';
364 tzi.DaylightName[sizeof(tzi.DaylightName) - 1] = '\0';
365 // copy the found data over (it may be more precise)
366 tzi.Bias = rtzitmp.Bias;
367 tzi.StandardBias = rtzitmp.StandardBias;
368 tzi.DaylightBias = rtzitmp.DaylightBias;
369 tzi.StandardDate = rtzitmp.StandardDate;
370 tzi.DaylightDate = rtzitmp.DaylightDate;
371
372 bestMatch = match;
373 }
374 }
375 }
376 }
377 RegCloseKey(hsubkey);
378 }
379 }
380 RegCloseKey(hkey);
381 }
382
383 if (bestMatch) {
384 dprintf(("InitRegistry: Found Windows Time Zone (best match %d):", bestMatch));
385 dprintf(("InitRegistry: StandardName '%ls'", tzi.StandardName));
386 dprintf(("InitRegistry: DaylightName '%ls'", tzi.DaylightName));
387 } else {
388 dprintf(("InitRegistry: WARNING: Couldn't match TZ to Windows Time Zone."));
389 dprintf(("InitRegistry: Check 'HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones' key."));
390 }
391
392 SetTimeZoneInformation (&tzi);
393}
394//******************************************************************************
395//******************************************************************************
396
Note: See TracBrowser for help on using the repository browser.