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