1 /*
2 * File handling functions
3 *
4 * Copyright 1993 John Burton
5 * Copyright 1996 Alexandre Julliard
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 *
21 * TODO:
22 * Fix the CopyFileEx methods to implement the "extended" functionality.
23 * Right now, they simply call the CopyFile method.
24 */
25
26 #include "config.h"
27 #include "wine/port.h"
28
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <assert.h>
32
33 #define NONAMELESSUNION
34 #define NONAMELESSSTRUCT
35 #include "winerror.h"
36 #include "windef.h"
37 #include "winbase.h"
38 #include "winternl.h"
39 #include "wine/winbase16.h"
40 #include "kernel16_private.h"
41 #include "wine/unicode.h"
42 #include "wine/debug.h"
43
44 WINE_DEFAULT_DEBUG_CHANNEL(file);
45
46 #define DOS_TABLE_SIZE 256
47
48 static HANDLE dos_handles[DOS_TABLE_SIZE];
49
50 /***********************************************************************
51 * FILE_InitProcessDosHandles
52 *
53 * Allocates the default DOS handles for a process. Called either by
54 * Win32HandleToDosFileHandle below or by the DOSVM stuff.
55 */
56 static void FILE_InitProcessDosHandles( void )
57 {
58 static BOOL init_done /* = FALSE */;
59 HANDLE cp = GetCurrentProcess();
60
61 if (init_done) return;
62 init_done = TRUE;
63 DuplicateHandle(cp, GetStdHandle(STD_INPUT_HANDLE), cp, &dos_handles[0],
64 0, TRUE, DUPLICATE_SAME_ACCESS);
65 DuplicateHandle(cp, GetStdHandle(STD_OUTPUT_HANDLE), cp, &dos_handles[1],
66 0, TRUE, DUPLICATE_SAME_ACCESS);
67 DuplicateHandle(cp, GetStdHandle(STD_ERROR_HANDLE), cp, &dos_handles[2],
68 0, TRUE, DUPLICATE_SAME_ACCESS);
69 DuplicateHandle(cp, GetStdHandle(STD_ERROR_HANDLE), cp, &dos_handles[3],
70 0, TRUE, DUPLICATE_SAME_ACCESS);
71 DuplicateHandle(cp, GetStdHandle(STD_ERROR_HANDLE), cp, &dos_handles[4],
72 0, TRUE, DUPLICATE_SAME_ACCESS);
73 }
74
75 /***********************************************************************
76 * DosFileHandleToWin32Handle (KERNEL32.20)
77 *
78 * Return the Win32 handle for a DOS handle.
79 *
80 * Note: this is not exactly right, since on Win95 the Win32 handles
81 * are on top of DOS handles and we do it the other way
82 * around. Should be good enough though.
83 */
84 HANDLE WINAPI DosFileHandleToWin32Handle( HFILE handle )
85 {
86 HFILE16 hfile = (HFILE16)handle;
87 if (hfile < 5) FILE_InitProcessDosHandles();
88 if ((hfile >= DOS_TABLE_SIZE) || !dos_handles[hfile])
89 {
90 SetLastError( ERROR_INVALID_HANDLE );
91 return INVALID_HANDLE_VALUE;
92 }
93 return dos_handles[hfile];
94 }
95
96 /***********************************************************************
97 * Win32HandleToDosFileHandle (KERNEL32.21)
98 *
99 * Allocate a DOS handle for a Win32 handle. The Win32 handle is no
100 * longer valid after this function (even on failure).
101 *
102 * Note: this is not exactly right, since on Win95 the Win32 handles
103 * are on top of DOS handles and we do it the other way
104 * around. Should be good enough though.
105 */
106 HFILE WINAPI Win32HandleToDosFileHandle( HANDLE handle )
107 {
108 int i;
109
110 if (!handle || (handle == INVALID_HANDLE_VALUE))
111 return HFILE_ERROR;
112
113 FILE_InitProcessDosHandles();
114 for (i = 0; i < DOS_TABLE_SIZE; i++)
115 if (!dos_handles[i])
116 {
117 dos_handles[i] = handle;
118 TRACE("Got %d for h32 %p\n", i, handle );
119 return (HFILE)i;
120 }
121 CloseHandle( handle );
122 SetLastError( ERROR_TOO_MANY_OPEN_FILES );
123 return HFILE_ERROR;
124 }
125
126 /***********************************************************************
127 * DisposeLZ32Handle (KERNEL32.22)
128 *
129 * Note: this is not entirely correct, we should only close the
130 * 32-bit handle and not the 16-bit one, but we cannot do
131 * this because of the way our DOS handles are implemented.
132 * It shouldn't break anything though.
133 */
134 void WINAPI DisposeLZ32Handle( HANDLE handle )
135 {
136 int i;
137
138 if (!handle || (handle == INVALID_HANDLE_VALUE)) return;
139
140 for (i = 5; i < DOS_TABLE_SIZE; i++)
141 if (dos_handles[i] == handle)
142 {
143 dos_handles[i] = 0;
144 CloseHandle( handle );
145 break;
146 }
147 }
148
149 /***********************************************************************
150 * GetProfileInt (KERNEL.57)
151 */
152 UINT16 WINAPI GetProfileInt16( LPCSTR section, LPCSTR entry, INT16 def_val )
153 {
154 return GetPrivateProfileInt16( section, entry, def_val, "win.ini" );
155 }
156
157
158 /***********************************************************************
159 * GetProfileString (KERNEL.58)
160 */
161 INT16 WINAPI GetProfileString16( LPCSTR section, LPCSTR entry, LPCSTR def_val,
162 LPSTR buffer, UINT16 len )
163 {
164 return GetPrivateProfileString16( section, entry, def_val,
165 buffer, len, "win.ini" );
166 }
167
168
169 /***********************************************************************
170 * WriteProfileString (KERNEL.59)
171 */
172 BOOL16 WINAPI WriteProfileString16( LPCSTR section, LPCSTR entry,
173 LPCSTR string )
174 {
175 return WritePrivateProfileString16( section, entry, string, "win.ini" );
176 }
177
178
179 /* get the search path for the current module; helper for OpenFile16 */
180 static char *get_search_path(void)
181 {
182 UINT len;
183 char *ret, *p, module[OFS_MAXPATHNAME];
184
185 module[0] = 0;
186 if (GetCurrentTask() && GetModuleFileName16( GetCurrentTask(), module, sizeof(module) ))
187 {
188 if (!(p = strrchr( module, '\\' ))) p = module;
189 *p = 0;
190 }
191
192 len = (2 + /* search order: first current dir */
193 GetSystemDirectory16( NULL, 0 ) + 1 + /* then system dir */
194 GetWindowsDirectoryA( NULL, 0 ) + 1 + /* then windows dir */
195 strlen( module ) + 1 + /* then module path */
196 GetEnvironmentVariableA( "PATH", NULL, 0 ) + 1); /* then look in PATH */
197 if (!(ret = HeapAlloc( GetProcessHeap(), 0, len ))) return NULL;
198 strcpy( ret, ".;" );
199 p = ret + 2;
200 GetSystemDirectory16( p, ret + len - p );
201 p += strlen( p );
202 *p++ = ';';
203 GetWindowsDirectoryA( p, ret + len - p );
204 p += strlen( p );
205 *p++ = ';';
206 if (module[0])
207 {
208 strcpy( p, module );
209 p += strlen( p );
210 *p++ = ';';
211 }
212 GetEnvironmentVariableA( "PATH", p, ret + len - p );
213 return ret;
214 }
215
216 /***********************************************************************
217 * OpenFile (KERNEL.74)
218 * OpenFileEx (KERNEL.360)
219 */
220 HFILE16 WINAPI OpenFile16( LPCSTR name, OFSTRUCT *ofs, UINT16 mode )
221 {
222 HFILE hFileRet;
223 HANDLE handle;
224 FILETIME filetime;
225 WORD filedatetime[2];
226 const char *p, *filename;
227
228 if (!ofs) return HFILE_ERROR;
229
230 TRACE("%s %s %s %s%s%s%s%s%s%s%s%s\n",debugstr_a(name),
231 ((mode & 0x3 )==OF_READ)?"OF_READ":
232 ((mode & 0x3 )==OF_WRITE)?"OF_WRITE":
233 ((mode & 0x3 )==OF_READWRITE)?"OF_READWRITE":"unknown",
234 ((mode & 0x70 )==OF_SHARE_COMPAT)?"OF_SHARE_COMPAT":
235 ((mode & 0x70 )==OF_SHARE_DENY_NONE)?"OF_SHARE_DENY_NONE":
236 ((mode & 0x70 )==OF_SHARE_DENY_READ)?"OF_SHARE_DENY_READ":
237 ((mode & 0x70 )==OF_SHARE_DENY_WRITE)?"OF_SHARE_DENY_WRITE":
238 ((mode & 0x70 )==OF_SHARE_EXCLUSIVE)?"OF_SHARE_EXCLUSIVE":"unknown",
239 ((mode & OF_PARSE )==OF_PARSE)?"OF_PARSE ":"",
240 ((mode & OF_DELETE )==OF_DELETE)?"OF_DELETE ":"",
241 ((mode & OF_VERIFY )==OF_VERIFY)?"OF_VERIFY ":"",
242 ((mode & OF_SEARCH )==OF_SEARCH)?"OF_SEARCH ":"",
243 ((mode & OF_CANCEL )==OF_CANCEL)?"OF_CANCEL ":"",
244 ((mode & OF_CREATE )==OF_CREATE)?"OF_CREATE ":"",
245 ((mode & OF_PROMPT )==OF_PROMPT)?"OF_PROMPT ":"",
246 ((mode & OF_EXIST )==OF_EXIST)?"OF_EXIST ":"",
247 ((mode & OF_REOPEN )==OF_REOPEN)?"OF_REOPEN ":""
248 );
249
250 if (mode & OF_PARSE)
251 {
252 OpenFile( name, ofs, mode );
253 return 0;
254 }
255
256 if (mode & OF_CREATE)
257 {
258 handle = (HANDLE)OpenFile( name, ofs, mode );
259 if (handle == (HANDLE)HFILE_ERROR) goto error;
260 }
261 else
262 {
263 ofs->cBytes = sizeof(OFSTRUCT);
264 ofs->nErrCode = 0;
265 if (mode & OF_REOPEN) name = ofs->szPathName;
266
267 if (!name) return HFILE_ERROR;
268
269 /* the watcom 10.6 IDE relies on a valid path returned in ofs->szPathName
270 Are there any cases where getting the path here is wrong?
271 Uwe Bonnes 1997 Apr 2 */
272 if (!GetFullPathNameA( name, sizeof(ofs->szPathName), ofs->szPathName, NULL )) goto error;
273
274 /* If OF_SEARCH is set, ignore the given path */
275
276 filename = name;
277 if ((mode & OF_SEARCH) && !(mode & OF_REOPEN))
278 {
279 /* First try the file name as is */
280 if (GetFileAttributesA( filename ) != INVALID_FILE_ATTRIBUTES) filename = NULL;
281 else
282 {
283 /* Now remove the path */
284 if (filename[0] && (filename[1] == ':')) filename += 2;
285 if ((p = strrchr( filename, '\\' ))) filename = p + 1;
286 if ((p = strrchr( filename, '/' ))) filename = p + 1;
287 if (!filename[0])
288 {
289 SetLastError( ERROR_FILE_NOT_FOUND );
290 goto error;
291 }
292 }
293 }
294
295 /* Now look for the file */
296
297 if (filename)
298 {
299 BOOL found;
300 char *path = get_search_path();
301
302 if (!path) goto error;
303 found = SearchPathA( path, filename, NULL, sizeof(ofs->szPathName),
304 ofs->szPathName, NULL );
305 HeapFree( GetProcessHeap(), 0, path );
306 if (!found) goto error;
307 }
308
309 TRACE("found %s\n", debugstr_a(ofs->szPathName) );
310
311 if (mode & OF_DELETE)
312 {
313 if (!DeleteFileA( ofs->szPathName )) goto error;
314 TRACE("(%s): OF_DELETE return = OK\n", name);
315 return 1;
316 }
317
318 handle = (HANDLE)_lopen( ofs->szPathName, mode );
319 if (handle == INVALID_HANDLE_VALUE) goto error;
320
321 GetFileTime( handle, NULL, NULL, &filetime );
322 FileTimeToDosDateTime( &filetime, &filedatetime[0], &filedatetime[1] );
323 if ((mode & OF_VERIFY) && (mode & OF_REOPEN))
324 {
325 if (ofs->Reserved1 != filedatetime[0] || ofs->Reserved2 != filedatetime[1] )
326 {
327 CloseHandle( handle );
328 WARN("(%s): OF_VERIFY failed\n", name );
329 /* FIXME: what error here? */
330 SetLastError( ERROR_FILE_NOT_FOUND );
331 goto error;
332 }
333 }
334 ofs->Reserved1 = filedatetime[0];
335 ofs->Reserved2 = filedatetime[1];
336 }
337
338 TRACE("(%s): OK, return = %p\n", name, handle );
339 hFileRet = Win32HandleToDosFileHandle( handle );
340 if (hFileRet == HFILE_ERROR16) goto error;
341 if (mode & OF_EXIST) _lclose16( hFileRet ); /* Return the handle, but close it first */
342 return hFileRet;
343
344 error: /* We get here if there was an error opening the file */
345 ofs->nErrCode = GetLastError();
346 WARN("(%s): return = HFILE_ERROR error= %d\n", name,ofs->nErrCode );
347 return HFILE_ERROR16;
348 }
349
350
351 /***********************************************************************
352 * _lclose (KERNEL.81)
353 */
354 HFILE16 WINAPI _lclose16( HFILE16 hFile )
355 {
356 if ((hFile >= DOS_TABLE_SIZE) || !dos_handles[hFile])
357 {
358 SetLastError( ERROR_INVALID_HANDLE );
359 return HFILE_ERROR16;
360 }
361 TRACE("%d (handle32=%p)\n", hFile, dos_handles[hFile] );
362 CloseHandle( dos_handles[hFile] );
363 dos_handles[hFile] = 0;
364 return 0;
365 }
366
367 /***********************************************************************
368 * _lcreat (KERNEL.83)
369 */
370 HFILE16 WINAPI _lcreat16( LPCSTR path, INT16 attr )
371 {
372 return Win32HandleToDosFileHandle( (HANDLE)_lcreat( path, attr ) );
373 }
374
375 /***********************************************************************
376 * _llseek (KERNEL.84)
377 *
378 * FIXME:
379 * Seeking before the start of the file should be allowed for _llseek16,
380 * but cause subsequent I/O operations to fail (cf. interrupt list)
381 *
382 */
383 LONG WINAPI _llseek16( HFILE16 hFile, LONG lOffset, INT16 nOrigin )
384 {
385 return SetFilePointer( DosFileHandleToWin32Handle(hFile), lOffset, NULL, nOrigin );
386 }
387
388
389 /***********************************************************************
390 * _lopen (KERNEL.85)
391 */
392 HFILE16 WINAPI _lopen16( LPCSTR path, INT16 mode )
393 {
394 return Win32HandleToDosFileHandle( (HANDLE)_lopen( path, mode ) );
395 }
396
397
398 /***********************************************************************
399 * _lread16 (KERNEL.82)
400 */
401 UINT16 WINAPI _lread16( HFILE16 hFile, LPVOID buffer, UINT16 count )
402 {
403 return (UINT16)_lread((HFILE)DosFileHandleToWin32Handle(hFile), buffer, (LONG)count );
404 }
405
406
407 /***********************************************************************
408 * _lwrite (KERNEL.86)
409 */
410 UINT16 WINAPI _lwrite16( HFILE16 hFile, LPCSTR buffer, UINT16 count )
411 {
412 return (UINT16)_hwrite( (HFILE)DosFileHandleToWin32Handle(hFile), buffer, (LONG)count );
413 }
414
415 /***********************************************************************
416 * _hread (KERNEL.349)
417 */
418 LONG WINAPI WIN16_hread( HFILE16 hFile, SEGPTR buffer, LONG count )
419 {
420 LONG maxlen;
421
422 TRACE("%d %08x %d\n", hFile, (DWORD)buffer, count );
423
424 /* Some programs pass a count larger than the allocated buffer */
425 maxlen = GetSelectorLimit16( SELECTOROF(buffer) ) - OFFSETOF(buffer) + 1;
426 if (count > maxlen) count = maxlen;
427 return _lread((HFILE)DosFileHandleToWin32Handle(hFile), MapSL(buffer), count );
428 }
429
430
431 /***********************************************************************
432 * _lread (KERNEL.82)
433 */
434 UINT16 WINAPI WIN16_lread( HFILE16 hFile, SEGPTR buffer, UINT16 count )
435 {
436 return (UINT16)WIN16_hread( hFile, buffer, (LONG)count );
437 }
438
439
440 /***********************************************************************
441 * _hwrite (KERNEL.350)
442 */
443 LONG WINAPI _hwrite16( HFILE16 hFile, LPCSTR buffer, LONG count )
444 {
445 return _hwrite( (HFILE)DosFileHandleToWin32Handle(hFile), buffer, count );
446 }
447
448
449 /***********************************************************************
450 * GetTempDrive (KERNEL.92)
451 * A closer look at krnl386.exe shows what the SDK doesn't mention:
452 *
453 * returns:
454 * AL: driveletter
455 * AH: ':' - yes, some kernel code even does stosw with
456 * the returned AX.
457 * DX: 1 for success
458 */
459 UINT WINAPI GetTempDrive( BYTE ignored )
460 {
461 WCHAR buffer[8];
462 BYTE ret;
463
464 if (GetTempPathW( 8, buffer )) ret = (BYTE)toupperW(buffer[0]);
465 else ret = 'C';
466 return MAKELONG( ret | (':' << 8), 1 );
467 }
468
469
470 /***********************************************************************
471 * GetTempFileName (KERNEL.97)
472 */
473 UINT16 WINAPI GetTempFileName16( BYTE drive, LPCSTR prefix, UINT16 unique,
474 LPSTR buffer )
475 {
476 char temppath[MAX_PATH];
477 char *prefix16 = NULL;
478 UINT16 ret;
479
480 if (!(drive & ~TF_FORCEDRIVE)) /* drive 0 means current default drive */
481 {
482 GetCurrentDirectoryA(sizeof(temppath), temppath);
483 drive |= temppath[0];
484 }
485
486 if (drive & TF_FORCEDRIVE)
487 {
488 char d[3];
489
490 d[0] = drive & ~TF_FORCEDRIVE;
491 d[1] = ':';
492 d[2] = '\0';
493 if (GetDriveTypeA(d) == DRIVE_NO_ROOT_DIR)
494 {
495 drive &= ~TF_FORCEDRIVE;
496 WARN("invalid drive %d specified\n", drive );
497 }
498 }
499
500 if (drive & TF_FORCEDRIVE)
501 sprintf(temppath,"%c:", drive & ~TF_FORCEDRIVE );
502 else
503 GetTempPathA( MAX_PATH, temppath );
504
505 if (prefix)
506 {
507 prefix16 = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + 2);
508 *prefix16 = '~';
509 strcpy(prefix16 + 1, prefix);
510 }
511
512 ret = GetTempFileNameA( temppath, prefix16, unique, buffer );
513
514 HeapFree(GetProcessHeap(), 0, prefix16);
515 return ret;
516 }
517
518
519 /***********************************************************************
520 * GetPrivateProfileInt (KERNEL.127)
521 */
522 UINT16 WINAPI GetPrivateProfileInt16( LPCSTR section, LPCSTR entry,
523 INT16 def_val, LPCSTR filename )
524 {
525 /* we used to have some elaborate return value limitation (<= -32768 etc.)
526 * here, but Win98SE doesn't care about this at all, so I deleted it.
527 * AFAIR versions prior to Win9x had these limits, though. */
528 return (INT16)GetPrivateProfileIntA(section,entry,def_val,filename);
529 }
530
531
532 /***********************************************************************
533 * GetPrivateProfileString (KERNEL.128)
534 */
535 INT16 WINAPI GetPrivateProfileString16( LPCSTR section, LPCSTR entry,
536 LPCSTR def_val, LPSTR buffer,
537 UINT16 len, LPCSTR filename )
538 {
539 if (!section)
540 {
541 if (buffer && len) buffer[0] = 0;
542 return 0;
543 }
544 if (!entry)
545 {
546 /* We have to return the list of keys in the section but without the values
547 * so we need to massage the results of GetPrivateProfileSectionA.
548 */
549 UINT ret, oldlen = len, size = min( len, 1024 );
550 LPSTR data, src;
551
552 for (;;)
553 {
554 if (!(data = HeapAlloc(GetProcessHeap(), 0, size ))) return 0;
555 ret = GetPrivateProfileSectionA( section, data, size, filename );
556 if (!ret)
557 {
558 HeapFree( GetProcessHeap(), 0, data );
559 return GetPrivateProfileStringA( section, entry, def_val, buffer, len, filename );
560 }
561 if (ret != size - 2) break;
562 /* overflow, try again */
563 size *= 2;
564 HeapFree( GetProcessHeap(), 0, data );
565 }
566
567 src = data;
568 while (len && *src)
569 {
570 char *p = strchr( src, '=' );
571
572 if (!p) p = src + strlen(src);
573 if (p - src < len)
574 {
575 memcpy( buffer, src, p - src );
576 buffer += p - src;
577 *buffer++ = 0;
578 len -= (p - src) + 1;
579 src += strlen(src) + 1;
580 }
581 else /* overflow */
582 {
583 memcpy( buffer, src, len );
584 buffer += len;
585 len = 0;
586 }
587 }
588 HeapFree( GetProcessHeap(), 0, data );
589
590 if (len)
591 {
592 *buffer = 0;
593 return oldlen - len;
594 }
595 if (oldlen > 2)
596 {
597 buffer[-2] = 0;
598 buffer[-1] = 0;
599 return oldlen - 2;
600 }
601 return 0;
602 }
603 return GetPrivateProfileStringA( section, entry, def_val, buffer, len, filename );
604 }
605
606
607 /***********************************************************************
608 * WritePrivateProfileString (KERNEL.129)
609 */
610 BOOL16 WINAPI WritePrivateProfileString16( LPCSTR section, LPCSTR entry,
611 LPCSTR string, LPCSTR filename )
612 {
613 return WritePrivateProfileStringA(section,entry,string,filename);
614 }
615
616
617 /***********************************************************************
618 * GetWindowsDirectory (KERNEL.134)
619 */
620 UINT16 WINAPI GetWindowsDirectory16( LPSTR path, UINT16 count )
621 {
622 return GetWindowsDirectoryA( path, count );
623 }
624
625
626 /***********************************************************************
627 * GetSystemDirectory (KERNEL.135)
628 */
629 UINT16 WINAPI GetSystemDirectory16( LPSTR path, UINT16 count )
630 {
631 static const char system16[] = "\\SYSTEM";
632 char windir[MAX_PATH];
633 UINT16 len;
634
635 len = GetWindowsDirectory16(windir, sizeof(windir) - sizeof(system16) + 1) + sizeof(system16);
636 if (count >= len)
637 {
638 lstrcpyA(path, windir);
639 lstrcatA(path, system16);
640 len--; /* space for the terminating zero is not included on success */
641 }
642 return len;
643 }
644
645
646 /***********************************************************************
647 * GetDriveType (KERNEL.136)
648 * Get the type of a drive in Win16.
649 *
650 * RETURNS
651 * The type of the Drive. For a list see GetDriveTypeW from kernel32.
652 *
653 * NOTES
654 * Note that it returns DRIVE_REMOTE for CD-ROMs, since MSCDEX uses the
655 * remote drive API. The return value DRIVE_REMOTE for CD-ROMs has been
656 * verified on Win 3.11 and Windows 95. Some programs rely on it, so don't
657 * do any pseudo-clever changes.
658 */
659 UINT16 WINAPI GetDriveType16( UINT16 drive ) /* [in] number (NOT letter) of drive */
660 {
661 UINT type;
662 WCHAR root[3];
663
664 root[0] = 'A' + drive;
665 root[1] = ':';
666 root[2] = 0;
667 type = GetDriveTypeW( root );
668 if (type == DRIVE_CDROM) type = DRIVE_REMOTE;
669 else if (type == DRIVE_NO_ROOT_DIR) type = DRIVE_UNKNOWN;
670 return type;
671 }
672
673
674 /***********************************************************************
675 * GetProfileSectionNames (KERNEL.142)
676 */
677 WORD WINAPI GetProfileSectionNames16(LPSTR buffer, WORD size)
678
679 {
680 return GetPrivateProfileSectionNamesA(buffer,size,"win.ini");
681 }
682
683
684 /***********************************************************************
685 * GetPrivateProfileSectionNames (KERNEL.143)
686 */
687 WORD WINAPI GetPrivateProfileSectionNames16( LPSTR buffer, WORD size,
688 LPCSTR filename )
689 {
690 return GetPrivateProfileSectionNamesA(buffer,size,filename);
691 }
692
693
694 /***********************************************************************
695 * CreateDirectory (KERNEL.144)
696 */
697 BOOL16 WINAPI CreateDirectory16( LPCSTR path, LPVOID dummy )
698 {
699 return CreateDirectoryA( path, NULL );
700 }
701
702
703 /***********************************************************************
704 * RemoveDirectory (KERNEL.145)
705 */
706 BOOL16 WINAPI RemoveDirectory16( LPCSTR path )
707 {
708 return RemoveDirectoryA( path );
709 }
710
711
712 /***********************************************************************
713 * DeleteFile (KERNEL.146)
714 */
715 BOOL16 WINAPI DeleteFile16( LPCSTR path )
716 {
717 return DeleteFileA( path );
718 }
719
720
721 /***********************************************************************
722 * SetHandleCount (KERNEL.199)
723 */
724 UINT16 WINAPI SetHandleCount16( UINT16 count )
725 {
726 return SetHandleCount( count );
727 }
728
729
730 /***********************************************************************
731 * GetShortPathName (KERNEL.274)
732 */
733 WORD WINAPI GetShortPathName16( LPCSTR longpath, LPSTR shortpath, WORD len )
734 {
735 return GetShortPathNameA( longpath, shortpath, len );
736 }
737
738
739 /***********************************************************************
740 * WriteOutProfiles (KERNEL.315)
741 */
742 void WINAPI WriteOutProfiles16(void)
743 {
744 WritePrivateProfileSectionW( NULL, NULL, NULL );
745 }
746
747
748 /***********************************************************************
749 * WritePrivateProfileStruct (KERNEL.406)
750 */
751 BOOL16 WINAPI WritePrivateProfileStruct16 (LPCSTR section, LPCSTR key,
752 LPVOID buf, UINT16 bufsize, LPCSTR filename)
753 {
754 return WritePrivateProfileStructA( section, key, buf, bufsize, filename );
755 }
756
757
758 /***********************************************************************
759 * GetPrivateProfileStruct (KERNEL.407)
760 */
761 BOOL16 WINAPI GetPrivateProfileStruct16(LPCSTR section, LPCSTR key,
762 LPVOID buf, UINT16 len, LPCSTR filename)
763 {
764 return GetPrivateProfileStructA( section, key, buf, len, filename );
765 }
766
767
768 /***********************************************************************
769 * GetCurrentDirectory (KERNEL.411)
770 */
771 UINT16 WINAPI GetCurrentDirectory16( UINT16 buflen, LPSTR buf )
772 {
773 return GetCurrentDirectoryA( buflen, buf );
774 }
775
776
777 /***********************************************************************
778 * SetCurrentDirectory (KERNEL.412)
779 */
780 BOOL16 WINAPI SetCurrentDirectory16( LPCSTR dir )
781 {
782 char fulldir[MAX_PATH];
783
784 if (!GetFullPathNameA( dir, MAX_PATH, fulldir, NULL )) return FALSE;
785
786 if (!SetCurrentDirectoryA( dir )) return FALSE;
787
788 if (fulldir[0] && fulldir[1] == ':')
789 {
790 TDB *pTask = GlobalLock16( GetCurrentTask() );
791 char env_var[4] = "=A:";
792
793 env_var[1] = fulldir[0];
794 SetEnvironmentVariableA( env_var, fulldir );
795
796 /* update the directory in the TDB */
797 if (pTask)
798 {
799 pTask->curdrive = 0x80 | (fulldir[0] - 'A');
800 GetShortPathNameA( fulldir + 2, pTask->curdir, sizeof(pTask->curdir) );
801 }
802 }
803 return TRUE;
804 }
805
806
807 /*************************************************************************
808 * FindFirstFile (KERNEL.413)
809 */
810 HANDLE16 WINAPI FindFirstFile16( LPCSTR path, WIN32_FIND_DATAA *data )
811 {
812 HGLOBAL16 h16;
813 HANDLE handle, *ptr;
814
815 if (!(h16 = GlobalAlloc16( GMEM_MOVEABLE, sizeof(handle) ))) return INVALID_HANDLE_VALUE16;
816 ptr = GlobalLock16( h16 );
817 *ptr = handle = FindFirstFileA( path, data );
818 GlobalUnlock16( h16 );
819
820 if (handle == INVALID_HANDLE_VALUE)
821 {
822 GlobalFree16( h16 );
823 h16 = INVALID_HANDLE_VALUE16;
824 }
825 return h16;
826 }
827
828
829 /*************************************************************************
830 * FindNextFile (KERNEL.414)
831 */
832 BOOL16 WINAPI FindNextFile16( HANDLE16 handle, WIN32_FIND_DATAA *data )
833 {
834 HANDLE *ptr;
835 BOOL ret = FALSE;
836
837 if ((handle == INVALID_HANDLE_VALUE16) || !(ptr = GlobalLock16( handle )))
838 {
839 SetLastError( ERROR_INVALID_HANDLE );
840 return ret;
841 }
842 ret = FindNextFileA( *ptr, data );
843 GlobalUnlock16( handle );
844 return ret;
845 }
846
847
848 /*************************************************************************
849 * FindClose (KERNEL.415)
850 */
851 BOOL16 WINAPI FindClose16( HANDLE16 handle )
852 {
853 HANDLE *ptr;
854
855 if ((handle == INVALID_HANDLE_VALUE16) || !(ptr = GlobalLock16( handle )))
856 {
857 SetLastError( ERROR_INVALID_HANDLE );
858 return FALSE;
859 }
860 FindClose( *ptr );
861 GlobalUnlock16( handle );
862 GlobalFree16( handle );
863 return TRUE;
864 }
865
866
867 /***********************************************************************
868 * WritePrivateProfileSection (KERNEL.416)
869 */
870 BOOL16 WINAPI WritePrivateProfileSection16( LPCSTR section,
871 LPCSTR string, LPCSTR filename )
872 {
873 return WritePrivateProfileSectionA( section, string, filename );
874 }
875
876
877 /***********************************************************************
878 * WriteProfileSection (KERNEL.417)
879 */
880 BOOL16 WINAPI WriteProfileSection16( LPCSTR section, LPCSTR keys_n_values)
881 {
882 return WritePrivateProfileSection16( section, keys_n_values, "win.ini");
883 }
884
885
886 /***********************************************************************
887 * GetPrivateProfileSection (KERNEL.418)
888 */
889 INT16 WINAPI GetPrivateProfileSection16( LPCSTR section, LPSTR buffer,
890 UINT16 len, LPCSTR filename )
891 {
892 return GetPrivateProfileSectionA( section, buffer, len, filename );
893 }
894
895
896 /***********************************************************************
897 * GetProfileSection (KERNEL.419)
898 */
899 INT16 WINAPI GetProfileSection16( LPCSTR section, LPSTR buffer, UINT16 len )
900 {
901 return GetPrivateProfileSection16( section, buffer, len, "win.ini" );
902 }
903
904
905 /**************************************************************************
906 * GetFileAttributes (KERNEL.420)
907 */
908 DWORD WINAPI GetFileAttributes16( LPCSTR name )
909 {
910 return GetFileAttributesA( name );
911 }
912
913
914 /**************************************************************************
915 * SetFileAttributes (KERNEL.421)
916 */
917 BOOL16 WINAPI SetFileAttributes16( LPCSTR lpFileName, DWORD attributes )
918 {
919 return SetFileAttributesA( lpFileName, attributes );
920 }
921
922
923 /***********************************************************************
924 * GetDiskFreeSpace (KERNEL.422)
925 */
926 BOOL16 WINAPI GetDiskFreeSpace16( LPCSTR root, LPDWORD cluster_sectors,
927 LPDWORD sector_bytes, LPDWORD free_clusters,
928 LPDWORD total_clusters )
929 {
930 return GetDiskFreeSpaceA( root, cluster_sectors, sector_bytes,
931 free_clusters, total_clusters );
932 }
933
934 /***********************************************************************
935 * FileCDR (KERNEL.130)
936 */
937 FARPROC16 WINAPI FileCDR16(FARPROC16 x)
938 {
939 FIXME("(%p): stub\n", x);
940 return (FARPROC16)TRUE;
941 }
942
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.