Mercurial > hg > xemacs-beta
annotate src/nt.c @ 5887:6eca500211f4
Prototype for X509_check_host() has changed, detect this in configure.ac
ChangeLog addition:
2015-04-09 Aidan Kehoe <kehoea@parhasard.net>
* configure.ac:
If X509_check_host() is available, check the number of arguments
it takes. Don't use it if it takes any number of arguments other
than five. Also don't use it if <openssl/x509v3.h> does not
declare it, since if that is so there is no portable way to tell
how many arguments it should take, and so we would end up smashing
the stack.
* configure: Regenerate.
src/ChangeLog addition:
2015-04-09 Aidan Kehoe <kehoea@parhasard.net>
* tls.c:
#include <openssl/x509v3.h> for its prototype for
X509_check_host().
* tls.c (tls_open):
Pass the new fifth argument to X509_check_host().
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Thu, 09 Apr 2015 14:27:02 +0100 |
parents | 4dee0387b9de |
children | e2fae7783046 |
rev | line source |
---|---|
771 | 1 /* Utility and Unix shadow routines under MS Windows (WIN32_NATIVE defined). |
428 | 2 Copyright (C) 1994, 1995 Free Software Foundation, Inc. |
2957 | 3 Copyright (C) 2000, 2001, 2002, 2004, 2005 Ben Wing. |
428 | 4 |
5 This file is part of XEmacs. | |
6 | |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5006
diff
changeset
|
7 XEmacs is free software: you can redistribute it and/or modify it |
428 | 8 under the terms of the GNU General Public License as published by the |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5006
diff
changeset
|
9 Free Software Foundation, either version 3 of the License, or (at your |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5006
diff
changeset
|
10 option) any later version. |
428 | 11 |
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5006
diff
changeset
|
18 along with XEmacs. If not, see <http://www.gnu.org/licenses/>. */ |
428 | 19 |
771 | 20 /* Authorship: |
428 | 21 |
771 | 22 Geoff Voelker (voelker@cs.washington.edu) 7-29-94 |
23 Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> | |
24 Sync'ed with Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> | |
25 (Note: Sync messages from Marc Paquette may indicate | |
26 incomplete synching, so beware.) | |
27 Synched (completely!) with Emacs 20.6 by Ben Wing, 6-23-00. | |
28 Largely rewritten by Ben Wing for XEmacs Mule support. | |
2526 | 29 Synched (completely!) with Emacs 21.0.103 by Ben Wing, 6-13-01. |
771 | 30 */ |
31 | |
32 /* This file Mule-ized by Ben Wing, 6-23-00. */ | |
428 | 33 |
34 #include <config.h> | |
35 #include "lisp.h" | |
36 | |
592 | 37 #include "buffer.h" |
872 | 38 #include "process.h" |
592 | 39 |
859 | 40 #include "sysdir.h" |
41 #include "sysfile.h" | |
428 | 42 #include "sysproc.h" |
442 | 43 #include "syspwd.h" |
859 | 44 #include "syssignal.h" |
45 #include "systime.h" | |
428 | 46 |
442 | 47 #include "syswindows.h" |
428 | 48 |
771 | 49 /* Control whether stat() attempts to determine file type and link count |
50 exactly, at the expense of slower operation. Since true hard links | |
51 are supported on NTFS volumes, this is only relevant on NT. */ | |
52 Lisp_Object Vmswindows_get_true_file_attributes; | |
428 | 53 |
771 | 54 /* Vmswindows_generate_fake_inodes; deleted */ |
55 | |
56 Fixnum mswindows_fake_unix_uid; | |
428 | 57 |
58 /* Emulate getpwuid, getpwnam and others. */ | |
59 | |
771 | 60 static struct passwd the_passwd = |
428 | 61 { |
771 | 62 "", |
63 "", | |
428 | 64 0, |
65 0, | |
66 0, | |
771 | 67 "", |
68 "", | |
69 "", | |
428 | 70 }; |
71 | |
72 uid_t | |
442 | 73 getuid (void) |
440 | 74 { |
771 | 75 return mswindows_fake_unix_uid; |
428 | 76 } |
77 | |
78 uid_t | |
442 | 79 geteuid (void) |
428 | 80 { |
771 | 81 /* Emacs 20.6 says: [[I could imagine arguing for checking to see |
82 whether the user is in the Administrators group and returning a | |
83 UID of 0 for that case, but I don't know how wise that would be | |
84 in the long run.]] */ | |
85 return mswindows_fake_unix_uid; | |
428 | 86 } |
87 | |
88 gid_t | |
442 | 89 getgid (void) |
428 | 90 { |
91 return the_passwd.pw_gid; | |
92 } | |
93 | |
94 gid_t | |
442 | 95 getegid (void) |
428 | 96 { |
97 return getgid (); | |
98 } | |
99 | |
100 struct passwd * | |
101 getpwuid (uid_t uid) | |
102 { | |
771 | 103 if (uid == mswindows_fake_unix_uid) |
440 | 104 { |
105 the_passwd.pw_gid = the_passwd.pw_uid = uid; | |
106 return &the_passwd; | |
107 } | |
108 else | |
109 return NULL; | |
428 | 110 } |
111 | |
112 struct passwd * | |
867 | 113 getpwnam (const Ibyte *name) |
428 | 114 { |
115 struct passwd *pw; | |
116 | |
117 pw = getpwuid (getuid ()); | |
118 if (!pw) | |
119 return pw; | |
120 | |
1204 | 121 if (qxestrcasecmp_i18n (name, (Ibyte *) pw->pw_name)) |
428 | 122 return NULL; |
123 | |
124 return pw; | |
125 } | |
126 | |
771 | 127 static void |
442 | 128 init_user_info (void) |
428 | 129 { |
440 | 130 /* This code is pretty much of ad hoc nature. There is no unix-like |
131 UIDs under Windows NT. There is no concept of root user, because | |
132 all security is ACL-based. Instead, let's use a simple variable, | |
133 nt-fake-unix-uid, which would allow the user to have a uid of | |
134 choice. --kkm, 02/03/2000 */ | |
135 #if 0 | |
428 | 136 /* Find the user's real name by opening the process token and |
137 looking up the name associated with the user-sid in that token. | |
138 | |
139 Use the relative portion of the identifier authority value from | |
140 the user-sid as the user id value (same for group id using the | |
141 primary group sid from the process token). */ | |
142 | |
771 | 143 TOKEN_USER sidinfo; |
144 Extbyte name[256], domain[256]; | |
145 Charcount length = sizeof (name) / XETCHAR_SIZE; | |
146 Charcount dlength = sizeof (domain) / XETCHAR_SIZE; | |
147 DWORD trash; | |
148 HANDLE token = NULL; | |
149 SID_NAME_USE user_type; | |
428 | 150 |
151 if (OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &token) | |
771 | 152 && GetTokenInformation (token, TokenUser, &sidinfo, sizeof (sidinfo), |
153 &trash) | |
154 && qxeLookupAccountSid (NULL, sidinfo.User.Sid, name, &length, | |
155 domain, &dlength, &user_type)) | |
428 | 156 { |
5000
44d7bde26046
fix compile errors, fix revert-buffer bug on binary/Latin 1 files, Mule-ize some files
Ben Wing <ben@xemacs.org>
parents:
4982
diff
changeset
|
157 the_passwd.pw_name = (CIbyte *) TSTR_TO_ITEXT_MALLOC (name); |
428 | 158 /* Determine a reasonable uid value. */ |
5000
44d7bde26046
fix compile errors, fix revert-buffer bug on binary/Latin 1 files, Mule-ize some files
Ben Wing <ben@xemacs.org>
parents:
4982
diff
changeset
|
159 if (qxestrcasecmp ((Ibyte *) the_passwd.pw_name, "administrator") == 0) |
428 | 160 { |
161 the_passwd.pw_uid = 0; | |
162 the_passwd.pw_gid = 0; | |
163 } | |
164 else | |
165 { | |
166 SID_IDENTIFIER_AUTHORITY * pSIA; | |
771 | 167 TOKEN_PRIMARY_GROUP group; |
428 | 168 |
771 | 169 pSIA = GetSidIdentifierAuthority (sidinfo.User.Sid); |
428 | 170 /* I believe the relative portion is the last 4 bytes (of 6) |
171 with msb first. */ | |
172 the_passwd.pw_uid = ((pSIA->Value[2] << 24) + | |
173 (pSIA->Value[3] << 16) + | |
174 (pSIA->Value[4] << 8) + | |
175 (pSIA->Value[5] << 0)); | |
176 /* restrict to conventional uid range for normal users */ | |
177 the_passwd.pw_uid = the_passwd.pw_uid % 60001; | |
178 | |
179 /* Get group id */ | |
180 if (GetTokenInformation (token, TokenPrimaryGroup, | |
771 | 181 &group, sizeof (group), &trash)) |
428 | 182 { |
183 SID_IDENTIFIER_AUTHORITY * pSIA; | |
184 | |
771 | 185 pSIA = GetSidIdentifierAuthority (group.PrimaryGroup); |
428 | 186 the_passwd.pw_gid = ((pSIA->Value[2] << 24) + |
187 (pSIA->Value[3] << 16) + | |
188 (pSIA->Value[4] << 8) + | |
189 (pSIA->Value[5] << 0)); | |
190 /* I don't know if this is necessary, but for safety... */ | |
191 the_passwd.pw_gid = the_passwd.pw_gid % 60001; | |
192 } | |
193 else | |
194 the_passwd.pw_gid = the_passwd.pw_uid; | |
195 } | |
196 } | |
197 /* If security calls are not supported (presumably because we | |
198 are running under Windows 95), fallback to this. */ | |
771 | 199 else if (qxeGetUserName (name, &length)) |
428 | 200 { |
5000
44d7bde26046
fix compile errors, fix revert-buffer bug on binary/Latin 1 files, Mule-ize some files
Ben Wing <ben@xemacs.org>
parents:
4982
diff
changeset
|
201 the_passwd.pw_name = (CIbyte *) TSTR_TO_ITEXT_MALLOC (name); |
44d7bde26046
fix compile errors, fix revert-buffer bug on binary/Latin 1 files, Mule-ize some files
Ben Wing <ben@xemacs.org>
parents:
4982
diff
changeset
|
202 if (qxestrcasecmp_ascii ((Ibyte *) the_passwd.pw_name, |
44d7bde26046
fix compile errors, fix revert-buffer bug on binary/Latin 1 files, Mule-ize some files
Ben Wing <ben@xemacs.org>
parents:
4982
diff
changeset
|
203 "administrator") == 0) |
428 | 204 the_passwd.pw_uid = 0; |
205 else | |
206 the_passwd.pw_uid = 123; | |
207 the_passwd.pw_gid = the_passwd.pw_uid; | |
208 } | |
209 else | |
210 { | |
771 | 211 the_passwd.pw_name = "unknown"; |
428 | 212 the_passwd.pw_uid = 123; |
213 the_passwd.pw_gid = 123; | |
214 } | |
215 | |
440 | 216 if (token) |
217 CloseHandle (token); | |
218 #else | |
219 /* Obtain only logon id here, uid part is moved to getuid */ | |
771 | 220 DWORD length = UNLEN + 1; |
221 Extbyte name[MAX_XETCHAR_SIZE * (UNLEN + 1)]; | |
222 if (qxeGetUserName (name, &length)) | |
5000
44d7bde26046
fix compile errors, fix revert-buffer bug on binary/Latin 1 files, Mule-ize some files
Ben Wing <ben@xemacs.org>
parents:
4982
diff
changeset
|
223 the_passwd.pw_name = (CIbyte *) TSTR_TO_ITEXT_MALLOC (name); |
440 | 224 else |
771 | 225 the_passwd.pw_name = "unknown"; |
440 | 226 #endif |
227 | |
771 | 228 #if 0 |
428 | 229 /* Ensure HOME and SHELL are defined. */ |
230 /* | |
231 * With XEmacs, setting $HOME is deprecated. | |
232 */ | |
771 | 233 if (egetenv ("HOME") == NULL) |
234 eputenv ("HOME=c:/"); | |
428 | 235 #endif |
236 | |
611 | 237 /* Set dir from environment variables. */ |
5000
44d7bde26046
fix compile errors, fix revert-buffer bug on binary/Latin 1 files, Mule-ize some files
Ben Wing <ben@xemacs.org>
parents:
4982
diff
changeset
|
238 the_passwd.pw_dir = (CIbyte *) qxestrdup (get_home_directory ()); |
611 | 239 /* We used to set pw_shell here, but the order is wrong (SHELL gets |
853 | 240 initted in process.c, called later in the init process) and pw_shell |
611 | 241 is not used anywhere. */ |
428 | 242 } |
243 | |
771 | 244 /* Parse the root part of file name, if present. Return length and |
867 | 245 optionally store pointer to Ibyte after root. */ |
771 | 246 static Bytecount |
867 | 247 parse_root (Ibyte *name, Ibyte **pPath) |
428 | 248 { |
867 | 249 Ibyte *start = name; |
428 | 250 |
251 if (name == NULL) | |
252 return 0; | |
253 | |
254 /* find the root name of the volume if given */ | |
255 if (isalpha (name[0]) && name[1] == ':') | |
256 { | |
257 /* skip past drive specifier */ | |
258 name += 2; | |
259 if (IS_DIRECTORY_SEP (name[0])) | |
260 name++; | |
261 } | |
262 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1])) | |
263 { | |
264 int slashes = 2; | |
265 name += 2; | |
266 do | |
267 { | |
268 if (IS_DIRECTORY_SEP (*name) && --slashes == 0) | |
269 break; | |
270 name++; | |
271 } | |
771 | 272 while (*name); |
428 | 273 if (IS_DIRECTORY_SEP (name[0])) |
274 name++; | |
275 } | |
276 | |
277 if (pPath) | |
278 *pPath = name; | |
279 | |
280 return name - start; | |
281 } | |
282 | |
283 /* Get long base name for name; name is assumed to be absolute. */ | |
867 | 284 static Ibyte * |
285 get_long_basename (Ibyte *name) | |
428 | 286 { |
771 | 287 WIN32_FIND_DATAW find_data; |
428 | 288 HANDLE dir_handle; |
771 | 289 Extbyte *nameext; |
428 | 290 |
771 | 291 /* must be valid filename, no wild cards or other invalid characters */ |
292 if (qxestrpbrk (name, "*?|<>\"")) | |
293 return 0; | |
428 | 294 |
2526 | 295 PATHNAME_CONVERT_OUT (name, nameext); |
771 | 296 dir_handle = qxeFindFirstFile (nameext, &find_data); |
428 | 297 if (dir_handle != INVALID_HANDLE_VALUE) |
298 { | |
867 | 299 Ibyte *fileint; |
771 | 300 |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
301 fileint = TSTR_TO_ITEXT_MALLOC (find_data.cFileName); |
428 | 302 FindClose (dir_handle); |
771 | 303 return fileint; |
428 | 304 } |
771 | 305 return 0; |
428 | 306 } |
307 | |
308 /* Get long name for file, if possible (assumed to be absolute). */ | |
867 | 309 Ibyte * |
310 mswindows_get_long_filename (Ibyte *name) | |
428 | 311 { |
867 | 312 Ibyte *full = mswindows_canonicalize_filename (name); |
313 Ibyte *p; | |
314 Ibyte *q; | |
771 | 315 DECLARE_EISTRING (o); |
316 Bytecount len; | |
428 | 317 |
318 /* Copy root part verbatim. */ | |
319 len = parse_root (full, &p); | |
771 | 320 eicpy_raw (o, full, len); |
428 | 321 |
771 | 322 while (p != NULL && *p) |
428 | 323 { |
867 | 324 Ibyte *component; |
771 | 325 |
428 | 326 q = p; |
771 | 327 p = qxestrchr (q, '\\'); |
428 | 328 if (p) *p = '\0'; |
771 | 329 component = get_long_basename (full); |
330 if (component) | |
428 | 331 { |
771 | 332 eicat_rawz (o, component); |
428 | 333 if (p != NULL) |
334 { | |
335 *p++ = '\\'; | |
771 | 336 eicat_ch (o, '\\'); |
428 | 337 } |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
338 xfree (component); |
428 | 339 } |
340 else | |
771 | 341 { |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
342 xfree (full); |
771 | 343 return 0; |
344 } | |
428 | 345 } |
346 | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
347 xfree (full); |
771 | 348 return eicpyout_malloc (o, 0); |
428 | 349 } |
350 | |
771 | 351 static int |
867 | 352 is_unc_volume (const Ibyte *filename) |
771 | 353 { |
867 | 354 const Ibyte *ptr = filename; |
428 | 355 |
771 | 356 if (!IS_DIRECTORY_SEP (ptr[0]) || !IS_DIRECTORY_SEP (ptr[1]) || !ptr[2]) |
357 return 0; | |
358 | |
359 if (qxestrpbrk (ptr + 2, "*?|<>\"\\/")) | |
360 return 0; | |
361 | |
362 return 1; | |
428 | 363 } |
364 | |
771 | 365 /* NOTE: Value returned is still in external format. Callers need to |
366 convert. */ | |
707 | 367 #define REG_ROOT "SOFTWARE\\XEmacs\\XEmacs" |
428 | 368 |
771 | 369 static LPBYTE |
867 | 370 nt_get_resource (Ibyte *key, LPDWORD lpdwtype) |
428 | 371 { |
372 LPBYTE lpvalue; | |
373 HKEY hrootkey = NULL; | |
374 DWORD cbData; | |
771 | 375 Extbyte *keyext; |
376 | |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
377 keyext = ITEXT_TO_TSTR (key); |
428 | 378 |
379 /* Check both the current user and the local machine to see if | |
380 we have any resources. */ | |
381 | |
771 | 382 if (qxeRegOpenKeyEx (HKEY_CURRENT_USER, XETEXT (REG_ROOT), 0, KEY_READ, |
383 &hrootkey) == ERROR_SUCCESS) | |
428 | 384 { |
385 lpvalue = NULL; | |
386 | |
771 | 387 if (qxeRegQueryValueEx (hrootkey, keyext, NULL, NULL, NULL, |
388 &cbData) == ERROR_SUCCESS | |
2367 | 389 && (lpvalue = xnew_array (BYTE, cbData)) != NULL |
771 | 390 && qxeRegQueryValueEx (hrootkey, keyext, NULL, lpdwtype, lpvalue, |
391 &cbData) == ERROR_SUCCESS) | |
392 return (lpvalue); | |
428 | 393 |
1726 | 394 if (lpvalue) |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
395 xfree (lpvalue); |
428 | 396 |
397 RegCloseKey (hrootkey); | |
398 } | |
399 | |
771 | 400 if (qxeRegOpenKeyEx (HKEY_LOCAL_MACHINE, XETEXT (REG_ROOT), 0, KEY_READ, |
401 &hrootkey) == ERROR_SUCCESS) | |
428 | 402 { |
403 lpvalue = NULL; | |
404 | |
771 | 405 if (qxeRegQueryValueEx (hrootkey, keyext, NULL, NULL, NULL, |
406 &cbData) == ERROR_SUCCESS && | |
2367 | 407 (lpvalue = xnew_array (BYTE, cbData)) != NULL && |
771 | 408 qxeRegQueryValueEx (hrootkey, keyext, NULL, lpdwtype, lpvalue, |
409 &cbData) == ERROR_SUCCESS) | |
410 return (lpvalue); | |
428 | 411 |
1726 | 412 if (lpvalue) |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
413 xfree (lpvalue); |
428 | 414 |
415 RegCloseKey (hrootkey); | |
416 } | |
417 | |
418 return (NULL); | |
419 } | |
420 | |
421 void | |
814 | 422 init_mswindows_environment (void) |
428 | 423 { |
424 /* Check for environment variables and use registry if they don't exist */ | |
771 | 425 /* Emacs 20.6 sets default values for these; not necessary here because |
426 we already supply them. (except SHELL, which is set in init_user_info().) | |
427 Emacs 20.6 messes with TMPDIR; not necessary here. */ | |
428 | 428 { |
429 int i; | |
430 LPBYTE lpval; | |
431 DWORD dwType; | |
432 | |
2367 | 433 static Ascbyte *env_vars[] = |
428 | 434 { |
435 "HOME", | |
436 "EMACSLOADPATH", | |
437 "EMACSDEBUGPATHS", | |
438 "SHELL", | |
439 "CMDPROXY", | |
440 "EMACSDATA", | |
441 "EMACSPATH", | |
442 "EMACSPACKAGEPATH", | |
3179 | 443 "EMACSEARLYPACKAGES", |
444 "EMACSLATEPACKAGES", | |
445 "EMACSLASTPACKAGES", | |
771 | 446 "EMACSLOCKMETHOD", |
428 | 447 "INFOPATH" |
448 }; | |
771 | 449 #if defined (HEAP_IN_DATA) && !defined (PDUMP) |
430 | 450 cache_system_info (); |
451 #endif | |
771 | 452 |
453 #if 0 /* FSF 21.1 */ | |
454 /* !!#### i think i already do the equivalent elsewhere. | |
455 delete when i'm sure i do. | |
456 (but maybe i should be playing with LANG when the user changes | |
457 the locale, so that subprocesses get it right.) */ | |
458 /* Get default locale info and use it for LANG. */ | |
459 if (GetLocaleInfo (LOCALE_USER_DEFAULT, | |
460 LOCALE_SABBREVLANGNAME | LOCALE_USE_CP_ACP, | |
461 locale_name, sizeof (locale_name))) | |
462 { | |
463 for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++) | |
464 { | |
465 if (strcmp (env_vars[i].name, "LANG") == 0) | |
466 { | |
467 env_vars[i].def_value = locale_name; | |
468 break; | |
469 } | |
470 } | |
471 } | |
472 #endif /* 0 */ | |
473 | |
428 | 474 for (i = 0; i < countof (env_vars); i++) |
475 { | |
771 | 476 if (!egetenv (env_vars[i]) && |
1204 | 477 (lpval = nt_get_resource ((Ibyte *) env_vars[i], &dwType)) != NULL) |
428 | 478 { |
479 if (dwType == REG_EXPAND_SZ) | |
480 { | |
771 | 481 Extbyte *buf = NULL; |
867 | 482 Ibyte *envval; |
771 | 483 Charcount cch; |
428 | 484 |
771 | 485 cch = qxeExpandEnvironmentStrings ((Extbyte *) lpval, buf, 0); |
2367 | 486 buf = alloca_extbytes (cch * XETCHAR_SIZE); |
771 | 487 qxeExpandEnvironmentStrings ((Extbyte *) lpval, buf, cch); |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
488 envval = TSTR_TO_ITEXT (buf); |
1204 | 489 eputenv (env_vars[i], (CIbyte *) envval); |
428 | 490 } |
491 else if (dwType == REG_SZ) | |
492 { | |
867 | 493 Ibyte *envval; |
771 | 494 |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
495 envval = TSTR_TO_ITEXT (lpval); |
1204 | 496 eputenv (env_vars[i], (CIbyte *) envval); |
428 | 497 } |
498 | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
499 xfree (lpval); |
428 | 500 } |
501 } | |
502 } | |
503 | |
504 /* Another special case: on NT, the PATH variable is actually named | |
505 "Path" although cmd.exe (perhaps NT itself) arranges for | |
506 environment variable lookup and setting to be case insensitive. | |
507 However, Emacs assumes a fully case sensitive environment, so we | |
508 need to change "Path" to "PATH" to match the expectations of | |
771 | 509 various elisp packages. |
428 | 510 |
511 The same applies to COMSPEC. */ | |
512 { | |
2367 | 513 EXTERNAL_LIST_LOOP_2 (str, Vprocess_environment) |
771 | 514 { |
515 if (STRINGP (str)) | |
516 { | |
867 | 517 Ibyte *dat = XSTRING_DATA (str); |
2367 | 518 if (qxestrncasecmp_ascii (dat, "PATH=", 5) == 0) |
771 | 519 memcpy (dat, "PATH=", 5); |
2367 | 520 else if (qxestrncasecmp_ascii (dat, "COMSPEC=", 8) == 0) |
771 | 521 memcpy (dat, "COMSPEC=", 8); |
522 } | |
523 } | |
428 | 524 } |
525 | |
526 init_user_info (); | |
527 } | |
528 | |
771 | 529 /* Emacs 20.6 contains a routine get_emacs_configuration() here to set |
530 EMACS_CONFIGURATION. */ | |
428 | 531 #ifndef HAVE_X_WINDOWS |
532 /* X11R6 on NT provides the single parameter version of this command. */ | |
533 | |
534 #include <sys/timeb.h> | |
535 | |
536 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */ | |
537 void | |
538 gettimeofday (struct timeval *tv, struct timezone *tz) | |
539 { | |
540 struct _timeb tb; | |
541 _ftime (&tb); | |
542 | |
543 tv->tv_sec = tb.time; | |
544 tv->tv_usec = tb.millitm * 1000L; | |
545 if (tz) | |
546 { | |
547 tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */ | |
548 tz->tz_dsttime = tb.dstflag; /* type of dst correction */ | |
549 } | |
550 } | |
551 | |
552 #endif /* HAVE_X_WINDOWS */ | |
553 | |
771 | 554 |
428 | 555 /* ------------------------------------------------------------------------- */ |
771 | 556 /* IO support and wrapper functions for Win32 API. */ |
428 | 557 /* ------------------------------------------------------------------------- */ |
558 | |
771 | 559 typedef struct volume_info_data |
428 | 560 { |
771 | 561 struct volume_info_data *next; |
428 | 562 |
563 /* time when info was obtained */ | |
771 | 564 DWORD timestamp; |
428 | 565 |
566 /* actual volume info */ | |
867 | 567 Ibyte *root_dir; |
771 | 568 DWORD serialnum; |
569 DWORD maxcomp; | |
570 DWORD flags; | |
867 | 571 Ibyte *name; |
572 Ibyte *type; | |
428 | 573 } volume_info_data; |
574 | |
575 /* Global referenced by various functions. */ | |
576 static volume_info_data volume_info; | |
577 | |
578 /* Vector to indicate which drives are local and fixed (for which cached | |
579 data never expires). */ | |
580 static BOOL fixed_drives[26]; | |
581 | |
582 /* Consider cached volume information to be stale if older than 10s, | |
583 at least for non-local drives. Info for fixed drives is never stale. */ | |
584 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' ) | |
585 #define VOLINFO_STILL_VALID( root_dir, info ) \ | |
586 ( ( isalpha (root_dir[0]) && \ | |
587 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \ | |
588 || GetTickCount () - info->timestamp < 10000 ) | |
589 | |
590 /* Cache support functions. */ | |
591 | |
592 /* Simple linked list with linear search is sufficient. */ | |
593 static volume_info_data *volume_cache = NULL; | |
594 | |
595 static volume_info_data * | |
867 | 596 lookup_volume_info (Ibyte *root_dir) |
428 | 597 { |
771 | 598 volume_info_data *info; |
428 | 599 |
600 for (info = volume_cache; info; info = info->next) | |
771 | 601 if (qxestrcasecmp_i18n (info->root_dir, root_dir) == 0) |
428 | 602 break; |
603 return info; | |
604 } | |
605 | |
606 static void | |
867 | 607 add_volume_info (Ibyte *root_dir, volume_info_data *info) |
428 | 608 { |
771 | 609 info->root_dir = qxestrdup (root_dir); |
428 | 610 info->next = volume_cache; |
611 volume_cache = info; | |
612 } | |
613 | |
614 | |
615 /* Wrapper for GetVolumeInformation, which uses caching to avoid | |
616 performance penalty (~2ms on 486 for local drives, 7.5ms for local | |
617 cdrom drive, ~5-10ms or more for remote drives on LAN). */ | |
771 | 618 static volume_info_data * |
867 | 619 get_cached_volume_information (Ibyte *root_dir) |
428 | 620 { |
771 | 621 volume_info_data *info; |
867 | 622 Ibyte *default_root; |
428 | 623 |
624 /* NULL for root_dir means use root from current directory. */ | |
625 if (root_dir == NULL) | |
626 { | |
771 | 627 Charcount nchars = qxeGetCurrentDirectory (0, NULL); |
628 Extbyte *rootext; | |
629 | |
630 if (!nchars) | |
428 | 631 return NULL; |
771 | 632 rootext = alloca_extbytes (nchars * XETCHAR_SIZE); |
633 if (!qxeGetCurrentDirectory (nchars, rootext)) | |
634 return NULL; | |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
635 default_root = TSTR_TO_ITEXT (rootext); |
428 | 636 parse_root (default_root, &root_dir); |
637 *root_dir = 0; | |
638 root_dir = default_root; | |
639 } | |
640 | |
641 /* Local fixed drives can be cached permanently. Removable drives | |
642 cannot be cached permanently, since the volume name and serial | |
643 number (if nothing else) can change. Remote drives should be | |
644 treated as if they are removable, since there is no sure way to | |
645 tell whether they are or not. Also, the UNC association of drive | |
646 letters mapped to remote volumes can be changed at any time (even | |
647 by other processes) without notice. | |
648 | |
649 As a compromise, so we can benefit from caching info for remote | |
650 volumes, we use a simple expiry mechanism to invalidate cache | |
651 entries that are more than ten seconds old. */ | |
652 | |
653 #if 0 | |
654 /* No point doing this, because WNetGetConnection is even slower than | |
655 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW, | |
656 GetDriveType is about the only call of this type which does not | |
657 involve network access, and so is extremely quick). */ | |
658 | |
659 /* Map drive letter to UNC if remote. */ | |
771 | 660 if (isalpha (root_dir[0]) && !fixed [DRIVE_INDEX (root_dir[0])]) |
428 | 661 { |
771 | 662 Extbyte remote_name[256 * XETCHAR_SIZE]; |
867 | 663 Ibyte drive[3] = { root_dir[0], ':' }; |
771 | 664 Extbyte *driveext; |
428 | 665 |
2526 | 666 PATHNAME_CONVERT_OUT (drive, driveext); |
771 | 667 if (qxeWNetGetConnection (driveext, remote_name, |
668 sizeof (remote_name) / XETCHAR_SIZE) | |
428 | 669 == NO_ERROR) |
670 /* do something */ ; | |
671 } | |
672 #endif | |
673 | |
674 info = lookup_volume_info (root_dir); | |
675 | |
676 if (info == NULL || ! VOLINFO_STILL_VALID (root_dir, info)) | |
771 | 677 { |
678 Extbyte name[256 * MAX_XETCHAR_SIZE]; | |
679 DWORD serialnum; | |
680 DWORD maxcomp; | |
681 DWORD flags; | |
682 Extbyte type[256 * MAX_XETCHAR_SIZE]; | |
1204 | 683 Extbyte *rootdirext; |
684 | |
2526 | 685 PATHNAME_CONVERT_OUT (root_dir, rootdirext); |
428 | 686 |
771 | 687 /* Info is not cached, or is stale. */ |
1204 | 688 if (!qxeGetVolumeInformation (rootdirext, |
771 | 689 name, sizeof (name) / XETCHAR_SIZE, |
690 &serialnum, | |
691 &maxcomp, | |
692 &flags, | |
693 type, sizeof (type) / XETCHAR_SIZE)) | |
694 return NULL; | |
428 | 695 |
771 | 696 /* Cache the volume information for future use, overwriting existing |
697 entry if present. */ | |
698 if (info == NULL) | |
699 { | |
2367 | 700 info = xnew (volume_info_data); |
771 | 701 add_volume_info (root_dir, info); |
702 } | |
703 else | |
704 { | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
705 xfree (info->name); |
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
706 xfree (info->type); |
771 | 707 } |
428 | 708 |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
709 info->name = TSTR_TO_ITEXT_MALLOC (name); |
771 | 710 info->serialnum = serialnum; |
711 info->maxcomp = maxcomp; | |
712 info->flags = flags; | |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
713 info->type = TSTR_TO_ITEXT_MALLOC (type); |
771 | 714 info->timestamp = GetTickCount (); |
715 } | |
428 | 716 |
717 return info; | |
718 } | |
719 | |
720 /* Get information on the volume where name is held; set path pointer to | |
721 start of pathname in name (past UNC header\volume header if present). */ | |
771 | 722 static int |
867 | 723 get_volume_info (const Ibyte *name, const Ibyte **pPath) |
428 | 724 { |
771 | 725 /* We probably only need a couple of bytes, but let's be generous in |
726 case this function gets changed */ | |
2367 | 727 Ibyte *temp = alloca_ibytes (qxestrlen (name) + 10); |
867 | 728 Ibyte *rootname = NULL; /* default to current volume */ |
771 | 729 volume_info_data *info; |
428 | 730 |
731 if (name == NULL) | |
732 return FALSE; | |
733 | |
734 /* find the root name of the volume if given */ | |
735 if (isalpha (name[0]) && name[1] == ':') | |
736 { | |
737 rootname = temp; | |
738 temp[0] = *name++; | |
739 temp[1] = *name++; | |
740 temp[2] = '\\'; | |
741 temp[3] = 0; | |
742 } | |
743 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1])) | |
744 { | |
867 | 745 Ibyte *str = temp; |
428 | 746 int slashes = 4; |
747 rootname = temp; | |
748 do | |
749 { | |
750 if (IS_DIRECTORY_SEP (*name) && --slashes == 0) | |
751 break; | |
752 *str++ = *name++; | |
753 } | |
771 | 754 while (*name); |
428 | 755 |
756 *str++ = '\\'; | |
757 *str = 0; | |
758 } | |
759 | |
760 if (pPath) | |
761 *pPath = name; | |
762 | |
771 | 763 info = get_cached_volume_information (rootname); |
428 | 764 if (info != NULL) |
765 { | |
766 /* Set global referenced by other functions. */ | |
767 volume_info = *info; | |
768 return TRUE; | |
769 } | |
770 return FALSE; | |
771 } | |
772 | |
771 | 773 /* XEmacs: Everything referring to map_win32_filename() aka map_w32_filename() |
774 removed; it was only for NT 3.1, which we hereby do not support. (NT 3.5 | |
775 predates Windows 95!) */ | |
428 | 776 |
1204 | 777 int |
778 mswindows_is_executable (const Ibyte *name) | |
771 | 779 { |
867 | 780 Ibyte *p = qxestrrchr (name, '.'); |
2367 | 781 return (p != NULL && (qxestrcasecmp_ascii (p, ".exe") == 0 || |
782 qxestrcasecmp_ascii (p, ".com") == 0 || | |
783 qxestrcasecmp_ascii (p, ".bat") == 0 || | |
784 qxestrcasecmp_ascii (p, ".cmd") == 0)); | |
428 | 785 } |
786 | |
787 /* Emulate the Unix directory procedures opendir, closedir, | |
788 and readdir. We can't use the procedures supplied in sysdep.c, | |
789 so we provide them here. */ | |
790 | |
791 struct direct dir_static; /* simulated directory contents */ | |
792 static HANDLE dir_find_handle = INVALID_HANDLE_VALUE; | |
771 | 793 /* dir_is_fat deleted */ |
867 | 794 static Ibyte *dir_pathname; |
771 | 795 static WIN32_FIND_DATAW dir_find_data; |
796 | |
797 /* Support shares on a network resource as subdirectories of a read-only | |
798 root directory. */ | |
799 static HANDLE wnet_enum_handle = INVALID_HANDLE_VALUE; | |
867 | 800 static HANDLE open_unc_volume (const Ibyte *); |
801 static Ibyte *read_unc_volume (HANDLE); | |
771 | 802 static int close_unc_volume (HANDLE); |
428 | 803 |
804 DIR * | |
867 | 805 mswindows_opendir (const Ibyte *filename) |
428 | 806 { |
807 DIR *dirp; | |
808 | |
809 /* Opening is done by FindFirstFile. However, a read is inherent to | |
810 this operation, so we defer the open until read time. */ | |
811 | |
771 | 812 if (dir_find_handle != INVALID_HANDLE_VALUE) |
428 | 813 return NULL; |
771 | 814 if (wnet_enum_handle != INVALID_HANDLE_VALUE) |
428 | 815 return NULL; |
816 | |
771 | 817 if (is_unc_volume (filename)) |
818 { | |
819 wnet_enum_handle = open_unc_volume (filename); | |
820 if (wnet_enum_handle == INVALID_HANDLE_VALUE) | |
821 return NULL; | |
822 } | |
428 | 823 |
771 | 824 if (!(dirp = xnew_and_zero (DIR))) |
825 return NULL; | |
826 | |
827 if (dir_pathname) | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
828 xfree (dir_pathname); |
771 | 829 dir_pathname = qxestrdup (filename); |
428 | 830 |
831 return dirp; | |
832 } | |
833 | |
442 | 834 int |
771 | 835 mswindows_closedir (DIR *dirp) |
428 | 836 { |
2957 | 837 int retval = -1; |
442 | 838 |
428 | 839 /* If we have a find-handle open, close it. */ |
840 if (dir_find_handle != INVALID_HANDLE_VALUE) | |
841 { | |
771 | 842 retval = FindClose (dir_find_handle) ? 0 : -1; |
428 | 843 dir_find_handle = INVALID_HANDLE_VALUE; |
844 } | |
771 | 845 else if (wnet_enum_handle != INVALID_HANDLE_VALUE) |
846 { | |
847 retval = close_unc_volume (wnet_enum_handle); | |
848 wnet_enum_handle = INVALID_HANDLE_VALUE; | |
849 } | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
850 xfree (dirp); |
771 | 851 |
852 return retval; | |
853 } | |
854 | |
855 struct direct * | |
2286 | 856 mswindows_readdir (DIR *UNUSED (dirp)) |
771 | 857 { |
867 | 858 Ibyte *val; |
771 | 859 int need_to_free = 0; |
860 | |
861 if (wnet_enum_handle != INVALID_HANDLE_VALUE) | |
862 { | |
863 if (!(val = read_unc_volume (wnet_enum_handle))) | |
864 return NULL; | |
865 need_to_free = 1; | |
866 } | |
867 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */ | |
868 else if (dir_find_handle == INVALID_HANDLE_VALUE) | |
869 { | |
870 DECLARE_EISTRING (filename); | |
867 | 871 Ichar lastch; |
2526 | 872 Extbyte *fileext; |
771 | 873 |
874 eicpy_rawz (filename, dir_pathname); | |
875 lastch = eigetch_char (filename, eicharlen (filename) - 1); | |
876 if (!IS_DIRECTORY_SEP (lastch)) | |
877 eicat_ch (filename, '\\'); | |
878 eicat_ch (filename, '*'); | |
2526 | 879 PATHNAME_CONVERT_OUT (eidata (filename), fileext); |
771 | 880 |
2526 | 881 dir_find_handle = qxeFindFirstFile (fileext, &dir_find_data); |
771 | 882 |
883 if (dir_find_handle == INVALID_HANDLE_VALUE) | |
884 return NULL; | |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
885 val = TSTR_TO_ITEXT (dir_find_data.cFileName); |
771 | 886 } |
887 else | |
888 { | |
889 if (!qxeFindNextFile (dir_find_handle, &dir_find_data)) | |
890 return NULL; | |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
891 val = TSTR_TO_ITEXT (dir_find_data.cFileName); |
771 | 892 } |
893 | |
894 /* XEmacs never uses this value, so don't bother making it match | |
895 value returned by qxe_stat(). */ | |
896 dir_static.d_ino = 1; | |
897 | |
898 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 + | |
899 dir_static.d_namlen - dir_static.d_namlen % 4; | |
900 | |
901 { | |
902 DECLARE_EISTRING (found); | |
903 Bytecount namlen; | |
904 | |
2526 | 905 if (mswindows_shortcuts_are_symlinks) |
906 { | |
907 int len = qxestrlen (val); | |
908 if (len > 4 && !qxestrcasecmp_ascii (val + len - 4, ".LNK")) | |
909 { | |
910 /* If we've found a valid link, then chop off the .LNK ending */ | |
911 DECLARE_EISTRING (linkname); | |
912 Ichar lastch; | |
913 Ibyte *resolved; | |
914 | |
915 /* First check if link is valid */ | |
916 PATHNAME_RESOLVE_LINKS (dir_pathname, resolved); | |
917 eicpy_rawz (linkname, resolved); | |
918 lastch = eigetch_char (linkname, eicharlen (linkname) - 1); | |
919 if (!IS_DIRECTORY_SEP (lastch)) | |
920 eicat_ch (linkname, '\\'); | |
921 eicat_rawz (linkname, val); | |
922 resolved = mswindows_read_link (eidata (linkname)); | |
923 if (resolved) | |
924 { | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
925 xfree (resolved); |
2526 | 926 len -= 4; |
927 val[len] = '\0'; | |
928 } | |
929 } | |
930 } | |
931 | |
771 | 932 eicpy_rawz (found, val); |
933 if (need_to_free) | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
934 xfree (val); |
771 | 935 |
936 if (!NILP (Vmswindows_downcase_file_names)) | |
937 eilwr (found); | |
938 | |
939 namlen = min (eilen (found), sizeof (dir_static.d_name) - 1); | |
5000
44d7bde26046
fix compile errors, fix revert-buffer bug on binary/Latin 1 files, Mule-ize some files
Ben Wing <ben@xemacs.org>
parents:
4982
diff
changeset
|
940 qxestrncpy ((Ibyte *) dir_static.d_name, eidata (found), namlen); |
771 | 941 dir_static.d_name[namlen] = '\0'; |
942 dir_static.d_namlen = (unsigned short) namlen; | |
943 } | |
944 | |
945 return &dir_static; | |
946 } | |
947 | |
948 static HANDLE | |
867 | 949 open_unc_volume (const Ibyte *path) |
771 | 950 { |
951 NETRESOURCEW nr; | |
952 HANDLE henum; | |
953 int result; | |
5000
44d7bde26046
fix compile errors, fix revert-buffer bug on binary/Latin 1 files, Mule-ize some files
Ben Wing <ben@xemacs.org>
parents:
4982
diff
changeset
|
954 Extbyte *extpath; |
771 | 955 |
956 nr.dwScope = RESOURCE_GLOBALNET; | |
957 nr.dwType = RESOURCETYPE_DISK; | |
958 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SERVER; | |
959 nr.dwUsage = RESOURCEUSAGE_CONTAINER; | |
960 nr.lpLocalName = NULL; | |
5000
44d7bde26046
fix compile errors, fix revert-buffer bug on binary/Latin 1 files, Mule-ize some files
Ben Wing <ben@xemacs.org>
parents:
4982
diff
changeset
|
961 PATHNAME_CONVERT_OUT (path, extpath); |
5006
ecdc03ef6e12
Instantiate Ben's compile fix for nt.c
Vin Shelton <acs@xemacs.org>
parents:
5000
diff
changeset
|
962 nr.lpRemoteName = (XELPTSTR) extpath; |
771 | 963 nr.lpComment = NULL; |
964 nr.lpProvider = NULL; | |
965 | |
966 result = qxeWNetOpenEnum (RESOURCE_GLOBALNET, RESOURCETYPE_DISK, | |
967 RESOURCEUSAGE_CONNECTABLE, &nr, &henum); | |
968 | |
969 if (result == NO_ERROR) | |
970 return henum; | |
971 else | |
972 return INVALID_HANDLE_VALUE; | |
973 } | |
974 | |
867 | 975 static Ibyte * |
2286 | 976 read_unc_volume (HANDLE UNUSED (henum)) |
771 | 977 { |
1204 | 978 DWORD count; |
771 | 979 int result; |
980 Extbyte buf[16384]; | |
867 | 981 Ibyte *ptr; |
1204 | 982 DWORD bufsize = sizeof (buf); |
771 | 983 |
984 count = 1; | |
985 /* #### we should just be querying the size and then allocating the | |
986 right amount, like for all similar API's. but the docs say this ?! | |
987 | |
988 An application cannot set the lpBuffer parameter to NULL and | |
989 retrieve the required buffer size from the lpBufferSize | |
990 parameter. Instead, the application should allocate a buffer of a | |
991 reasonable size -- 16 kilobytes (K) is typical -- and use the value | |
992 of lpBufferSize for error detection. | |
993 */ | |
994 | |
995 result = qxeWNetEnumResource (wnet_enum_handle, &count, buf, &bufsize); | |
996 if (result != NO_ERROR) | |
997 return NULL; | |
998 | |
999 /* WNetEnumResource returns \\resource\share...skip forward to "share". */ | |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
1000 ptr = TSTR_TO_ITEXT (((LPNETRESOURCEW) buf)->lpRemoteName); |
867 | 1001 INC_IBYTEPTR (ptr); |
1002 INC_IBYTEPTR (ptr); | |
1003 while (*ptr && !IS_DIRECTORY_SEP (itext_ichar (ptr))) | |
1004 INC_IBYTEPTR (ptr); | |
1005 INC_IBYTEPTR (ptr); | |
771 | 1006 |
1007 return qxestrdup (ptr); | |
1008 } | |
1009 | |
1010 static int | |
1011 close_unc_volume (HANDLE henum) | |
1012 { | |
1013 if (henum != INVALID_HANDLE_VALUE) | |
1014 return WNetCloseEnum (henum) == NO_ERROR ? 0 : -1; | |
442 | 1015 else |
1016 return -1; | |
428 | 1017 } |
1018 | |
771 | 1019 static DWORD |
867 | 1020 unc_volume_file_attributes (const Ibyte *path) |
428 | 1021 { |
771 | 1022 HANDLE henum; |
1023 DWORD attrs; | |
1024 | |
1025 henum = open_unc_volume (path); | |
1026 if (henum == INVALID_HANDLE_VALUE) | |
1027 return -1; | |
1028 | |
1029 attrs = FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY; | |
1030 | |
1031 close_unc_volume (henum); | |
428 | 1032 |
771 | 1033 return attrs; |
1034 } | |
1035 | |
1036 int | |
867 | 1037 mswindows_access (const Ibyte *path, int mode) |
771 | 1038 { |
1039 DWORD attributes; | |
428 | 1040 |
771 | 1041 /* MSVC implementation doesn't recognize D_OK. */ |
1042 if (is_unc_volume (path)) | |
1043 { | |
1044 attributes = unc_volume_file_attributes (path); | |
1045 if (attributes == -1) | |
1046 { | |
1047 errno = EACCES; | |
1048 return -1; | |
1049 } | |
428 | 1050 } |
1051 else | |
1052 { | |
771 | 1053 Extbyte *pathext; |
1054 | |
2526 | 1055 PATHNAME_CONVERT_OUT (path, pathext); |
771 | 1056 if ((attributes = qxeGetFileAttributes (pathext)) == -1) |
1057 { | |
1058 /* Should try mapping GetLastError to errno; for now just indicate | |
1059 that path doesn't exist. */ | |
1060 errno = EACCES; | |
1061 return -1; | |
1062 } | |
428 | 1063 } |
1204 | 1064 if ((mode & X_OK) != 0 && !mswindows_is_executable (path)) |
771 | 1065 { |
1066 errno = EACCES; | |
1067 return -1; | |
1068 } | |
1069 if ((mode & W_OK) != 0 && (attributes & FILE_ATTRIBUTE_READONLY) != 0) | |
428 | 1070 { |
771 | 1071 errno = EACCES; |
1072 return -1; | |
428 | 1073 } |
771 | 1074 if ((mode & D_OK) != 0 && (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0) |
1075 { | |
1076 errno = EACCES; | |
1077 return -1; | |
1078 } | |
1079 return 0; | |
428 | 1080 } |
1081 | |
771 | 1082 /* This only works on NTFS volumes, but is useful to have. */ |
1083 /* #### NT 5.0 has a function CreateHardLink to do this directly, | |
1084 and it may do more things. */ | |
428 | 1085 int |
2957 | 1086 mswindows_link (const Ibyte *old, const Ibyte *new_) |
428 | 1087 { |
771 | 1088 HANDLE fileh; |
1089 int result = -1; | |
1204 | 1090 Extbyte *oldext; |
771 | 1091 |
2957 | 1092 if (old == NULL || new_ == NULL) |
771 | 1093 { |
1094 errno = ENOENT; | |
1095 return -1; | |
1096 } | |
1097 | |
2526 | 1098 PATHNAME_CONVERT_OUT (old, oldext); |
1204 | 1099 fileh = qxeCreateFile (oldext, 0, 0, NULL, OPEN_EXISTING, |
771 | 1100 FILE_FLAG_BACKUP_SEMANTICS, NULL); |
1101 if (fileh != INVALID_HANDLE_VALUE) | |
1102 { | |
1103 int wlen; | |
1104 WCHAR *newuni; | |
1105 | |
1106 /* Confusingly, the "alternate" stream name field does not apply | |
1107 when restoring a hard link, and instead contains the actual | |
1108 stream data for the link (ie. the name of the link to create). | |
1109 The WIN32_STREAM_ID structure before the cStreamName field is | |
1110 the stream header, which is then immediately followed by the | |
1111 stream data. */ | |
1112 | |
1113 struct | |
1114 { | |
1115 WIN32_STREAM_ID wid; | |
2421 | 1116 WCHAR wbuffer[_MAX_PATH]; /* extra space for link name */ |
771 | 1117 } data; |
1118 | |
2957 | 1119 TO_EXTERNAL_FORMAT (C_STRING, new_, |
771 | 1120 ALLOCA, (newuni, wlen), Qmswindows_unicode); |
2421 | 1121 if (wlen / sizeof (WCHAR) < _MAX_PATH) |
771 | 1122 { |
1123 LPVOID context = NULL; | |
1124 DWORD wbytes = 0; | |
428 | 1125 |
771 | 1126 wcscpy (data.wid.cStreamName, newuni); |
1127 data.wid.dwStreamId = BACKUP_LINK; | |
1128 data.wid.dwStreamAttributes = 0; | |
4638
5bbff3553494
mswindows_link had off-by-one error. <1vq2brxz.wl_Ron.Isaacson@morganstanley.com>
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4487
diff
changeset
|
1129 /* Include the trailing null. In bytes, not chars! */ |
5bbff3553494
mswindows_link had off-by-one error. <1vq2brxz.wl_Ron.Isaacson@morganstanley.com>
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4487
diff
changeset
|
1130 data.wid.Size.LowPart = wlen + sizeof (WCHAR); |
771 | 1131 data.wid.Size.HighPart = 0; |
1132 data.wid.dwStreamNameSize = 0; | |
1133 | |
1134 if (BackupWrite (fileh, (LPBYTE)&data, | |
1135 offsetof (WIN32_STREAM_ID, cStreamName) | |
1136 + data.wid.Size.LowPart, | |
1137 &wbytes, FALSE, FALSE, &context) | |
1138 && BackupWrite (fileh, NULL, 0, &wbytes, TRUE, FALSE, &context)) | |
1139 { | |
1140 /* succeeded */ | |
1141 result = 0; | |
1142 } | |
1143 else | |
1144 { | |
1145 /* Should try mapping GetLastError to errno; for now just | |
1146 indicate a general error (eg. links not supported). */ | |
1242 | 1147 errno = EINVAL; /* perhaps EMLINK? */ |
771 | 1148 } |
1149 } | |
1150 | |
1151 CloseHandle (fileh); | |
1152 } | |
1153 else | |
1154 errno = ENOENT; | |
1155 | |
1156 return result; | |
1157 } | |
1158 | |
1159 /* sys_open() merged into sysdep.c sys_open() */ | |
1160 | |
1161 int | |
867 | 1162 mswindows_rename (const Ibyte *oldname, const Ibyte *newname) |
771 | 1163 { |
1164 int result; | |
867 | 1165 Ibyte *temp; |
771 | 1166 |
1167 /* MoveFile on Windows 95 doesn't correctly change the short file name | |
428 | 1168 alias in a number of circumstances (it is not easy to predict when |
1169 just by looking at oldname and newname, unfortunately). In these | |
1170 cases, renaming through a temporary name avoids the problem. | |
1171 | |
771 | 1172 A second problem on Windows 95 is that renaming through a temp name when |
428 | 1173 newname is uppercase fails (the final long name ends up in |
1174 lowercase, although the short alias might be uppercase) UNLESS the | |
1175 long temp name is not 8.3. | |
1176 | |
771 | 1177 So, on Windows 95 we always rename through a temp name, and we make sure |
428 | 1178 the temp name has a long extension to ensure correct renaming. */ |
1179 | |
771 | 1180 /* XEmacs: We sprintf() part of OLDNAME into part of OLDNAME + a number, |
1181 so the following calculation should certainly be enough. */ | |
428 | 1182 |
867 | 1183 temp = qxestrcpy (alloca_ibytes (2 * qxestrlen (oldname) + 100), oldname); |
771 | 1184 |
1185 if (mswindows_windows9x_p) | |
428 | 1186 { |
867 | 1187 Ibyte *o; |
1188 Ibyte *p; | |
771 | 1189 int i = 0; |
428 | 1190 |
771 | 1191 if (o = qxestrrchr (oldname, '\\')) |
1192 o++; | |
1193 else | |
867 | 1194 o = (Ibyte *) oldname; |
771 | 1195 |
1196 if (p = qxestrrchr (temp, '\\')) | |
428 | 1197 p++; |
1198 else | |
1199 p = temp; | |
771 | 1200 |
1201 do | |
1202 { | |
1203 Extbyte *oldext, *tempext; | |
1204 /* Force temp name to require a manufactured 8.3 alias - this | |
1205 seems to make the second rename work properly. */ | |
1206 qxesprintf (p, "_.%s.%u", o, i); | |
1207 i++; | |
2526 | 1208 PATHNAME_CONVERT_OUT (oldname, oldext); |
1209 PATHNAME_CONVERT_OUT (temp, tempext); | |
771 | 1210 result = rename (oldext, tempext); |
1211 } | |
1212 /* This loop must surely terminate! */ | |
1213 while (result < 0 && errno == EEXIST); | |
1214 if (result < 0) | |
428 | 1215 return -1; |
1216 } | |
1217 | |
771 | 1218 /* Emulate Unix behaviour - newname is deleted if it already exists |
428 | 1219 (at least if it is a file; don't do this for directories). |
771 | 1220 |
1221 Since we mustn't do this if we are just changing the case of the | |
1222 file name (we would end up deleting the file we are trying to | |
1223 rename!), we let rename detect if the destination file already | |
1224 exists - that way we avoid the possible pitfalls of trying to | |
1225 determine ourselves whether two names really refer to the same | |
1226 file, which is not always possible in the general case. (Consider | |
1227 all the permutations of shared or subst'd drives, etc.) */ | |
1228 { | |
1229 Extbyte *newext, *tempext; | |
1230 | |
2526 | 1231 PATHNAME_CONVERT_OUT (newname, newext); |
1232 PATHNAME_CONVERT_OUT (temp, tempext); | |
1233 if (XEUNICODE_P) | |
1234 { | |
1235 result = _wrename ((const wchar_t *) tempext, | |
1236 (const wchar_t *) newext); | |
1237 if (result < 0 | |
1238 && (errno == EEXIST || errno == EACCES) | |
1239 && _wchmod ((const wchar_t *) newext, 0666) == 0 | |
1240 && _wunlink ((const wchar_t *) newext) == 0) | |
1241 result = _wrename ((const wchar_t *) tempext, | |
1242 (const wchar_t *) newext); | |
1243 } | |
1244 else | |
1245 { | |
1246 result = rename (tempext, newext); | |
1247 if (result < 0 | |
1248 && (errno == EEXIST || errno == EACCES) | |
1249 && _chmod (newext, 0666) == 0 | |
1250 && _unlink (newext) == 0) | |
1251 result = rename (tempext, newext); | |
1252 } | |
771 | 1253 } |
1254 | |
1255 return result; | |
1256 } | |
428 | 1257 |
771 | 1258 int |
867 | 1259 mswindows_unlink (const Ibyte *path) |
771 | 1260 { |
1261 Extbyte *pathout; | |
1262 | |
2526 | 1263 PATHNAME_CONVERT_OUT (path, pathout); |
771 | 1264 /* On Unix, unlink works without write permission. */ |
2526 | 1265 if (XEUNICODE_P) |
1266 { | |
1267 _wchmod ((const wchar_t *) pathout, 0666); | |
1268 return _wunlink ((const wchar_t *) pathout); | |
1269 } | |
1270 else | |
1271 { | |
1272 _chmod (pathout, 0666); | |
1273 return _unlink (pathout); | |
1274 } | |
428 | 1275 } |
1276 | |
1277 static FILETIME utc_base_ft; | |
592 | 1278 static long double utc_base; |
440 | 1279 static int init = 0; |
771 | 1280 static LARGE_INTEGER utc_base_li; |
440 | 1281 |
771 | 1282 /* XEmacs: We seem to have a new definition of |
1283 mswindows_convert_time(), although I'm not sure why. --ben */ | |
428 | 1284 |
1285 time_t | |
771 | 1286 mswindows_convert_time (FILETIME uft) |
440 | 1287 { |
1288 time_t ret; | |
1289 #ifndef MAXLONGLONG | |
1290 SYSTEMTIME st; | |
1291 struct tm t; | |
1292 FILETIME ft; | |
1293 TIME_ZONE_INFORMATION tzi; | |
1294 DWORD tzid; | |
1295 #else | |
1296 LARGE_INTEGER lft; | |
1297 #endif | |
1298 | |
1299 if (!init) | |
1300 { | |
1301 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */ | |
1302 SYSTEMTIME st; | |
1303 | |
1304 st.wYear = 1970; | |
1305 st.wMonth = 1; | |
1306 st.wDay = 1; | |
1307 st.wHour = 0; | |
1308 st.wMinute = 0; | |
1309 st.wSecond = 0; | |
1310 st.wMilliseconds = 0; | |
1311 | |
1312 SystemTimeToFileTime (&st, &utc_base_ft); | |
1313 | |
1314 utc_base_li.LowPart = utc_base_ft.dwLowDateTime; | |
1315 utc_base_li.HighPart = utc_base_ft.dwHighDateTime; | |
1316 | |
1317 init = 1; | |
1318 } | |
1319 | |
1320 #ifdef MAXLONGLONG | |
1321 | |
1322 /* On a compiler that supports long integers, do it the easy way */ | |
1323 lft.LowPart = uft.dwLowDateTime; | |
1324 lft.HighPart = uft.dwHighDateTime; | |
1325 ret = (time_t) ((lft.QuadPart - utc_base_li.QuadPart) / 10000000); | |
1326 | |
1327 #else | |
1328 | |
1329 /* Do it the hard way using mktime. */ | |
1330 FileTimeToLocalFileTime(&uft, &ft); | |
1331 FileTimeToSystemTime (&ft, &st); | |
1332 tzid = GetTimeZoneInformation (&tzi); | |
1333 t.tm_year = st.wYear - 1900; | |
1334 t.tm_mon = st.wMonth - 1; | |
1335 t.tm_mday = st.wDay; | |
1336 t.tm_hour = st.wHour; | |
1337 t.tm_min = st.wMinute; | |
1338 t.tm_sec = st.wSecond; | |
1339 t.tm_isdst = (tzid == TIME_ZONE_ID_DAYLIGHT); | |
1340 /* st.wMilliseconds not applicable */ | |
1341 ret = mktime(&t); | |
1342 if (ret == -1) | |
1343 { | |
1344 ret = 0; | |
1345 } | |
1346 | |
1347 #endif | |
1348 | |
1349 return ret; | |
1350 } | |
428 | 1351 |
771 | 1352 static void |
428 | 1353 convert_from_time_t (time_t time, FILETIME * pft) |
1354 { | |
1355 long double tmp; | |
1356 | |
1357 if (!init) | |
1358 { | |
1359 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */ | |
1360 SYSTEMTIME st; | |
1361 | |
1362 st.wYear = 1970; | |
1363 st.wMonth = 1; | |
1364 st.wDay = 1; | |
1365 st.wHour = 0; | |
1366 st.wMinute = 0; | |
1367 st.wSecond = 0; | |
1368 st.wMilliseconds = 0; | |
1369 | |
1370 SystemTimeToFileTime (&st, &utc_base_ft); | |
1371 utc_base = (long double) utc_base_ft.dwHighDateTime | |
1372 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime; | |
1373 init = 1; | |
1374 } | |
1375 | |
1376 /* time in 100ns units since 1-Jan-1601 */ | |
1377 tmp = (long double) time * 1e7 + utc_base; | |
1378 pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024)); | |
771 | 1379 pft->dwLowDateTime = (DWORD) (tmp - (4096.0 * 1024 * 1024) * |
1380 pft->dwHighDateTime); | |
428 | 1381 } |
1382 | |
1383 #if 0 | |
771 | 1384 /* A comment from Emacs 20.6: |
1385 | |
1386 No reason to keep this; faking inode values either by hashing or even | |
428 | 1387 using the file index from GetInformationByHandle, is not perfect and |
1388 so by default Emacs doesn't use the inode values on Windows. | |
1389 Instead, we now determine file-truename correctly (except for | |
1390 possible drive aliasing etc). */ | |
1391 | |
771 | 1392 /* XEmacs: Removed the fake-inodes code here, which was if 0'd out. |
1393 If you want it, look in w32.c in Emacs 20.6. */ | |
428 | 1394 #endif |
1395 | |
442 | 1396 /* #### aichner@ecf.teradyne.com reported that with the library |
1397 provided stat/fstat, (file-exist "d:\\tmp\\") =>> nil, | |
1398 (file-exist "d:\\tmp") =>> t, when d:\tmp exists. Whenever | |
1399 we opt to use non-encapsulated stat(), this should serve as | |
1400 a compatibility test. --kkm */ | |
440 | 1401 |
771 | 1402 /* Provide fstat and utime as well as stat for consistent handling of |
1403 file timestamps. */ | |
442 | 1404 int |
771 | 1405 mswindows_fstat (int desc, struct stat *buf) |
432 | 1406 { |
448 | 1407 HANDLE fh = (HANDLE) _get_osfhandle (desc); |
1408 BY_HANDLE_FILE_INFORMATION info; | |
1409 DWORD fake_inode; | |
1410 int permission; | |
1411 | |
1412 switch (GetFileType (fh) & ~FILE_TYPE_REMOTE) | |
432 | 1413 { |
448 | 1414 case FILE_TYPE_DISK: |
1415 buf->st_mode = _S_IFREG; | |
1416 if (!GetFileInformationByHandle (fh, &info)) | |
1417 { | |
1418 errno = EACCES; | |
1419 return -1; | |
1420 } | |
1421 break; | |
1422 case FILE_TYPE_PIPE: | |
1423 buf->st_mode = _S_IFIFO; | |
1424 goto non_disk; | |
1425 case FILE_TYPE_CHAR: | |
1426 case FILE_TYPE_UNKNOWN: | |
1427 default: | |
1428 buf->st_mode = _S_IFCHR; | |
1429 non_disk: | |
1430 memset (&info, 0, sizeof (info)); | |
1431 info.dwFileAttributes = 0; | |
1432 info.ftCreationTime = utc_base_ft; | |
1433 info.ftLastAccessTime = utc_base_ft; | |
1434 info.ftLastWriteTime = utc_base_ft; | |
1435 } | |
1436 | |
1437 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) | |
1438 { | |
1439 buf->st_mode = _S_IFDIR; | |
1440 buf->st_nlink = 2; /* doesn't really matter */ | |
1441 fake_inode = 0; /* this doesn't either I think */ | |
432 | 1442 } |
1443 else | |
1444 { | |
462 | 1445 buf->st_nlink = (short) info.nNumberOfLinks; |
448 | 1446 /* Might as well use file index to fake inode values, but this |
1447 is not guaranteed to be unique unless we keep a handle open | |
1448 all the time (even then there are situations where it is | |
1449 not unique). Reputedly, there are at most 48 bits of info | |
1450 (on NTFS, presumably less on FAT). */ | |
1451 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh; | |
432 | 1452 } |
448 | 1453 |
1454 /* MSVC defines _ino_t to be short; other libc's might not. */ | |
1455 if (sizeof (buf->st_ino) == 2) | |
462 | 1456 buf->st_ino = (unsigned short) (fake_inode ^ (fake_inode >> 16)); |
448 | 1457 else |
462 | 1458 buf->st_ino = (unsigned short) fake_inode; |
448 | 1459 |
1460 /* consider files to belong to current user */ | |
1461 buf->st_uid = 0; | |
1462 buf->st_gid = 0; | |
1463 | |
1464 buf->st_dev = info.dwVolumeSerialNumber; | |
1465 buf->st_rdev = info.dwVolumeSerialNumber; | |
1466 | |
1467 buf->st_size = info.nFileSizeLow; | |
1468 | |
1469 /* Convert timestamps to Unix format. */ | |
771 | 1470 buf->st_mtime = mswindows_convert_time (info.ftLastWriteTime); |
1471 buf->st_atime = mswindows_convert_time (info.ftLastAccessTime); | |
448 | 1472 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime; |
771 | 1473 buf->st_ctime = mswindows_convert_time (info.ftCreationTime); |
448 | 1474 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime; |
1475 | |
1476 /* determine rwx permissions */ | |
1477 if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) | |
1478 permission = _S_IREAD; | |
1479 else | |
1480 permission = _S_IREAD | _S_IWRITE; | |
1481 | |
1482 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) | |
1483 permission |= _S_IEXEC; | |
771 | 1484 else |
1485 { | |
1486 #if 0 /* no way of knowing the filename */ | |
1204 | 1487 if (mswindows_is_executable (name)) |
771 | 1488 permission |= _S_IEXEC; |
1489 #endif | |
1490 } | |
448 | 1491 |
1492 buf->st_mode |= permission | (permission >> 3) | (permission >> 6); | |
1493 | |
1494 return 0; | |
432 | 1495 } |
1496 | |
428 | 1497 /* MSVC stat function can't cope with UNC names and has other bugs, so |
1498 replace it with our own. This also allows us to calculate consistent | |
1499 inode values without hacks in the main Emacs code. */ | |
1500 int | |
867 | 1501 mswindows_stat (const Ibyte *path, struct stat *buf) |
428 | 1502 { |
867 | 1503 Ibyte *name, *r; |
771 | 1504 WIN32_FIND_DATAW wfd; |
428 | 1505 HANDLE fh; |
1506 DWORD fake_inode; | |
1507 int permission; | |
771 | 1508 Bytecount len; |
428 | 1509 int rootdir = FALSE; |
771 | 1510 Extbyte *nameext; |
819 | 1511 int errm; |
428 | 1512 |
1513 if (path == NULL || buf == NULL) | |
1514 { | |
1515 errno = EFAULT; | |
1516 return -1; | |
1517 } | |
1518 | |
867 | 1519 name = qxestrcpy (alloca_ibytes (qxestrlen (path) + 10), path); |
819 | 1520 errm = SetErrorMode (SEM_FAILCRITICALERRORS |
1521 | SEM_NOOPENFILEERRORBOX); | |
771 | 1522 |
1523 get_volume_info (name, &path); | |
1524 /* must be valid filename, no wild cards or other invalid characters */ | |
1525 if (qxestrpbrk (name, "*?|<>\"")) | |
428 | 1526 { |
1527 errno = ENOENT; | |
1528 return -1; | |
1529 } | |
1530 | |
771 | 1531 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */ |
1532 r = IS_DEVICE_SEP (name[1]) ? &name[2] : name; | |
1533 if (IS_DIRECTORY_SEP (r[0]) && r[1] == '.' && r[2] == '.' && r[3] == '\0') | |
1534 { | |
1535 r[1] = r[2] = '\0'; | |
1536 } | |
1537 | |
428 | 1538 /* Remove trailing directory separator, unless name is the root |
1539 directory of a drive or UNC volume in which case ensure there | |
1540 is a trailing separator. */ | |
771 | 1541 len = qxestrlen (name); |
428 | 1542 rootdir = (path >= name + len - 1 |
1543 && (IS_DIRECTORY_SEP (*path) || *path == 0)); | |
771 | 1544 |
1545 if (is_unc_volume (name)) | |
1546 { | |
1547 DWORD attrs = unc_volume_file_attributes (name); | |
1548 | |
1549 if (attrs == -1) | |
1550 return -1; | |
428 | 1551 |
771 | 1552 memset (&wfd, 0, sizeof (wfd)); |
1553 wfd.dwFileAttributes = attrs; | |
1554 wfd.ftCreationTime = utc_base_ft; | |
1555 wfd.ftLastAccessTime = utc_base_ft; | |
1556 wfd.ftLastWriteTime = utc_base_ft; | |
1557 /* XEmacs deleted: strcpy (wfd.cFileName, name); | |
1558 Not used later on. */ | |
1559 } | |
1560 else if (rootdir) | |
428 | 1561 { |
1562 if (!IS_DIRECTORY_SEP (name[len-1])) | |
867 | 1563 qxestrcat (name, (Ibyte *) "\\"); |
2526 | 1564 /* File has already been resolved and we don't want to do it again |
1565 in case of lstat() */ | |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
1566 nameext = ITEXT_TO_TSTR (name); |
771 | 1567 if (qxeGetDriveType (nameext) < 2) |
428 | 1568 { |
819 | 1569 SetErrorMode (errm); |
428 | 1570 errno = ENOENT; |
1571 return -1; | |
1572 } | |
1573 memset (&wfd, 0, sizeof (wfd)); | |
1574 wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; | |
1575 wfd.ftCreationTime = utc_base_ft; | |
1576 wfd.ftLastAccessTime = utc_base_ft; | |
1577 wfd.ftLastWriteTime = utc_base_ft; | |
771 | 1578 /* XEmacs deleted: strcpy (wfd.cFileName, name); |
1579 Not used later on. */ | |
428 | 1580 } |
1581 else | |
1582 { | |
1583 if (IS_DIRECTORY_SEP (name[len-1])) | |
1584 name[len - 1] = 0; | |
1585 | |
1586 /* (This is hacky, but helps when doing file completions on | |
1587 network drives.) Optimize by using information available from | |
1588 active readdir if possible. */ | |
771 | 1589 if (dir_pathname) |
1590 { | |
1591 len = qxestrlen (dir_pathname); | |
1592 if (len && IS_DIRECTORY_SEP (dir_pathname[len-1])) | |
1593 len--; | |
1594 } | |
1595 if (dir_find_handle != INVALID_HANDLE_VALUE | |
1596 && dir_pathname | |
801 | 1597 && qxestrncasecmp_i18n (dir_pathname, name, len) == 0 |
771 | 1598 && IS_DIRECTORY_SEP (name[len]) |
1599 && qxestrcasecmp_i18n (name + len + 1, | |
867 | 1600 (Ibyte *) dir_static.d_name) == 0) |
428 | 1601 { |
1602 /* This was the last entry returned by readdir. */ | |
1603 wfd = dir_find_data; | |
1604 } | |
1605 else | |
1606 { | |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
1607 nameext = ITEXT_TO_TSTR (name); |
771 | 1608 fh = qxeFindFirstFile (nameext, &wfd); |
1609 if (fh == INVALID_HANDLE_VALUE) | |
1610 { | |
819 | 1611 SetErrorMode (errm); |
771 | 1612 errno = ENOENT; |
1613 return -1; | |
1614 } | |
1615 FindClose (fh); | |
1616 /* XEmacs: Don't need to convert wfd.cFileName because | |
1617 not used later on. */ | |
428 | 1618 } |
1619 } | |
1620 | |
1621 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) | |
1622 { | |
1623 buf->st_mode = _S_IFDIR; | |
1624 buf->st_nlink = 2; /* doesn't really matter */ | |
1625 fake_inode = 0; /* this doesn't either I think */ | |
1626 } | |
771 | 1627 else |
428 | 1628 { |
771 | 1629 if (!NILP (Vmswindows_get_true_file_attributes)) |
2526 | 1630 /* File has already been resolved and we don't want to do it again |
1631 in case of lstat() */ | |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
1632 nameext = ITEXT_TO_TSTR (name); |
771 | 1633 if (!NILP (Vmswindows_get_true_file_attributes) |
1634 /* No access rights required to get info. */ | |
1635 && (fh = qxeCreateFile (nameext, 0, 0, NULL, OPEN_EXISTING, 0, NULL)) | |
1636 != INVALID_HANDLE_VALUE) | |
1637 { | |
2526 | 1638 /* This is more accurate in terms of getting the correct number |
5384
3889ef128488
Fix misspelled words, and some grammar, across the entire source tree.
Jerry James <james@xemacs.org>
parents:
5006
diff
changeset
|
1639 of links, but is quite slow (it is noticeable when Emacs is |
771 | 1640 making a list of file name completions). */ |
1641 BY_HANDLE_FILE_INFORMATION info; | |
428 | 1642 |
771 | 1643 if (GetFileInformationByHandle (fh, &info)) |
1644 { | |
1645 buf->st_nlink = (short) info.nNumberOfLinks; | |
1646 /* Might as well use file index to fake inode values, but this | |
1647 is not guaranteed to be unique unless we keep a handle open | |
1648 all the time (even then there are situations where it is | |
1649 not unique). Reputedly, there are at most 48 bits of info | |
1650 (on NTFS, presumably less on FAT). */ | |
1651 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh; | |
1652 } | |
1653 else | |
1654 { | |
1655 buf->st_nlink = 1; | |
1656 fake_inode = 0; | |
1657 } | |
428 | 1658 |
1659 switch (GetFileType (fh)) | |
1660 { | |
1661 case FILE_TYPE_DISK: | |
1662 buf->st_mode = _S_IFREG; | |
1663 break; | |
1664 case FILE_TYPE_PIPE: | |
1665 buf->st_mode = _S_IFIFO; | |
1666 break; | |
1667 case FILE_TYPE_CHAR: | |
1668 case FILE_TYPE_UNKNOWN: | |
1669 default: | |
1670 buf->st_mode = _S_IFCHR; | |
1671 } | |
1672 CloseHandle (fh); | |
1673 } | |
1674 else | |
1675 { | |
771 | 1676 /* Don't bother to make this information more accurate. */ |
1677 buf->st_mode = _S_IFREG; | |
1678 buf->st_nlink = 1; | |
1679 fake_inode = 0; | |
428 | 1680 } |
2526 | 1681 |
1682 if (mswindows_shortcuts_are_symlinks && | |
1683 buf->st_mode == _S_IFREG) | |
1684 { | |
1685 len = qxestrlen (name); | |
1686 if (len > 4 && !qxestrcasecmp_ascii (name + len - 4, ".LNK")) | |
1687 { | |
1688 /* check if link is valid */ | |
1689 Ibyte *resolved = mswindows_read_link (name); | |
1690 if (resolved) | |
1691 { | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
1692 xfree (resolved); |
2526 | 1693 buf->st_mode = S_IFLNK; |
1694 } | |
1695 } | |
1696 } | |
428 | 1697 } |
1698 | |
819 | 1699 SetErrorMode (errm); |
1700 | |
428 | 1701 #if 0 |
771 | 1702 /* XEmacs: Removed the fake-inodes code here, which was if 0'd out. |
1703 If you want it, look in w32.c in Emacs 20.6. */ | |
428 | 1704 #endif |
1705 | |
771 | 1706 /* MSVC defines _ino_t to be short; other libc's might not. */ |
1707 if (sizeof (buf->st_ino) == 2) | |
1708 buf->st_ino = (unsigned short) (fake_inode ^ (fake_inode >> 16)); | |
1709 else | |
1710 buf->st_ino = (unsigned short) fake_inode; | |
428 | 1711 |
1712 /* consider files to belong to current user */ | |
771 | 1713 buf->st_uid = the_passwd.pw_uid; |
1714 buf->st_gid = the_passwd.pw_gid; | |
428 | 1715 |
771 | 1716 /* volume_info is set by get_volume_info */ |
428 | 1717 buf->st_dev = volume_info.serialnum; |
1718 buf->st_rdev = volume_info.serialnum; | |
1719 | |
771 | 1720 |
428 | 1721 buf->st_size = wfd.nFileSizeLow; |
1722 | |
1723 /* Convert timestamps to Unix format. */ | |
771 | 1724 buf->st_mtime = mswindows_convert_time (wfd.ftLastWriteTime); |
1725 buf->st_atime = mswindows_convert_time (wfd.ftLastAccessTime); | |
428 | 1726 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime; |
771 | 1727 buf->st_ctime = mswindows_convert_time (wfd.ftCreationTime); |
428 | 1728 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime; |
1729 | |
1730 /* determine rwx permissions */ | |
1731 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) | |
1732 permission = _S_IREAD; | |
1733 else | |
1734 permission = _S_IREAD | _S_IWRITE; | |
1735 | |
1736 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) | |
1737 permission |= _S_IEXEC; | |
1204 | 1738 else if (mswindows_is_executable (name)) |
771 | 1739 permission |= _S_IEXEC; |
428 | 1740 |
1741 buf->st_mode |= permission | (permission >> 3) | (permission >> 6); | |
1742 | |
1743 return 0; | |
1744 } | |
1745 | |
1746 int | |
771 | 1747 mswindows_utime (Lisp_Object path, struct utimbuf *times) |
428 | 1748 { |
771 | 1749 /* #### Supposedly we're providing this because standard utime() |
1750 might not work; or at the very least to get consistent results | |
1751 since we replace other time-handling routines in stat. But out | |
1752 replacement doesn't seem to work, probably due to some subtle bug | |
1753 in this routine, which should be investigated eventually. So for | |
1754 the moment, we just use utime(), which conceivably might be | |
1755 slightly off in comparison with our own routines? Seems strange, | |
1756 and so far no problems seen. --ben */ | |
428 | 1757 |
771 | 1758 struct utimbuf deftime; |
1759 #if 0 | |
1760 HANDLE fh; | |
1761 #endif | |
1762 static FILETIME mtime; | |
1763 static FILETIME atime; | |
1764 Extbyte *filename; | |
428 | 1765 |
771 | 1766 if (times == NULL) |
428 | 1767 { |
771 | 1768 deftime.modtime = deftime.actime = time (NULL); |
1769 times = &deftime; | |
428 | 1770 } |
1771 | |
2526 | 1772 LISP_PATHNAME_CONVERT_OUT (path, filename); |
771 | 1773 /* APA: SetFileTime fails to set mtime correctly (always 1-Jan-1970) */ |
1774 #if 0 | |
1775 /* Need write access to set times. */ | |
1776 fh = qxeCreateFile (filename, GENERIC_WRITE, | |
1777 FILE_SHARE_READ | FILE_SHARE_WRITE, | |
1778 0, OPEN_EXISTING, 0, NULL); | |
1779 if (fh) | |
1780 { | |
1781 convert_from_time_t (times->actime, &atime); | |
1782 convert_from_time_t (times->modtime, &mtime); | |
1783 if (!SetFileTime (fh, NULL, &atime, &mtime)) | |
1784 { | |
1785 CloseHandle (fh); | |
1786 errno = EACCES; | |
1787 return -1; | |
1788 } | |
1789 CloseHandle (fh); | |
1790 } | |
1791 else | |
1792 { | |
1793 errno = EINVAL; | |
1794 return -1; | |
1795 } | |
1796 return 0; | |
1797 #else | |
1798 { | |
1799 struct _utimbuf newtimes; | |
1800 | |
1801 newtimes.actime = times->actime; | |
1802 newtimes.modtime = times->modtime; | |
1803 | |
1804 if (XEUNICODE_P) | |
1805 return _wutime ((const wchar_t *) filename, &newtimes); | |
1806 else | |
1807 return _utime (filename, &newtimes); | |
1808 } | |
1809 #endif | |
1810 } | |
1811 | |
867 | 1812 Ibyte * |
771 | 1813 mswindows_getdcwd (int drivelet) |
1814 { | |
1815 Extbyte *cwdext; | |
867 | 1816 Ibyte *cwd; |
4786 | 1817 /* Following comment and two-liner fix comes from |
1818 https://bugzilla.mozilla.org/show_bug.cgi?id=419326 which | |
1819 apparently fell prey to this feature of msvcrt8 as well. */ | |
1820 /* We need to worry about IPH, for details read bug 419326. | |
1821 * _getdrives - http://msdn2.microsoft.com/en-us/library/xdhk0xd2.aspx | |
1822 * uses a bitmask, bit 0 is 'a:' | |
1823 * _chdrive - http://msdn2.microsoft.com/en-us/library/0d1409hb.aspx | |
1824 * _getdcwd - http://msdn2.microsoft.com/en-us/library/7t2zk3s4.aspx | |
1825 * take an int, 1 is 'a:'. | |
1826 * | |
1827 * Because of this, we need to do some math. Subtract 1 to convert from | |
1828 * _chdrive/_getdcwd format to _getdrives drive numbering. | |
1829 * Shift left x bits to convert from integer indexing to bitfield indexing. | |
1830 * And of course, we need to find out if the drive is in the bitmask. | |
1831 * | |
1832 * If we're really unlucky, we can still lose, but only if the user | |
1833 * manages to eject the drive between our call to _getdrives() and | |
1834 * our *calls* to _wgetdcwd. | |
1835 */ | |
1836 if (!((1 << (drivelet - 1)) & _getdrives())) | |
1837 return NULL; | |
771 | 1838 if (XEUNICODE_P) |
1839 cwdext = (Extbyte *) _wgetdcwd (drivelet, NULL, 0); | |
1840 else | |
1841 cwdext = _getdcwd (drivelet, NULL, 0); | |
3648 | 1842 if (cwdext == NULL) return NULL; |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
1843 cwd = TSTR_TO_ITEXT_MALLOC (cwdext); |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
1844 xfree (cwdext); |
771 | 1845 return cwd; |
428 | 1846 } |
1847 | |
442 | 1848 |
1849 /*--------------------------------------------------------------------*/ | |
1850 /* Memory-mapped files */ | |
1851 /*--------------------------------------------------------------------*/ | |
1852 | |
428 | 1853 int |
867 | 1854 open_input_file (file_data *p_file, const Ibyte *filename) |
428 | 1855 { |
442 | 1856 /* Synched with FSF 20.6. We fixed some warnings. */ |
428 | 1857 HANDLE file; |
1858 HANDLE file_mapping; | |
771 | 1859 void *file_base; |
428 | 1860 DWORD size, upper_size; |
771 | 1861 Extbyte *fileext; |
428 | 1862 |
2526 | 1863 PATHNAME_CONVERT_OUT (filename, fileext); |
771 | 1864 |
1865 file = qxeCreateFile (fileext, GENERIC_READ, FILE_SHARE_READ, NULL, | |
1866 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); | |
428 | 1867 if (file == INVALID_HANDLE_VALUE) |
1868 return FALSE; | |
1869 | |
1870 size = GetFileSize (file, &upper_size); | |
771 | 1871 file_mapping = qxeCreateFileMapping (file, NULL, PAGE_READONLY, |
1872 0, size, NULL); | |
428 | 1873 if (!file_mapping) |
1874 return FALSE; | |
1875 | |
1876 file_base = MapViewOfFile (file_mapping, FILE_MAP_READ, 0, 0, size); | |
1877 if (file_base == 0) | |
1878 return FALSE; | |
1879 | |
771 | 1880 p_file->name = filename; |
442 | 1881 p_file->size = size; |
1882 p_file->file = file; | |
1883 p_file->file_mapping = file_mapping; | |
771 | 1884 p_file->file_base = file_base; |
442 | 1885 |
1886 return TRUE; | |
1887 } | |
1888 | |
1889 int | |
867 | 1890 open_output_file (file_data *p_file, const Ibyte *filename, |
771 | 1891 unsigned long size) |
442 | 1892 { |
1893 /* Synched with FSF 20.6. We fixed some warnings. */ | |
1894 HANDLE file; | |
1895 HANDLE file_mapping; | |
771 | 1896 void *file_base; |
1897 Extbyte *fileext; | |
442 | 1898 |
2526 | 1899 PATHNAME_CONVERT_OUT (filename, fileext); |
771 | 1900 |
1901 file = qxeCreateFile (fileext, GENERIC_READ | GENERIC_WRITE, 0, NULL, | |
1902 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); | |
442 | 1903 if (file == INVALID_HANDLE_VALUE) |
1904 return FALSE; | |
1905 | |
771 | 1906 file_mapping = qxeCreateFileMapping (file, NULL, PAGE_READWRITE, |
1907 0, size, NULL); | |
442 | 1908 if (!file_mapping) |
1909 return FALSE; | |
1910 | |
1911 file_base = MapViewOfFile (file_mapping, FILE_MAP_WRITE, 0, 0, size); | |
1912 if (file_base == NULL) | |
1913 return FALSE; | |
1914 | |
1915 p_file->name = filename; | |
428 | 1916 p_file->size = size; |
1917 p_file->file = file; | |
1918 p_file->file_mapping = file_mapping; | |
771 | 1919 p_file->file_base = file_base; |
428 | 1920 |
1921 return TRUE; | |
1922 } | |
1923 | |
442 | 1924 #if 1 /* !defined(MINGW) */ |
1925 /* Return pointer to section header for section containing the given | |
1926 relative virtual address. */ | |
1927 static IMAGE_SECTION_HEADER * | |
771 | 1928 rva_to_section (DWORD rva, IMAGE_NT_HEADERS *nt_header) |
442 | 1929 { |
1930 /* Synched with FSF 20.6. We added MINGW stuff. */ | |
1931 PIMAGE_SECTION_HEADER section; | |
1932 int i; | |
1933 | |
1934 section = IMAGE_FIRST_SECTION (nt_header); | |
1935 | |
1936 for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++) | |
1937 { | |
1938 /* Some linkers (eg. the NT SDK linker I believe) swapped the | |
1939 meaning of these two values - or rather, they ignored | |
1940 VirtualSize entirely and always set it to zero. This affects | |
1941 some very old exes (eg. gzip dated Dec 1993). Since | |
1942 mswindows_executable_type relies on this function to work reliably, | |
1943 we need to cope with this. */ | |
1944 DWORD real_size = max (section->SizeOfRawData, | |
1945 section->Misc.VirtualSize); | |
1946 if (rva >= section->VirtualAddress | |
1947 && rva < section->VirtualAddress + real_size) | |
1948 return section; | |
1949 section++; | |
1950 } | |
1951 return NULL; | |
1952 } | |
1953 #endif | |
1954 | |
1955 void | |
867 | 1956 mswindows_executable_type (const Ibyte *filename, int *is_dos_app, |
771 | 1957 int *is_cygnus_app) |
442 | 1958 { |
1959 /* Synched with FSF 20.6. We added MINGW stuff and casts. */ | |
1960 file_data executable; | |
867 | 1961 Ibyte *p; |
442 | 1962 |
1963 /* Default values in case we can't tell for sure. */ | |
1964 *is_dos_app = FALSE; | |
1965 *is_cygnus_app = FALSE; | |
1966 | |
1967 if (!open_input_file (&executable, filename)) | |
1968 return; | |
1969 | |
771 | 1970 p = qxestrrchr (filename, '.'); |
442 | 1971 |
1972 /* We can only identify DOS .com programs from the extension. */ | |
2367 | 1973 if (p && qxestrcasecmp_ascii (p, ".com") == 0) |
442 | 1974 *is_dos_app = TRUE; |
2367 | 1975 else if (p && (qxestrcasecmp_ascii (p, ".bat") == 0 || |
1976 qxestrcasecmp_ascii (p, ".cmd") == 0)) | |
442 | 1977 { |
1978 /* A DOS shell script - it appears that CreateProcess is happy to | |
1979 accept this (somewhat surprisingly); presumably it looks at | |
1980 COMSPEC to determine what executable to actually invoke. | |
1981 Therefore, we have to do the same here as well. */ | |
1982 /* Actually, I think it uses the program association for that | |
1983 extension, which is defined in the registry. */ | |
1984 p = egetenv ("COMSPEC"); | |
1985 if (p) | |
1986 mswindows_executable_type (p, is_dos_app, is_cygnus_app); | |
1987 } | |
1988 else | |
1989 { | |
1990 /* Look for DOS .exe signature - if found, we must also check that | |
1991 it isn't really a 16- or 32-bit Windows exe, since both formats | |
1992 start with a DOS program stub. Note that 16-bit Windows | |
1993 executables use the OS/2 1.x format. */ | |
1994 | |
1995 #if 0 /* defined( MINGW ) */ | |
771 | 1996 /* mingw doesn't have enough headers to detect cygwin |
442 | 1997 apps, just do what we can. */ |
771 | 1998 FILHDR *exe_header; |
442 | 1999 |
771 | 2000 exe_header = (FILHDR *) executable.file_base; |
442 | 2001 if (exe_header->e_magic != DOSMAGIC) |
2002 goto unwind; | |
2003 | |
5000
44d7bde26046
fix compile errors, fix revert-buffer bug on binary/Latin 1 files, Mule-ize some files
Ben Wing <ben@xemacs.org>
parents:
4982
diff
changeset
|
2004 if ((Rawbyte *) exe_header->e_lfanew > (Rawbyte *) executable.size) |
442 | 2005 { |
2006 /* Some dos headers (pkunzip) have bogus e_lfanew fields. */ | |
2007 *is_dos_app = TRUE; | |
2008 } | |
2009 else if (exe_header->nt_signature != NT_SIGNATURE) | |
2010 { | |
2011 *is_dos_app = TRUE; | |
2012 } | |
2013 #else | |
771 | 2014 IMAGE_DOS_HEADER *dos_header; |
2015 IMAGE_NT_HEADERS *nt_header; | |
442 | 2016 |
2017 dos_header = (PIMAGE_DOS_HEADER) executable.file_base; | |
2018 if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) | |
2019 goto unwind; | |
2020 | |
5000
44d7bde26046
fix compile errors, fix revert-buffer bug on binary/Latin 1 files, Mule-ize some files
Ben Wing <ben@xemacs.org>
parents:
4982
diff
changeset
|
2021 nt_header = (PIMAGE_NT_HEADERS) ((Rawbyte *) dos_header + |
771 | 2022 dos_header->e_lfanew); |
442 | 2023 |
5000
44d7bde26046
fix compile errors, fix revert-buffer bug on binary/Latin 1 files, Mule-ize some files
Ben Wing <ben@xemacs.org>
parents:
4982
diff
changeset
|
2024 if ((Rawbyte *) nt_header > (Rawbyte *) dos_header + executable.size) |
442 | 2025 { |
2026 /* Some dos headers (pkunzip) have bogus e_lfanew fields. */ | |
2027 *is_dos_app = TRUE; | |
2028 } | |
2029 else if (nt_header->Signature != IMAGE_NT_SIGNATURE && | |
2030 LOWORD (nt_header->Signature) != IMAGE_OS2_SIGNATURE) | |
2031 { | |
2032 *is_dos_app = TRUE; | |
2033 } | |
2034 else if (nt_header->Signature == IMAGE_NT_SIGNATURE) | |
2035 { | |
2036 /* Look for cygwin.dll in DLL import list. */ | |
2037 IMAGE_DATA_DIRECTORY import_dir = | |
771 | 2038 nt_header->OptionalHeader. |
2039 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; | |
2040 IMAGE_IMPORT_DESCRIPTOR *imports; | |
2041 IMAGE_SECTION_HEADER *section; | |
442 | 2042 |
2043 section = rva_to_section (import_dir.VirtualAddress, nt_header); | |
771 | 2044 imports = |
2045 (IMAGE_IMPORT_DESCRIPTOR *) RVA_TO_PTR (import_dir.VirtualAddress, | |
2046 section, executable); | |
2047 | |
442 | 2048 for ( ; imports->Name; imports++) |
2049 { | |
771 | 2050 Extbyte *dllname_ext = |
2051 (Extbyte *) RVA_TO_PTR (imports->Name, section, executable); | |
867 | 2052 Ibyte *dllname; |
771 | 2053 |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
2054 dllname = EXTERNAL_TO_ITEXT (dllname_ext, Qbinary); |
442 | 2055 |
2056 /* The exact name of the cygwin dll has changed with | |
2057 various releases, but hopefully this will be reasonably | |
2058 future proof. */ | |
867 | 2059 if (qxestrncasecmp (dllname, (Ibyte *) "cygwin", 6) == 0) |
442 | 2060 { |
2061 *is_cygnus_app = TRUE; | |
2062 break; | |
2063 } | |
2064 } | |
2065 } | |
2066 #endif | |
2067 } | |
2068 | |
2069 unwind: | |
2070 close_file_data (&executable); | |
2071 } | |
2072 | |
428 | 2073 /* Close the system structures associated with the given file. */ |
2074 void | |
2075 close_file_data (file_data *p_file) | |
2076 { | |
611 | 2077 UnmapViewOfFile (p_file->file_base); |
2078 CloseHandle (p_file->file_mapping); | |
2079 CloseHandle (p_file->file); | |
428 | 2080 } |
2081 | |
771 | 2082 |
2083 /* Some miscellaneous functions that are Windows specific, but not GUI | |
2084 specific (ie. are applicable in terminal or batch mode as well). */ | |
2085 | |
4487
866b84b7c97e
Remove interactive specs from #'mswindows-{short,long}-file-name,
Aidan Kehoe <kehoea@parhasard.net>
parents:
3648
diff
changeset
|
2086 DEFUN ("mswindows-short-file-name", Fmswindows_short_file_name, 1, 1, 0, /* |
771 | 2087 Return the short file name version (8.3) of the full path of FILENAME. |
2088 If FILENAME does not exist, return nil. | |
2089 All path elements in FILENAME are converted to their short names. | |
2090 */ | |
2091 (filename)) | |
2092 { | |
4854 | 2093 Extbyte shortname[PATH_MAX_TCHAR]; |
771 | 2094 Extbyte *fileext; |
867 | 2095 Ibyte *shortint; |
771 | 2096 |
2097 CHECK_STRING (filename); | |
2098 | |
2099 /* first expand it. */ | |
2100 filename = Fexpand_file_name (filename, Qnil); | |
2101 | |
2526 | 2102 LISP_PATHNAME_CONVERT_OUT (filename, fileext); |
771 | 2103 /* luckily, this returns the short version of each element in the path. */ |
2104 if (qxeGetShortPathName (fileext, shortname, | |
2105 sizeof (shortname) / XETCHAR_SIZE) == 0) | |
2106 return Qnil; | |
2107 | |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
2108 shortint = TSTR_TO_ITEXT (shortname); |
771 | 2109 MSWINDOWS_NORMALIZE_FILENAME (shortint); |
2110 | |
4953
304aebb79cd3
function renamings to track names of char typedefs
Ben Wing <ben@xemacs.org>
parents:
4854
diff
changeset
|
2111 return build_istring (shortint); |
771 | 2112 } |
2113 | |
2114 | |
4487
866b84b7c97e
Remove interactive specs from #'mswindows-{short,long}-file-name,
Aidan Kehoe <kehoea@parhasard.net>
parents:
3648
diff
changeset
|
2115 DEFUN ("mswindows-long-file-name", Fmswindows_long_file_name, 1, 1, 0, /* |
771 | 2116 Return the long file name version of the full path of FILENAME. |
2117 If FILENAME does not exist, return nil. | |
2118 All path elements in FILENAME are converted to their long names. | |
2119 */ | |
2120 (filename)) | |
2121 { | |
867 | 2122 Ibyte *longname, *canon; |
771 | 2123 Lisp_Object ret; |
2124 | |
2125 CHECK_STRING (filename); | |
2126 | |
2127 /* first expand it. */ | |
2128 filename = Fexpand_file_name (filename, Qnil); | |
2129 | |
2130 if (!(longname = mswindows_get_long_filename (XSTRING_DATA (filename)))) | |
2131 return Qnil; | |
2132 | |
2133 canon = mswindows_canonicalize_filename (longname); | |
4953
304aebb79cd3
function renamings to track names of char typedefs
Ben Wing <ben@xemacs.org>
parents:
4854
diff
changeset
|
2134 ret = build_istring (canon); |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
2135 xfree (canon); |
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
2136 xfree (longname); |
771 | 2137 return ret; |
2138 } | |
2139 | |
814 | 2140 |
2141 void | |
2142 init_nt (void) | |
2143 { | |
2144 /* Initial preparation for subprocess support: replace our standard | |
2145 handles with non-inheritable versions. | |
2146 | |
2147 #### Do we still need this? This is left over from the old process | |
2148 support. */ | |
2149 { | |
2150 HANDLE parent; | |
2151 HANDLE stdin_save = INVALID_HANDLE_VALUE; | |
2152 HANDLE stdout_save = INVALID_HANDLE_VALUE; | |
2153 HANDLE stderr_save = INVALID_HANDLE_VALUE; | |
2154 | |
2155 parent = GetCurrentProcess (); | |
2156 | |
2157 /* ignore errors when duplicating and closing; typically the | |
2158 handles will be invalid when running as a gui program. */ | |
2159 DuplicateHandle (parent, | |
2160 GetStdHandle (STD_INPUT_HANDLE), | |
2161 parent, | |
2162 &stdin_save, | |
2163 0, | |
2164 FALSE, | |
2165 DUPLICATE_SAME_ACCESS); | |
2166 | |
2167 DuplicateHandle (parent, | |
2168 GetStdHandle (STD_OUTPUT_HANDLE), | |
2169 parent, | |
2170 &stdout_save, | |
2171 0, | |
2172 FALSE, | |
2173 DUPLICATE_SAME_ACCESS); | |
2174 | |
2175 DuplicateHandle (parent, | |
2176 GetStdHandle (STD_ERROR_HANDLE), | |
2177 parent, | |
2178 &stderr_save, | |
2179 0, | |
2180 FALSE, | |
2181 DUPLICATE_SAME_ACCESS); | |
2182 | |
2183 retry_fclose (stdin); | |
2184 retry_fclose (stdout); | |
2185 retry_fclose (stderr); | |
2186 | |
2187 if (stdin_save != INVALID_HANDLE_VALUE) | |
2188 _open_osfhandle ((long) stdin_save, O_TEXT); | |
2189 else | |
2190 _open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY); | |
2191 _fdopen (0, "r"); | |
2192 | |
2193 if (stdout_save != INVALID_HANDLE_VALUE) | |
2194 _open_osfhandle ((long) stdout_save, O_TEXT); | |
2195 else | |
2196 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY); | |
2197 _fdopen (1, "w"); | |
2198 | |
2199 if (stderr_save != INVALID_HANDLE_VALUE) | |
2200 _open_osfhandle ((long) stderr_save, O_TEXT); | |
2201 else | |
2202 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY); | |
2203 _fdopen (2, "w"); | |
2204 } | |
2205 | |
2206 /* determine which drives are fixed, for get_cached_volume_information */ | |
2207 { | |
2208 /* GetDriveType must have trailing backslash. */ | |
867 | 2209 Ibyte drive[] = "A:\\"; |
814 | 2210 |
2211 /* Loop over all possible drive letters */ | |
2212 while (*drive <= 'Z') | |
2213 { | |
2214 Extbyte *driveext; | |
2215 | |
2526 | 2216 PATHNAME_CONVERT_OUT (drive, driveext); |
814 | 2217 |
2218 /* Record if this drive letter refers to a fixed drive. */ | |
2219 fixed_drives[DRIVE_INDEX (*drive)] = | |
2220 (qxeGetDriveType (driveext) == DRIVE_FIXED); | |
2221 | |
2222 (*drive)++; | |
2223 } | |
2224 | |
2225 /* Reset the volume info cache. */ | |
2226 volume_cache = NULL; | |
2227 } | |
2228 } | |
2229 | |
771 | 2230 void |
2231 syms_of_nt (void) | |
2232 { | |
2233 DEFSUBR (Fmswindows_short_file_name); | |
2234 DEFSUBR (Fmswindows_long_file_name); | |
2235 } | |
2236 | |
440 | 2237 void |
2238 vars_of_nt (void) | |
2239 { | |
771 | 2240 DEFVAR_INT ("mswindows-fake-unix-uid", &mswindows_fake_unix_uid /* |
440 | 2241 *Set uid returned by `user-uid' and `user-real-uid'. |
771 | 2242 Under NT and 9x, there are no uids, and even no almighty user called root. |
2243 By setting this variable, you can have any uid of choice. Default is 0. | |
440 | 2244 Changes to this variable take effect immediately. |
2245 */ ); | |
771 | 2246 mswindows_fake_unix_uid = 0; |
2247 | |
2248 DEFVAR_LISP ("mswindows-get-true-file-attributes", &Vmswindows_get_true_file_attributes /* | |
2249 Non-nil means determine accurate link count in file-attributes. | |
2250 This option slows down file-attributes noticeably, so is disabled by | |
2251 default. Note that it is only useful for files on NTFS volumes, | |
2252 where hard links are supported. | |
2253 */ ); | |
2254 Vmswindows_get_true_file_attributes = Qnil; | |
440 | 2255 } |
2256 | |
428 | 2257 /* end of nt.c */ |