source: trunk/src/kernel32/Fileio.cpp@ 9011

Last change on this file since 9011 was 9011, checked in by sandervl, 23 years ago

PF: Fully implemented GetShortPathNameA/W & GetLongPathNameA/W

File size: 64.6 KB
Line 
1/* $Id: Fileio.cpp,v 1.67 2002-08-16 09:56:30 sandervl Exp $ */
2
3/*
4 * Win32 File IO API functions for OS/2
5 *
6 * Copyright 1998-2000 Sander van Leeuwen
7 * Copyright 1998 Patrick Haller
8 *
9 * Some parts based on Wine code (CopyFileExA/W, FindFirstFileExW,
10 * GetShortPathNameA/W, GetLongPathNameA/W)
11 *
12 * Copyright 1993 John Burton
13 * Copyright 1993 Erik Bos
14 * Copyright 1996 Alexandre Julliard
15 *
16 *
17 * Project Odin Software License can be found in LICENSE.TXT
18 *
19 */
20
21
22/*****************************************************************************
23 * Includes *
24 *****************************************************************************/
25
26#include <odin.h>
27#include <odinwrap.h>
28#include <os2sel.h>
29
30#include <os2win.h>
31#include <stdlib.h>
32#include <string.h>
33#include "unicode.h"
34#include <heapstring.h>
35#include "handlemanager.h"
36#include "oslibdos.h"
37
38#define DBG_LOCALLOG DBG_fileio
39#include "dbglocal.h"
40
41ODINDEBUGCHANNEL(KERNEL32-FILEIO)
42
43#include <ctype.h>
44#include "fileio.h"
45#include <win/file.h>
46
47
48/***********************************************************************
49 * DOSFS_ValidDOSName
50 *
51 * Return 1 if OS/2 file 'name' is also a valid MS-DOS name
52 * (i.e. contains only valid DOS chars, lower-case only, fits in 8.3 format).
53 * File name can be terminated by '\0', '\\' or '/'.
54 */
55static int DOSFS_ValidDOSName( const char *name, int ignore_case )
56{
57 static const char invalid_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" INVALID_DOS_CHARS;
58 const char *p = name;
59 const char *invalid = ignore_case ? (invalid_chars + 26) : invalid_chars;
60 int len = 0;
61
62 if (*p == '.')
63 {
64 /* Check for "." and ".." */
65 p++;
66 if (*p == '.') p++;
67 /* All other names beginning with '.' are invalid */
68 return (IS_END_OF_NAME(*p));
69 }
70 while (!IS_END_OF_NAME(*p))
71 {
72 if (strchr( invalid, *p )) return 0; /* Invalid char */
73 if (*p == '.') break; /* Start of the extension */
74 if (++len > 8) return 0; /* Name too long */
75 p++;
76 }
77 if (*p != '.') return 1; /* End of name */
78 p++;
79 if (IS_END_OF_NAME(*p)) return 0; /* Empty extension not allowed */
80 len = 0;
81 while (!IS_END_OF_NAME(*p))
82 {
83 if (strchr( invalid, *p )) return 0; /* Invalid char */
84 if (*p == '.') return 0; /* Second extension not allowed */
85 if (++len > 3) return 0; /* Extension too long */
86 p++;
87 }
88 return 1;
89}
90
91/***********************************************************************
92 * DOSFS_Hash
93 *
94 * Transform an OS/2 file name into a hashed DOS name. If the name is a valid
95 * DOS name, it is converted to upper-case; otherwise it is replaced by a
96 * hashed version that fits in 8.3 format.
97 * File name can be terminated by '\0', '\\' or '/'.
98 * 'buffer' must be at least 13 characters long.
99 */
100
101static void DOSFS_Hash( LPCSTR name, LPSTR buffer, BOOL dir_format,
102 BOOL ignore_case )
103{
104 static const char invalid_chars[] = INVALID_DOS_CHARS "~.";
105 static const char hash_chars[33] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";
106
107 const char *p, *ext;
108 char *dst;
109 unsigned short hash;
110 int i;
111
112 if (dir_format) strcpy( buffer, " " );
113
114 if (DOSFS_ValidDOSName( name, ignore_case ))
115 {
116 /* Check for '.' and '..' */
117 if (*name == '.')
118 {
119 buffer[0] = '.';
120 if (!dir_format) buffer[1] = buffer[2] = '\0';
121 if (name[1] == '.') buffer[1] = '.';
122 return;
123 }
124
125 /* Simply copy the name, converting to uppercase */
126
127 for (dst = buffer; !IS_END_OF_NAME(*name) && (*name != '.'); name++)
128 *dst++ = FILE_toupper(*name);
129 if (*name == '.')
130 {
131 if (dir_format) dst = buffer + 8;
132 else *dst++ = '.';
133 for (name++; !IS_END_OF_NAME(*name); name++)
134 *dst++ = FILE_toupper(*name);
135 }
136 if (!dir_format) *dst = '\0';
137 return;
138 }
139
140 /* Compute the hash code of the file name */
141 /* If you know something about hash functions, feel free to */
142 /* insert a better algorithm here... */
143 if (ignore_case)
144 {
145 for (p = name, hash = 0xbeef; !IS_END_OF_NAME(p[1]); p++)
146 hash = (hash<<3) ^ (hash>>5) ^ FILE_tolower(*p) ^ (FILE_tolower(p[1]) << 8);
147 hash = (hash<<3) ^ (hash>>5) ^ FILE_tolower(*p); /* Last character*/
148 }
149 else
150 {
151 for (p = name, hash = 0xbeef; !IS_END_OF_NAME(p[1]); p++)
152 hash = (hash << 3) ^ (hash >> 5) ^ *p ^ (p[1] << 8);
153 hash = (hash << 3) ^ (hash >> 5) ^ *p; /* Last character */
154 }
155
156 /* Find last dot for start of the extension */
157 for (p = name+1, ext = NULL; !IS_END_OF_NAME(*p); p++)
158 if (*p == '.') ext = p;
159 if (ext && IS_END_OF_NAME(ext[1]))
160 ext = NULL; /* Empty extension ignored */
161
162 /* Copy first 4 chars, replacing invalid chars with '_' */
163 for (i = 4, p = name, dst = buffer; i > 0; i--, p++)
164 {
165 if (IS_END_OF_NAME(*p) || (p == ext)) break;
166 *dst++ = strchr( invalid_chars, *p ) ? '_' : FILE_toupper(*p);
167 }
168 /* Pad to 5 chars with '~' */
169 while (i-- >= 0) *dst++ = '~';
170
171 /* Insert hash code converted to 3 ASCII chars */
172 *dst++ = hash_chars[(hash >> 10) & 0x1f];
173 *dst++ = hash_chars[(hash >> 5) & 0x1f];
174 *dst++ = hash_chars[hash & 0x1f];
175
176 /* Copy the first 3 chars of the extension (if any) */
177 if (ext)
178 {
179 if (!dir_format) *dst++ = '.';
180 for (i = 3, ext++; (i > 0) && !IS_END_OF_NAME(*ext); i--, ext++)
181 *dst++ = strchr( invalid_chars, *ext ) ? '_' : FILE_toupper(*ext);
182 }
183 if (!dir_format) *dst = '\0';
184}
185
186//******************************************************************************
187//******************************************************************************
188HFILE WIN32API CreateFileA(LPCSTR lpszName, DWORD fdwAccess, DWORD fdwShareMode,
189 LPSECURITY_ATTRIBUTES lpsa, DWORD fdwCreate,
190 DWORD fdwAttrsAndFlags, HANDLE hTemplateFile)
191{
192 dprintf(("CreateFileA %s", lpszName));
193 return(HMCreateFile(lpszName,
194 fdwAccess,
195 fdwShareMode,
196 lpsa,
197 fdwCreate,
198 fdwAttrsAndFlags,
199 hTemplateFile));
200}
201
202//******************************************************************************
203//******************************************************************************
204HFILE WIN32API CreateFileW(LPCWSTR lpszName, DWORD fdwAccess, DWORD fdwShareMode,
205 LPSECURITY_ATTRIBUTES lpsa, DWORD fdwCreate,
206 DWORD fdwAttrsAndFlags, HANDLE hTemplateFile)
207{
208 HANDLE rc;
209 char *astring;
210
211 astring = UnicodeToAsciiString((LPWSTR)lpszName);
212 rc = CreateFileA(astring, fdwAccess, fdwShareMode,
213 lpsa, fdwCreate, fdwAttrsAndFlags,
214 hTemplateFile);
215 FreeAsciiString(astring);
216 return(rc);
217}
218//******************************************************************************
219//******************************************************************************
220HANDLE WINAPI FindFirstFileA(LPCSTR lpFileName, WIN32_FIND_DATAA *lpFindFileData)
221{
222 return FindFirstFileExA(lpFileName, FindExInfoStandard, lpFindFileData,
223 FindExSearchNameMatch, NULL, 0);
224}
225/*****************************************************************************
226 * Name : HANDLE WIN32API FindFirstFileExA
227 * Purpose : The FindFirstFileExA function searches a directory for a file
228 * whose name and attributes match those specified in the
229 * function call.
230 * Parameters: LPCSTR lpFileName pointer to the name of the file
231 * to search for
232 * FINDEX_INFO_LEVELS fInfoLevelId information level of the returned data
233 * LPVOID lpFindFileData pointer to the returned information
234 * FINDEX_SEARCH_OPS fSearchOp type of filtering to perform
235 * LPVOID lpSearchFilter pointer to search criteria
236 * DWORD dwAdditionalFlags additional search control flags
237 * Variables :
238 * Result : If the function succeeds, the return value is a search handle
239 * that can be used in a subsequent call to the FindNextFile or
240 * FindClose functions.
241 * If the function fails, the return value is INVALID_HANDLE_VALUE
242 * Remark :
243 * Status :
244 *
245 * Author : SvL
246 *****************************************************************************/
247HANDLE WIN32API FindFirstFileExA(LPCSTR lpFileName, FINDEX_INFO_LEVELS fInfoLevelId,
248 LPVOID lpFindFileData,
249 FINDEX_SEARCH_OPS fSearchOp,
250 LPVOID lpSearchFilter,
251 DWORD dwAdditionalFlags)
252{
253 HANDLE hFind;
254 char *filename;
255 int namelen;
256
257 if(lpFileName == NULL || lpFindFileData == NULL || lpSearchFilter != NULL)
258 {
259 dprintf(("!ERROR!: invalid parameter(s)"));
260 SetLastError(ERROR_INVALID_PARAMETER);
261 return INVALID_HANDLE_VALUE;
262 }
263
264 if(fSearchOp == FindExSearchLimitToDevices) {
265 dprintf(("!ERROR!: FindExSearchLimitToDevices not implemented"));
266 SetLastError(ERROR_NOT_SUPPORTED);
267 return INVALID_HANDLE_VALUE;
268 }
269 else
270 if(fSearchOp == FindExSearchLimitToDirectories) {
271 //NOTE: According to the SDK docs we are allowed to silently ignore this option
272 dprintf(("!WARNING!: FindExSearchLimitToDirectories IGNORED"));
273 fSearchOp = FindExSearchNameMatch;
274 }
275 if(dwAdditionalFlags != 0) {
276 dprintf(("!ERROR!: options not implemented 0x%08x 0x%08lx\n", fSearchOp, dwAdditionalFlags ));
277 SetLastError(ERROR_NOT_SUPPORTED);
278 return INVALID_HANDLE_VALUE;
279 }
280
281 dprintf(("FindFirstFileExA %s %x %x %x %x %x", lpFileName, fInfoLevelId, lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags));
282
283 switch(fInfoLevelId)
284 {
285 case FindExInfoStandard:
286 namelen = strlen(lpFileName);
287 if(lpFileName[namelen-1] == '\\')
288 {
289 filename = (char *)alloca(namelen+1);
290 strcpy(filename, lpFileName);
291 filename[namelen-1] = 0;
292 }
293 else
294 filename = (char *)lpFileName;
295
296 return (HANDLE)OSLibDosFindFirst(filename, (WIN32_FIND_DATAA *)lpFindFileData);
297
298 default: //should never happen
299 dprintf(("!ERROR! unsupported fInfoLevelId"));
300 SetLastError(ERROR_INVALID_PARAMETER);
301 break;
302 }
303 return INVALID_HANDLE_VALUE;
304}
305//******************************************************************************
306//******************************************************************************
307HANDLE WINAPI FindFirstFileW(LPCWSTR lpFileName, WIN32_FIND_DATAW *lpFindFileData)
308{
309 return FindFirstFileExW(lpFileName, FindExInfoStandard, lpFindFileData,
310 FindExSearchNameMatch, NULL, 0);
311}
312/*****************************************************************************
313 * Name : HANDLE WIN32API FindFirstFileExW
314 * Purpose : The FindFirstFileExW function searches a directory for a file
315 * whose name and attributes match those specified in the
316 * function call.
317 * Parameters: LPCWSTR lpFileName pointer to the name of the file
318 * to search for
319 * FINDEX_INFO_LEVELS fInfoLevelId information level of the returned data
320 * LPVOID lpFindFileData pointer to the returned information
321 * FINDEX_SEARCH_OPS fSearchOp type of filtering to perform
322 * LPVOID lpSearchFilter pointer to search criteria
323 * DWORD dwAdditionalFlags additional search control flags
324 * Variables :
325 * Result : If the function succeeds, the return value is a search handle
326 * that can be used in a subsequent call to the FindNextFile or
327 * FindClose functions.
328 * If the function fails, the return value is INVALID_HANDLE_VALUE
329 * Remark :
330 * Status :
331 *
332 * Author : Wine
333 *****************************************************************************/
334HANDLE WIN32API FindFirstFileExW(LPCWSTR lpFileName,
335 FINDEX_INFO_LEVELS fInfoLevelId,
336 LPVOID lpFindFileData,
337 FINDEX_SEARCH_OPS fSearchOp,
338 LPVOID lpSearchFilter,
339 DWORD dwAdditionalFlags)
340{
341 HANDLE handle;
342 WIN32_FIND_DATAA dataA;
343 LPVOID _lpFindFileData;
344 LPSTR pathA;
345
346 switch(fInfoLevelId)
347 {
348 case FindExInfoStandard:
349 {
350 _lpFindFileData = &dataA;
351 }
352 break;
353 default:
354 dprintf(("!ERROR! unsupported fInfoLevelId"));
355 SetLastError(ERROR_INVALID_PARAMETER);
356 break;
357 }
358
359 pathA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFileName );
360 handle = FindFirstFileExA(pathA, fInfoLevelId, _lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags);
361 HeapFree( GetProcessHeap(), 0, pathA );
362 if (handle == INVALID_HANDLE_VALUE) return handle;
363
364 switch(fInfoLevelId)
365 {
366 case FindExInfoStandard:
367 {
368 WIN32_FIND_DATAW *dataW = (WIN32_FIND_DATAW*) lpFindFileData;
369 dataW->dwFileAttributes = dataA.dwFileAttributes;
370 dataW->ftCreationTime = dataA.ftCreationTime;
371 dataW->ftLastAccessTime = dataA.ftLastAccessTime;
372 dataW->ftLastWriteTime = dataA.ftLastWriteTime;
373 dataW->nFileSizeHigh = dataA.nFileSizeHigh;
374 dataW->nFileSizeLow = dataA.nFileSizeLow;
375 MultiByteToWideChar( CP_ACP, 0, dataA.cFileName, -1,
376 dataW->cFileName, sizeof(dataW->cFileName)/sizeof(WCHAR) );
377 MultiByteToWideChar( CP_ACP, 0, dataA.cAlternateFileName, -1,
378 dataW->cAlternateFileName,
379 sizeof(dataW->cAlternateFileName)/sizeof(WCHAR) );
380 }
381 break;
382 }
383 return handle;
384}
385//******************************************************************************
386// internal function for faster access (SHELL32)
387//******************************************************************************
388HANDLE WIN32API FindFirstFileMultiA(LPCSTR lpFileName,
389 WIN32_FIND_DATAA * lpFindFileData,
390 DWORD * count)
391{
392 return (HANDLE)OSLibDosFindFirstMulti(lpFileName,lpFindFileData,count);
393}
394//******************************************************************************
395//******************************************************************************
396BOOL WIN32API FindNextFileA(HANDLE hFindFile, WIN32_FIND_DATAA * lpFindFileData)
397{
398 return OSLibDosFindNext(hFindFile,lpFindFileData);
399}
400//******************************************************************************
401// internal function for faster access (SHELL32)
402//******************************************************************************
403BOOL WIN32API FindNextFileMultiA(HANDLE hFindFile, WIN32_FIND_DATAA * lpFindFileData,
404 DWORD *count)
405{
406 return OSLibDosFindNextMulti(hFindFile,lpFindFileData,count);
407}
408//******************************************************************************
409//******************************************************************************
410BOOL WIN32API FindNextFileW(HANDLE hFindFile, WIN32_FIND_DATAW * lpFindFileData)
411{
412 WIN32_FIND_DATAA wfda;
413 BOOL rc;
414
415 rc = OSLibDosFindNext(hFindFile,&wfda);
416
417 if(rc == 0) {
418 memset(lpFindFileData, 0, sizeof(WIN32_FIND_DATAW));
419 }
420 else {
421 // convert back the result structure
422 memcpy(lpFindFileData,
423 &wfda,
424 sizeof(WIN32_FIND_DATAA));
425
426 lstrcpynAtoW (lpFindFileData->cFileName,
427 wfda.cFileName,
428 sizeof(wfda.cFileName));
429
430 lstrcpynAtoW (lpFindFileData->cAlternateFileName,
431 wfda.cAlternateFileName,
432 sizeof(wfda.cAlternateFileName));
433 }
434 return rc;
435}
436//******************************************************************************
437//******************************************************************************
438BOOL WIN32API FindClose(HANDLE hFindFile)
439{
440 return OSLibDosFindClose(hFindFile);
441}
442//******************************************************************************
443//******************************************************************************
444DWORD WIN32API GetFileType(HANDLE hFile)
445{
446 return(HMGetFileType(hFile));
447}
448//******************************************************************************
449//******************************************************************************
450DWORD WIN32API GetFileInformationByHandle(HANDLE arg1, BY_HANDLE_FILE_INFORMATION * arg2)
451{
452 return(HMGetFileInformationByHandle(arg1,arg2));
453}
454//******************************************************************************
455//******************************************************************************
456BOOL WIN32API SetEndOfFile(HANDLE arg1)
457{
458 return HMSetEndOfFile(arg1);
459}
460//******************************************************************************
461//******************************************************************************
462BOOL WIN32API SetFileTime(HANDLE arg1, const FILETIME * arg2,
463 const FILETIME * arg3,
464 const FILETIME * arg4)
465{
466 return HMSetFileTime(arg1,
467 arg2,
468 arg3,
469 arg4);
470}
471//******************************************************************************
472//******************************************************************************
473INT WIN32API CompareFileTime(FILETIME * lpft1, FILETIME * lpft2)
474{
475 if (lpft1 == NULL || lpft2 == NULL) {
476 SetLastError(ERROR_INVALID_PARAMETER);
477 return -1;
478 }
479
480 if(lpft1->dwHighDateTime > lpft2->dwHighDateTime)
481 return 1;
482
483 if(lpft1->dwHighDateTime < lpft2->dwHighDateTime)
484 return -1;
485
486 if(lpft1->dwLowDateTime > lpft2->dwLowDateTime)
487 return 1;
488
489 if(lpft1->dwLowDateTime < lpft2->dwLowDateTime)
490 return -1;
491
492 return 0; //equal
493}
494//******************************************************************************
495//******************************************************************************
496BOOL WIN32API GetFileTime(HANDLE hFile, LPFILETIME arg2, LPFILETIME arg3, LPFILETIME arg4)
497{
498 return HMGetFileTime(hFile, arg2, arg3, arg4);
499}
500//******************************************************************************
501//******************************************************************************
502BOOL WIN32API CopyFileA(LPCSTR arg1, LPCSTR arg2, BOOL arg3)
503{
504 return OSLibDosCopyFile(arg1, arg2, arg3);
505}
506//******************************************************************************
507//******************************************************************************
508BOOL WIN32API CopyFileW(LPCWSTR arg1, LPCWSTR arg2, BOOL arg3)
509{
510 BOOL rc;
511 char *astring1, *astring2;
512
513 astring1 = UnicodeToAsciiString((LPWSTR)arg1);
514 astring2 = UnicodeToAsciiString((LPWSTR)arg2);
515 rc = CopyFileA(astring1, astring2, arg3);
516 FreeAsciiString(astring2);
517 FreeAsciiString(astring1);
518 return(rc);
519}
520/*****************************************************************************
521 * Name : BOOL WIN32API CopyFileExA
522 * Purpose : The CopyFileExA function copies an existing file to a new file.
523 * This function preserves extended attributes, OLE structured
524 * storage, NTFS alternate data streams, and file attributes.
525 * Security attributes for the existing file are not copied to
526 * the new file.
527 * Parameters: LPCSTR lpExistingFileName pointer to name of an existing file
528 * LPCSTR lpNewFileName pointer to filename to copy to
529 * LPPROGRESS_ROUTINE lpProgressRoutine pointer to the callback function
530 * LPVOID lpData to be passed to the callback function
531 * LPBOOL pbCancel flag that can be used to cancel the operation
532 * DWORD dwCopyFlags flags that specify how the file is copied
533 * Variables :
534 * Result : f the function succeeds, the return value is nonzero.
535 * If the function fails, the return value is zero.
536 * To get extended error information call GetLastError.
537 * Remark :
538 * Status : UNTESTED STUB
539 *
540 * Author : Markus Montkowski [Thu, 1998/05/19 11:46]
541 *****************************************************************************/
542
543BOOL WIN32API CopyFileExA( LPCSTR lpExistingFileName,
544 LPCSTR lpNewFileName,
545 LPPROGRESS_ROUTINE lpProgressRoutine,
546 LPVOID lpData,
547 LPBOOL pbCancel,
548 DWORD dwCopyFlags)
549{
550
551 dprintf(("KERNEL32: CopyFileExA(%08x,%08x,%08x,%08x,%08x,%08x) not properly implemented\n",
552 lpExistingFileName,
553 lpNewFileName,
554 lpProgressRoutine,
555 lpData,
556 pbCancel,
557 dwCopyFlags
558 ));
559
560 BOOL failIfExists = FALSE;
561
562 /*
563 * Interpret the only flag that CopyFile can interpret.
564 */
565 if((dwCopyFlags & COPY_FILE_FAIL_IF_EXISTS) != 0)
566 {
567 failIfExists = TRUE;
568 }
569
570 return CopyFileA(lpExistingFileName, lpNewFileName, failIfExists);
571}
572
573
574/*****************************************************************************
575 * Name : BOOL WIN32API CopyFileExW
576 * Purpose : The CopyFileExW function copies an existing file to a new file.
577 * This function preserves extended attributes, OLE structured
578 * storage, NTFS alternate data streams, and file attributes.
579 * Security attributes for the existing file are not copied to
580 * the new file.
581 * Parameters: LPCWSTR lpExistingFileName pointer to name of an existing file
582 * LPCWSTR lpNewFileName pointer to filename to copy to
583 * LPPROGRESS_ROUTINE lpProgressRoutine pointer to the callback function
584 * LPVOID lpData to be passed to the callback function
585 * LPBOOL pbCancel flag that can be used to cancel the operation
586 * DWORD dwCopyFlags flags that specify how the file is copied
587 * Variables :
588 * Result : f the function succeeds, the return value is nonzero.
589 * If the function fails, the return value is zero.
590 * To get extended error information call GetLastError.
591 * Remark :
592 * Status : UNTESTED STUB
593 *
594 * Author : Markus Montkowski [Thu, 1998/05/19 11:46]
595 *****************************************************************************/
596
597BOOL WIN32API CopyFileExW( LPCWSTR lpExistingFileName,
598 LPCWSTR lpNewFileName,
599 LPPROGRESS_ROUTINE lpProgressRoutine,
600 LPVOID lpData,
601 LPBOOL pbCancel,
602 DWORD dwCopyFlags)
603{
604 LPSTR sourceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpExistingFileName );
605 LPSTR destA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpNewFileName );
606
607 BOOL ret = CopyFileExA(sourceA,
608 destA,
609 lpProgressRoutine,
610 lpData,
611 pbCancel,
612 dwCopyFlags);
613
614 HeapFree( GetProcessHeap(), 0, sourceA );
615 HeapFree( GetProcessHeap(), 0, destA );
616
617 return ret;
618}
619//******************************************************************************
620//******************************************************************************
621DWORD WIN32API GetFileSize(HANDLE arg1, PDWORD arg2)
622{
623 return HMGetFileSize(arg1,
624 arg2);
625}
626//******************************************************************************
627//******************************************************************************
628BOOL WIN32API DeleteFileA(LPCSTR lpszFile)
629{
630 BOOL rc;
631
632#if 0
633 if((strstr(lpszFile, "odin32_") || strstr(lpszFile, "pe_")) && strstr(lpszFile, ".log")) {
634 return TRUE;
635 }
636#endif
637 rc = OSLibDosDelete((LPSTR)lpszFile);
638 if(!rc) {
639 dprintf(("DeleteFileA %s returned FALSE; last error %x", lpszFile, GetLastError()));
640 if(GetLastError() == ERROR_BAD_UNIT) {
641 return TRUE;
642 }
643 }
644 else dprintf(("DeleteFileA %s", lpszFile));
645
646 return rc;
647}
648//******************************************************************************
649//******************************************************************************
650BOOL WIN32API DeleteFileW(LPCWSTR arg1)
651{
652 BOOL rc;
653 char *astring;
654
655 astring = UnicodeToAsciiString((LPWSTR)arg1);
656 rc = DeleteFileA(astring);
657 FreeAsciiString(astring);
658 return(rc);
659}
660//******************************************************************************
661//******************************************************************************
662UINT WIN32API GetTempFileNameA(LPCSTR arg1, LPCSTR arg2, UINT arg3, LPSTR arg4)
663{
664 return O32_GetTempFileName(arg1, arg2, arg3, arg4);
665}
666//******************************************************************************
667//******************************************************************************
668UINT WIN32API GetTempFileNameW(LPCWSTR lpPathName, LPCWSTR lpPrefixString,
669 UINT uUnique, LPWSTR lpTempFileName)
670{
671 char *asciipath, *asciiprefix;
672 char *asciitemp = (char *)malloc(MAX_PATH+1);
673 UINT rc;
674
675 asciipath = UnicodeToAsciiString((LPWSTR)lpPathName);
676 asciiprefix = UnicodeToAsciiString((LPWSTR)lpPrefixString);
677 rc = O32_GetTempFileName(asciipath, asciiprefix, uUnique, asciitemp);
678 if(rc) AsciiToUnicode(asciitemp, lpTempFileName);
679 FreeAsciiString(asciiprefix);
680 FreeAsciiString(asciipath);
681 free(asciitemp);
682 return(rc);
683}
684//******************************************************************************
685//******************************************************************************
686BOOL WIN32API ReadFile(HANDLE hFile, PVOID pBuffer, DWORD dwLength,
687 PDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
688{
689 if(lpNumberOfBytesRead) *lpNumberOfBytesRead = 0;
690 if(dwLength == 0) {
691 dprintf(("!WARNING!: Nothing to do"));
692 //TODO: should we fail here instead?? (wine doesn't)
693 return TRUE;
694 }
695 return (HMReadFile(hFile,
696 pBuffer,
697 dwLength,
698 lpNumberOfBytesRead,
699 lpOverlapped, NULL));
700}
701//******************************************************************************
702//******************************************************************************
703BOOL WIN32API ReadFileEx(HANDLE hFile,
704 LPVOID lpBuffer,
705 DWORD nNumberOfBytesToRead,
706 LPOVERLAPPED lpOverlapped,
707 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
708{
709 if(nNumberOfBytesToRead == 0) {
710 dprintf(("!WARNING!: Nothing to do"));
711 //TODO: should we fail here instead?? (wine doesn't)
712 return TRUE;
713 }
714 if(!lpOverlapped || !lpCompletionRoutine) {
715 dprintf(("!WARNING!: !lpOverlapped || !lpCompletionRoutine"));
716 SetLastError(ERROR_INVALID_PARAMETER);
717 return FALSE;
718 }
719 //SDK docs say ReadFileEx will fail if this condition is true
720 if(GetFileType(hFile) == FILE_TYPE_PIPE && (lpOverlapped->Offset || lpOverlapped->OffsetHigh)) {
721 dprintf(("!WARNING!: lpOverlapped->Offset & lpOverlapped->OffsetHigh must be ZERO for named pipes"));
722 SetLastError(ERROR_INVALID_PARAMETER);
723 return FALSE;
724 }
725 return (HMReadFile(hFile,
726 lpBuffer,
727 nNumberOfBytesToRead, NULL,
728 lpOverlapped, lpCompletionRoutine));
729}
730//******************************************************************************
731//******************************************************************************
732BOOL WIN32API WriteFile(HANDLE hFile, LPCVOID buffer, DWORD nrbytes,
733 LPDWORD nrbyteswritten, LPOVERLAPPED lpOverlapped)
734{
735 if(nrbyteswritten) *nrbyteswritten = 0;
736 if(nrbytes == 0) {
737 dprintf(("!WARNING!: Nothing to do"));
738 //TODO: should we fail here instead?? (wine doesn't)
739 return TRUE;
740 }
741
742 return (HMWriteFile(hFile,
743 buffer,
744 nrbytes,
745 nrbyteswritten,
746 lpOverlapped, NULL));
747}
748/*****************************************************************************
749 * Name : BOOL WriteFileEx
750 * Purpose : The WriteFileEx function writes data to a file. It is designed
751 * solely for asynchronous operation, unlike WriteFile, which is
752 * designed for both synchronous and asynchronous operation.
753 * WriteFileEx reports its completion status asynchronously,
754 * calling a specified completion routine when writing is completed
755 * and the calling thread is in an alertable wait state.
756 * Parameters: HANDLE hFile handle of file to write
757 * LPVOID lpBuffer address of buffer
758 * DWORD nNumberOfBytesToRead number of bytes to write
759 * LPOVERLAPPED lpOverlapped address of offset
760 * LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine address of completion routine
761 * Variables :
762 * Result : TRUE / FALSE
763 * Remark :
764 * Status : UNTESTED STUB
765 *
766 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
767 *****************************************************************************/
768
769BOOL WIN32API WriteFileEx(HANDLE hFile,
770 LPCVOID lpBuffer,
771 DWORD nNumberOfBytesToWrite,
772 LPOVERLAPPED lpOverlapped,
773 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
774{
775 if(nNumberOfBytesToWrite == 0) {
776 dprintf(("!WARNING!: Nothing to do"));
777 //TODO: should we fail here instead?? (wine doesn't)
778 return TRUE;
779 }
780 if(!lpOverlapped || !lpCompletionRoutine) {
781 dprintf(("!WARNING!: !lpOverlapped || !lpCompletionRoutine"));
782 SetLastError(ERROR_INVALID_PARAMETER);
783 return FALSE;
784 }
785 //SDK docs say WriteFileEx will fail if this condition is true
786 if(GetFileType(hFile) == FILE_TYPE_PIPE && (lpOverlapped->Offset || lpOverlapped->OffsetHigh)) {
787 dprintf(("!WARNING!: lpOverlapped->Offset & lpOverlapped->OffsetHigh must be ZERO for named pipes"));
788 SetLastError(ERROR_INVALID_PARAMETER);
789 return FALSE;
790 }
791 return (HMWriteFile(hFile,
792 (LPVOID)lpBuffer,
793 nNumberOfBytesToWrite, NULL,
794 lpOverlapped, lpCompletionRoutine));
795}
796//******************************************************************************
797//******************************************************************************
798DWORD WIN32API SetFilePointer(HANDLE hFile, LONG lDistanceToMove,
799 PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod)
800{
801 return(HMSetFilePointer(hFile,
802 lDistanceToMove,
803 lpDistanceToMoveHigh,
804 dwMoveMethod));
805}
806//******************************************************************************
807//******************************************************************************
808DWORD WIN32API GetFileAttributesA(LPCSTR lpszFileName)
809{
810 DWORD rc, error;
811
812 if((NULL!=lpszFileName) && strlen(lpszFileName)==2 && lpszFileName[1] == ':')
813 {
814 char szDrive[4];
815 szDrive[0] = lpszFileName[0];
816 szDrive[1] = lpszFileName[1];
817 szDrive[2] = '\\';
818 szDrive[3] = 0x00;
819 rc = O32_GetFileAttributes((LPSTR)szDrive);
820 }
821 else {
822 rc = O32_GetFileAttributes((LPSTR)lpszFileName);
823 if(rc == -1 && lpszFileName[strlen(lpszFileName)-1] != '\\') {
824 char *filename = (char *)alloca(strlen(lpszFileName)+2); //+2!!!!!!
825 strcpy(filename, lpszFileName);
826 strcat(filename, "\\");
827 rc = O32_GetFileAttributes((LPSTR)filename);
828 }
829 }
830 //SvL: Open32 returns FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_NORMAL for
831 // directories whereas NT 4 (SP6) only returns FILE_ATTRIBUTE_DIRECTORY
832 if(rc != -1 && (rc & FILE_ATTRIBUTE_DIRECTORY)) {
833 rc = FILE_ATTRIBUTE_DIRECTORY;
834 }
835
836#if 0 // need more tests, maybe there is also a better way to hide simulated b:
837 if(rc == -1 && lpszFileName != NULL && !strnicmp(lpszFileName, "B:", 2))
838 {
839 error = GetLastError();
840 if(error = ERROR_DISK_CHANGE)
841 SetLastError(ERROR_NOT_READY);
842 else
843 SetLastError(error);
844 }
845#endif
846 dprintf(("KERNEL32: GetFileAttributes of %s returned %d\n", lpszFileName, rc));
847 return(rc);
848}
849//******************************************************************************
850//******************************************************************************
851DWORD WIN32API GetFileAttributesW(LPCWSTR arg1)
852{
853 DWORD rc;
854 char *astring;
855
856 astring = UnicodeToAsciiString((LPWSTR)arg1);
857 rc = GetFileAttributesA(astring);
858 FreeAsciiString(astring);
859 return(rc);
860}
861//******************************************************************************
862//******************************************************************************
863BOOL WIN32API SetFileAttributesA(LPCSTR lpFileName, DWORD dwFileAttributes)
864{
865 dprintf(("KERNEL32: SetFileAttributes of %s", lpFileName));
866 return O32_SetFileAttributes(lpFileName, dwFileAttributes);
867}
868//******************************************************************************
869//******************************************************************************
870BOOL WIN32API SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
871{
872 char *asciifile;
873 BOOL rc;
874
875 asciifile = UnicodeToAsciiString((LPWSTR)lpFileName);
876 rc = SetFileAttributesA(asciifile, dwFileAttributes);
877 FreeAsciiString(asciifile);
878 return(rc);
879}
880//******************************************************************************
881//******************************************************************************
882DWORD WIN32API GetFullPathNameA(LPCSTR arg1, DWORD arg2, LPSTR arg3,
883 LPSTR * arg4)
884{
885 char *ptr;
886 DWORD rc;
887 dprintf(("KERNEL32: GetFullPathName called with %s %d %x", arg1, arg2, arg3));
888 while((ptr = strchr(arg1, '/')) != NULL)
889 *ptr = '\\';
890
891 return O32_GetFullPathName(arg1, arg2, arg3, arg4);
892}
893//******************************************************************************
894//******************************************************************************
895DWORD WIN32API GetFullPathNameW(LPCWSTR lpFileName, DWORD nBufferLength,
896 LPWSTR lpBuffer, LPWSTR *lpFilePart)
897{
898 char *astring = NULL, *asciibuffer = NULL, *asciipart = NULL;
899 DWORD rc;
900
901 if(nBufferLength) {
902 asciibuffer = (char *)malloc(nBufferLength+1);
903 }
904 astring = UnicodeToAsciiString((LPWSTR)lpFileName);
905
906 rc = GetFullPathNameA(astring, nBufferLength,
907 asciibuffer, &asciipart);
908
909 dprintf(("KERNEL32: GetFullPathNameW %s returns %s\n",
910 astring,
911 asciibuffer));
912
913 if(rc && asciibuffer)
914 AsciiToUnicode(asciibuffer,
915 lpBuffer);
916
917 if(lpFilePart) {
918 if (asciipart == NULL)
919 *lpFilePart = NULL;
920 else
921 *lpFilePart = lpBuffer + ((int)asciipart - (int)asciibuffer);
922 }
923
924 FreeAsciiString(astring);
925 if(asciibuffer) free(asciibuffer);
926 return(rc);
927}
928//******************************************************************************
929//******************************************************************************
930BOOL WIN32API LockFile(HANDLE arg1, DWORD arg2,
931 DWORD arg3, DWORD arg4,
932 DWORD arg5)
933{
934 return HMLockFile(arg1,
935 arg2,
936 arg3,
937 arg4,
938 arg5);
939}
940
941
942/*****************************************************************************
943 * Name : BOOL LockFileEx
944 * Purpose : The LockFileEx function locks a byte range within an open file for shared or exclusive access.
945 * Parameters: HANDLE hFile handle of file to lock
946 * DWORD dwFlags functional behavior modification flags
947 * DWORD dwReserved reserved, must be set to zero
948 * DWORD nNumberOfBytesToLockLow low-order 32 bits of length to lock
949 * DWORD nNumberOfBytesToLockHigh high-order 32 bits of length to lock
950 * LPOVERLAPPED LPOVERLAPPED addr. of structure with lock region start offset
951 * Variables :
952 * Result : TRUE / FALSE
953 * Remark :
954 * Status : UNTESTED STUB
955 *
956 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
957 *****************************************************************************/
958
959BOOL LockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved,
960 DWORD nNumberOfBytesToLockLow,
961 DWORD nNumberOfBytesToLockHigh,
962 LPOVERLAPPED lpOverlapped)
963{
964 return(HMLockFile(hFile,
965 lpOverlapped->Offset,
966 lpOverlapped->OffsetHigh,
967 nNumberOfBytesToLockLow,
968 nNumberOfBytesToLockHigh));
969}
970//******************************************************************************
971//******************************************************************************
972BOOL WIN32API MoveFileA(LPCSTR arg1, LPCSTR arg2)
973{
974 dprintf(("KERNEL32: MoveFileA %s %s", arg1, arg2));
975 return OSLibDosMoveFile(arg1, arg2);
976}
977//******************************************************************************
978//******************************************************************************
979
980
981/*****************************************************************************
982 * Name : MoveFileExA
983 * Purpose : Move or delete a file
984 * Parameters: LPCSTR lpExistingFileName
985 * LPCSTR lpNewFileName
986 * DWORD dwFlags
987 * Variables :
988 * Result :
989 * Remark : "delete on system-reboot" feature is not supported!
990 * Status :
991 *
992 * Author : Patrick Haller [2001-08-30]
993 *****************************************************************************/
994
995BOOL WIN32API MoveFileExA(LPCSTR lpszOldFilename,
996 LPCSTR lpszNewFilename,
997 DWORD fdwFlags)
998{
999 dprintf(("KERNEL32: MoveFileExA %s to %s %x, not complete!\n",
1000 lpszOldFilename,
1001 lpszNewFilename,
1002 fdwFlags));
1003
1004 // this parameter combination is illegal
1005 if ( (fdwFlags & MOVEFILE_DELAY_UNTIL_REBOOT) &&
1006 (fdwFlags & MOVEFILE_COPY_ALLOWED) )
1007 {
1008 // Note: error code not verified
1009 SetLastError(ERROR_INVALID_PARAMETER);
1010 return FALSE;
1011 }
1012
1013 // first, we take care about the special cases
1014 if (fdwFlags && MOVEFILE_DELAY_UNTIL_REBOOT)
1015 {
1016 // We cannot really support this in any other way than
1017 // to call the IBMCSFLK driver. As the first place I've encountered
1018 // this call is Microsoft ACMSETUP wanting to replace OLEPRO32.DLL
1019 // in the ODIN system directory, we are better skipping the call.
1020
1021 // Anyway, this is only supported under Windows NT
1022 fdwFlags &= ~MOVEFILE_DELAY_UNTIL_REBOOT;
1023
1024 // Until we support this, we have to intercept
1025 // lpszNewFilename == NULL
1026 if (NULL == lpszNewFilename)
1027 {
1028 // try to delete the filename
1029 dprintf(("KERNEL32-MoveFileExA: trying to delete file [%s], skipped.",
1030 lpszOldFilename));
1031
1032 SetLastError( NO_ERROR );
1033 return TRUE;
1034 }
1035 }
1036
1037 if (fdwFlags && MOVEFILE_COPY_ALLOWED)
1038 {
1039 // if lpszOldFilename and lpszNewFilename refer to different
1040 // volumes, this flag controls if a copy operation is allowed.
1041 }
1042
1043 if (fdwFlags && MOVEFILE_REPLACE_EXISTING)
1044 {
1045 // We can only attempt to
1046 // 1 move away the current file if existing,
1047 // 2 do the current move operation
1048 // 3 if succesful, delete the backup
1049 // otherwise restore the original file
1050 }
1051
1052 return OSLibDosMoveFile(lpszOldFilename,
1053 lpszNewFilename);
1054}
1055//******************************************************************************
1056//******************************************************************************
1057BOOL WIN32API MoveFileW(LPCWSTR lpSrc, LPCWSTR lpDest)
1058{
1059 char *asciisrc, *asciidest;
1060 BOOL rc;
1061
1062 asciisrc = UnicodeToAsciiString((LPWSTR)lpSrc);
1063 asciidest = UnicodeToAsciiString((LPWSTR)lpDest);
1064 rc = MoveFileA(asciisrc, asciidest);
1065 FreeAsciiString(asciisrc);
1066 FreeAsciiString(asciidest);
1067 return(rc);
1068}
1069//******************************************************************************
1070//******************************************************************************
1071BOOL WIN32API MoveFileExW(LPCWSTR lpSrc, LPCWSTR lpDest, DWORD fdwFlags)
1072{
1073 dprintf(("KERNEL32: MoveFileExW %ls to %ls %x",
1074 lpSrc,
1075 lpDest,
1076 fdwFlags));
1077
1078 char *asciisrc,
1079 *asciidest;
1080 BOOL rc;
1081
1082 asciisrc = UnicodeToAsciiString((LPWSTR)lpSrc);
1083 if (NULL != lpDest)
1084 asciidest = UnicodeToAsciiString((LPWSTR)lpDest);
1085 else
1086 asciidest = NULL;
1087
1088 rc = MoveFileExA(asciisrc,
1089 asciidest,
1090 fdwFlags);
1091
1092 if (NULL != asciidest)
1093 FreeAsciiString(asciidest);
1094
1095 FreeAsciiString(asciisrc);
1096
1097 return(rc);
1098}
1099//******************************************************************************
1100/*****************************************************************************
1101ODINFUNCTION3(*, :,
1102 HFILE, WIN32API,
1103 OpenFile *, Purpose,
1104 :, forwardOpenFile to Open32
1105 * Parameters:
1106 * Variables :
1107 * Result : API returncode
1108 * Remark : modified for handle translation support
1109 * Status : @@@PH verify if 0 is a valid "invalid handle" :)
1110 *
1111 * Author : Patrick Haller [Fri, 1998/06/12 02:53]
1112 *****************************************************************************/
1113
1114HFILE WIN32API OpenFile(LPCSTR lpszFile, OFSTRUCT *lpOpenBuff,
1115 UINT fuMode)
1116{
1117 HFILE hFile;
1118
1119 dprintf(("KERNEL32: OpenFile(%s, %08xh, %08xh)\n",
1120 lpszFile,
1121 lpOpenBuff,
1122 fuMode));
1123
1124 hFile = HMOpenFile(lpszFile, /* call open32 */
1125 lpOpenBuff,
1126 fuMode);
1127
1128 return (hFile);
1129}
1130//******************************************************************************
1131//******************************************************************************
1132BOOL WIN32API UnlockFile(HANDLE arg1, DWORD arg2, DWORD arg3,
1133 DWORD arg4, DWORD arg5)
1134{
1135 return HMUnlockFile(arg1,
1136 arg2,
1137 arg3,
1138 arg4,
1139 arg5);
1140}
1141
1142
1143/*****************************************************************************
1144 * Name : BOOL UnlockFileEx
1145 * Purpose : The UnlockFileEx function unlocks a previously locked byte range in an open file.
1146 * Parameters: HANDLE hFile handle of file to lock
1147 * DWORD dwReserved reserved, must be set to zero
1148 * DWORD nNumberOfBytesToLockLow low-order 32 bits of length to lock
1149 * DWORD nNumberOfBytesToLockHigh high-order 32 bits of length to lock
1150 * LPOVERLAPPED LPOVERLAPPED addr. of structure with lock region start offset
1151 * Variables :
1152 * Result : TRUE / FALSE
1153 * Remark :
1154 * Status : UNTESTED STUB
1155 *
1156 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
1157 *****************************************************************************/
1158
1159BOOL WIN32API UnlockFileEx(HANDLE hFile, DWORD dwReserved,
1160 DWORD nNumberOfBytesToLockLow,
1161 DWORD nNumberOfBytesToLockHigh,
1162 LPOVERLAPPED lpOverlapped)
1163{
1164 return(HMUnlockFileEx(hFile, dwReserved,
1165 nNumberOfBytesToLockLow,
1166 nNumberOfBytesToLockHigh,
1167 lpOverlapped));
1168}
1169//******************************************************************************
1170//Behaviour in NT 4, SP6:
1171//- converts long filename to 8.3 short filname (TODO: not yet done here!)
1172//- fails on volume that doesn't support 8.3 filenames
1173//- if lpszShortPath 0 or cchBuffer too small -> return required length
1174// (INCLUDING 0 terminator)
1175//- if lpszLongPath == NULL -> ERROR_INVALID_PARAMETER (return 0)
1176//- if lpszLongPath empty -> proceed as if nothing is wrong
1177//- does NOT clear the last error if successful!
1178//- if successful -> return length of string (excluding 0 terminator)
1179//******************************************************************************
1180DWORD WIN32API GetShortPathNameA(LPCTSTR lpszLongPath,
1181 LPTSTR lpszShortPath,
1182 DWORD cchBuffer)
1183{
1184 char short_name[MAX_PATHNAME_LEN]; /* Long pathname in Unix format */
1185 int length, marker = 0;
1186 LPSTR tmpshortpath,tmplongpath;
1187 DWORD attr, sp = 0, lp = 0;
1188 int tmplen, drive;
1189
1190 dprintf(("KERNEL32: GetShortPathNameA %s", lpszLongPath));
1191
1192 if(!lpszLongPath) {
1193 SetLastError(ERROR_INVALID_PARAMETER);
1194 return 0;
1195 }
1196 if (!lpszLongPath[0]) {
1197 SetLastError(ERROR_BAD_PATHNAME);
1198 return 0;
1199 }
1200
1201 if ( ( tmpshortpath = (char*) HeapAlloc ( GetProcessHeap(), 0, MAX_PATHNAME_LEN ) ) == NULL ) {
1202 SetLastError ( ERROR_NOT_ENOUGH_MEMORY );
1203 return 0;
1204 }
1205
1206 if ( ( tmplongpath = (char*) HeapAlloc ( GetProcessHeap(), 0, MAX_PATHNAME_LEN ) ) == NULL ) {
1207 SetLastError ( ERROR_NOT_ENOUGH_MEMORY );
1208 return 0;
1209 }
1210
1211 lstrcpyA(tmplongpath,lpszLongPath);
1212
1213 /* check for drive letter */
1214 if ( lpszLongPath[1] == ':' ) {
1215 tmpshortpath[0] = lpszLongPath[0];
1216 tmpshortpath[1] = ':';
1217 sp = 2;
1218 lp = 2;
1219 }
1220
1221 //todo: check drive validity!
1222
1223 while ( lpszLongPath[lp] ) {
1224 marker = 0;
1225 /* check for path delimiters and reproduce them */
1226 if ( lpszLongPath[lp] == '\\' || lpszLongPath[lp] == '/' ) {
1227 if (!sp || tmpshortpath[sp-1]!= '\\')
1228 {
1229 /* strip double "\\" */
1230 tmpshortpath[sp] = '\\';
1231 sp++;
1232 }
1233 tmpshortpath[sp]=0;/*terminate string*/
1234 lp++;
1235 continue;
1236 }
1237
1238 tmplen = strcspn ( lpszLongPath + lp, "\\/" );
1239 lstrcpynA ( tmpshortpath+sp, lpszLongPath + lp, tmplen+1 );
1240
1241 /* Check, if the current element is a valid dos name */
1242 if ( DOSFS_ValidDOSName ( lpszLongPath + lp, TRUE ) ) {
1243 sp += tmplen;
1244 lp += tmplen;
1245 continue;
1246 }
1247
1248 if (tmplongpath[lp + tmplen] == '\\')
1249 {
1250 tmplongpath[lp + tmplen] = 0;
1251 marker = 1;
1252 }
1253
1254 attr = GetFileAttributesA(tmplongpath);
1255
1256 if (attr == -1)
1257 {
1258 SetLastError ( ERROR_FILE_NOT_FOUND );
1259 HeapFree ( GetProcessHeap(), 0, tmpshortpath );
1260 HeapFree ( GetProcessHeap(), 0, tmplongpath );
1261 return 0;
1262 }
1263
1264 DOSFS_Hash(tmpshortpath+sp, short_name, FALSE, TRUE );
1265
1266 strcpy( tmpshortpath+sp, short_name);
1267 sp += strlen ( tmpshortpath+sp );
1268 if (marker)
1269 tmplongpath[lp + tmplen] = '\\';
1270 lp += tmplen;
1271
1272 }
1273
1274 tmpshortpath[sp] = 0;
1275
1276 lstrcpynA ( lpszShortPath, tmpshortpath, cchBuffer );
1277 dprintf(("returning %s\n", lpszShortPath));
1278 tmplen = strlen ( lpszShortPath );
1279
1280 HeapFree ( GetProcessHeap(), 0, tmpshortpath );
1281 HeapFree ( GetProcessHeap(), 0, tmplongpath );
1282
1283 return tmplen;
1284}
1285//******************************************************************************
1286//******************************************************************************
1287DWORD WIN32API GetShortPathNameW(LPCWSTR lpszLongPath, LPWSTR lpszShortPath,
1288 DWORD cchBuffer)
1289{
1290 LPSTR longpathA, shortpathA;
1291 DWORD ret = 0;
1292
1293 longpathA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszLongPath );
1294 shortpathA = (LPSTR) HeapAlloc ( GetProcessHeap(), 0, cchBuffer );
1295
1296 ret = GetShortPathNameA ( longpathA, shortpathA, cchBuffer );
1297 if (cchBuffer > 0 && !MultiByteToWideChar( CP_ACP, 0, shortpathA, -1, lpszShortPath, cchBuffer ))
1298 lpszShortPath[cchBuffer-1] = 0;
1299 HeapFree( GetProcessHeap(), 0, longpathA );
1300 HeapFree( GetProcessHeap(), 0, shortpathA );
1301
1302 return ret;
1303}
1304//******************************************************************************
1305//Behaviour in NT 4, SP6: (presumably the same as GetShortPathNameA; TODO check)
1306//- converts short filename to long filenames (TODO: not yet done here!)
1307//- if lpszShortPath 0 or cchBuffer too small -> return required length
1308// (INCLUDING 0 terminator)
1309//- if lpszLongPath == NULL -> ERROR_INVALID_PARAMETER (return 0)
1310//- if lpszLongPath empty -> proceed as if nothing is wrong
1311//- does NOT clear the last error if successful!
1312//- if successful -> return length of string (excluding 0 terminator)
1313//******************************************************************************
1314DWORD WINAPI GetLongPathNameA( LPCSTR lpszShortPath, LPSTR lpszLongPath,
1315 DWORD cchBuffer )
1316{
1317 int tmplen;
1318 char short_name[MAX_PATHNAME_LEN]; /* Long pathname in Unix format */
1319 WIN32_FIND_DATAA FindFileData;
1320 HANDLE hFind;
1321 DWORD sp = 0, lp = 0,attr;
1322 LPSTR tmpshortpath,tmplongpath;
1323
1324 dprintf(("GetLongPathNameA %s %x %d", lpszShortPath, lpszLongPath, cchBuffer));
1325
1326 if(!lpszShortPath) {
1327 SetLastError(ERROR_INVALID_PARAMETER);
1328 return 0;
1329 }
1330
1331 if ( ( tmpshortpath = (char*) HeapAlloc ( GetProcessHeap(), 0, MAX_PATHNAME_LEN ) ) == NULL ) {
1332 SetLastError ( ERROR_NOT_ENOUGH_MEMORY );
1333 return 0;
1334 }
1335
1336 if ( ( tmplongpath = (char*) HeapAlloc ( GetProcessHeap(), 0, MAX_PATHNAME_LEN ) ) == NULL ) {
1337 SetLastError ( ERROR_NOT_ENOUGH_MEMORY );
1338 return 0;
1339 }
1340
1341 lstrcpyA(tmpshortpath,lpszShortPath);
1342
1343 /* check for drive letter */
1344 if ( lpszShortPath[1] == ':' ) {
1345 tmplongpath[0] = lpszShortPath[0];
1346 tmplongpath[1] = ':';
1347 sp = 2;
1348 lp = 2;
1349 }
1350
1351 //todo: check drive validity!
1352
1353 while ( lpszShortPath[lp] ) {
1354
1355 /* check for path delimiters and reproduce them */
1356 if ( lpszShortPath[lp] == '\\' || lpszShortPath[lp] == '/' ) {
1357 if (!sp || tmplongpath[sp-1]!= '\\')
1358 {
1359 /* strip double "\\" */
1360 tmplongpath[sp] = '\\';
1361 sp++;
1362 }
1363 tmplongpath[sp]=0;/*terminate string*/
1364 lp++;
1365 continue;
1366 }
1367
1368 tmplen = strcspn ( lpszShortPath + lp, "\\/" );
1369 lstrcpynA ( tmplongpath+sp, lpszShortPath + lp, tmplen+1 );
1370
1371 attr = GetFileAttributesA(tmplongpath);
1372 if (attr != -1)
1373 {
1374 sp += tmplen;
1375 lp += tmplen;
1376 continue;
1377 }
1378 else
1379 // it may be hashed name or name with weird characters!
1380 if ((tmplongpath+sp)[4] == '~')
1381 {
1382 //hashed entry Wine does linear dir search.. incredible.. we will be
1383 //better ;)
1384 if (strchr(tmplongpath+sp,'_'))
1385 {
1386 (tmplongpath+sp)[0] = '*';
1387 (tmplongpath+sp)[1] = 0;
1388 }
1389 else
1390 {
1391 (tmplongpath+sp)[4] = '*';
1392 (tmplongpath+sp)[5] = 0;
1393 }
1394 hFind = FindFirstFileExA(tmplongpath, FindExInfoStandard, &FindFileData,
1395 FindExSearchNameMatch, NULL, 0 );
1396
1397 if (hFind == INVALID_HANDLE_VALUE)
1398 {
1399 //no possible variants!
1400 SetLastError ( ERROR_FILE_NOT_FOUND );
1401 HeapFree ( GetProcessHeap(), 0, tmpshortpath );
1402 HeapFree ( GetProcessHeap(), 0, tmplongpath );
1403 return 0;
1404 }
1405 else
1406 do
1407 {
1408 DOSFS_Hash(FindFileData.cFileName, short_name, FALSE, TRUE );
1409 //this happens on files like [hello world]
1410 if (!lstrncmpA(short_name, lpszShortPath+lp, (lpszShortPath+lp+tmplen)[-1] == '.' ? tmplen-1 : tmplen ))
1411 {
1412 strcpy( tmplongpath+sp, FindFileData.cFileName);
1413 sp += strlen ( tmplongpath+sp );
1414 lp += tmplen;
1415 break;
1416 }
1417 }
1418 while (FindNextFileA(hFind, &FindFileData));
1419
1420 // no FindClose() here or else GetLastError() will not give its error
1421 if (GetLastError() == ERROR_NO_MORE_FILES)
1422 {
1423 FindClose(hFind);
1424 SetLastError ( ERROR_FILE_NOT_FOUND );
1425 HeapFree ( GetProcessHeap(), 0, tmpshortpath );
1426 HeapFree ( GetProcessHeap(), 0, tmplongpath );
1427 return 0;
1428 }
1429 FindClose(hFind);
1430 }
1431 else
1432 {
1433 // if this file can't be found in common or hashed files
1434 // it does not exist
1435 SetLastError ( ERROR_FILE_NOT_FOUND );
1436 HeapFree ( GetProcessHeap(), 0, tmpshortpath );
1437 HeapFree ( GetProcessHeap(), 0, tmplongpath );
1438 return 0;
1439 }
1440 }
1441 tmplongpath[sp] = 0;
1442
1443 lstrcpynA ( lpszLongPath, tmplongpath, cchBuffer );
1444 dprintf(("returning %s\n", lpszLongPath));
1445 tmplen = strlen ( lpszLongPath );
1446
1447 HeapFree ( GetProcessHeap(), 0, tmpshortpath );
1448 HeapFree ( GetProcessHeap(), 0, tmplongpath );
1449
1450 return tmplen;
1451}
1452//******************************************************************************
1453//******************************************************************************
1454DWORD WINAPI GetLongPathNameW( LPCWSTR lpszShortPath, LPWSTR lpszLongPath,
1455 DWORD cchBuffer )
1456{
1457 int length;
1458
1459 dprintf(("GetLongPathNameW %x %ls %d", lpszShortPath, lpszLongPath, cchBuffer));
1460 dprintf(("WARNING: WIN98 ONLY!!"));
1461
1462 if(!lpszShortPath) {
1463 SetLastError(ERROR_INVALID_PARAMETER);
1464 return 0;
1465 }
1466
1467 length = lstrlenW(lpszShortPath) + 1;
1468 if(length > cchBuffer) {
1469 if(lpszLongPath) {
1470 *lpszLongPath = 0;
1471 }
1472 return(length); //return length required (including 0 terminator)
1473 }
1474 lstrcpyW(lpszLongPath, lpszShortPath);
1475 return(length-1);
1476}
1477//******************************************************************************
1478//******************************************************************************
1479void WIN32API SetFileApisToANSI()
1480{
1481 dprintf(("!WARNING! SetFileApisToANSI() stub\n"));
1482}
1483
1484/*****************************************************************************
1485 * Name : DWORD GetCompressedFileSizeA
1486 * Purpose : The GetCompressedFileSizeA function obtains the compressed
1487 * size, in bytes, of a specified file.
1488 * Parameters: LPCTSTR lpFileName, // pointer to name of file
1489 * LPDWORD lpFileSizeHigh // pointer to DWORD to receive
1490 * high-order doubleword of file size
1491 * Variables :
1492 * Result : size of compressed file
1493 * Remark :
1494 * Status : UNTESTED
1495 *
1496 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
1497 *****************************************************************************/
1498
1499DWORD WIN32API GetCompressedFileSizeA(LPCTSTR lpFileName, LPDWORD lpFileSizeHigh)
1500{
1501 dprintf(("KERNEL32: GetCompressedFileSizeA (%s, %08xh) not implemented.\n",
1502 lpFileName,
1503 lpFileSizeHigh));
1504
1505 /* @@@PH: simply return the standard filesize */
1506 return 0;
1507}
1508
1509
1510/*****************************************************************************
1511 * Name : DWORD GetCompressedFileSizeW
1512 * Purpose : The GetCompressedFileSizeE function obtains the compressed
1513 * size, in bytes, of a specified file.
1514 * Parameters: LPCWSTR lpFileName, // pointer to name of file
1515 * LPDWORD lpFileSizeHigh // pointer to DWORD to receive
1516 * high-order doubleword of file size
1517 * Variables :
1518 * Result : size of compressed file
1519 * Remark :
1520 * Status : UNTESTED
1521 *
1522 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
1523 *****************************************************************************/
1524
1525DWORD WIN32API GetCompressedFileSizeW(LPCWSTR lpFileName, LPDWORD lpFileSizeHigh)
1526{
1527 LPCTSTR lpAsciiFileName; /* converted filename */
1528 DWORD rc; /* function result */
1529
1530 dprintf(("KERNEL32: GetCompressedFileSizeW (%s, %08xh)\n",
1531 lpFileName,
1532 lpFileSizeHigh));
1533
1534 lpAsciiFileName = UnicodeToAsciiString( (LPWSTR) lpFileName);
1535
1536 rc = GetCompressedFileSizeA(lpAsciiFileName,
1537 lpFileSizeHigh);
1538
1539 FreeAsciiString( (char *) lpAsciiFileName);
1540
1541 return (rc); /* return result */
1542}
1543
1544
1545/*****************************************************************************
1546 * Name : BOOL GetFileAttributesExA
1547 * Purpose :
1548 * Parameters:
1549 * Variables :
1550 * Result :
1551 * Remark : KERNEL32.874
1552 * Status : UNTESTED
1553 *
1554 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
1555 *****************************************************************************/
1556
1557BOOL WIN32API GetFileAttributesExA(LPCSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
1558 LPVOID lpFileInformation)
1559{
1560 BOOL rc;
1561
1562 dprintf(("KERNEL32: GetFileAttributesExA(%s,%08xh,%08xh) mostly implemented.\n",
1563 lpFileName,
1564 fInfoLevelId,
1565 lpFileInformation));
1566
1567 if (lpFileName == NULL) return FALSE;
1568 if (lpFileInformation == NULL) return FALSE;
1569
1570 if (fInfoLevelId == GetFileExInfoStandard)
1571 {
1572 LPWIN32_FILE_ATTRIBUTE_DATA lpFad = (LPWIN32_FILE_ATTRIBUTE_DATA) lpFileInformation;
1573
1574 rc = OSLibDosGetFileAttributesEx((LPSTR)lpFileName,
1575 fInfoLevelId,
1576 lpFileInformation);
1577 return (rc);
1578 }
1579 else
1580 {
1581 dprintf(("KERNEL32: GetFileAttributesExA - invalid info level %d!\n",
1582 fInfoLevelId));
1583 return FALSE;
1584 }
1585}
1586
1587
1588/*****************************************************************************
1589 * Name : BOOL GetFileAttributesExW
1590 * Purpose :
1591 * Parameters:
1592 * Variables :
1593 * Result :
1594 * Remark : KERNEL32.875
1595 * Status : UNTESTED
1596 *
1597 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
1598 *****************************************************************************/
1599
1600BOOL WIN32API GetFileAttributesExW(LPCWSTR lpFileName,
1601 GET_FILEEX_INFO_LEVELS fInfoLevelId,
1602 LPVOID lpFileInformation)
1603{
1604 LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFileName );
1605 BOOL res = GetFileAttributesExA( nameA, fInfoLevelId, lpFileInformation);
1606 HeapFree( GetProcessHeap(), 0, nameA );
1607 return res;
1608}
1609
1610//******************************************************************************
1611//******************************************************************************
1612HANDLE WIN32API FindFirstChangeNotificationA(LPCSTR lpPathName,
1613 BOOL bWatchSubtree,
1614 DWORD dwNotifyFilter)
1615{
1616 dprintf(("KERNEL32: FindFirstChangeNotificationA %s, Not implemented (faked)", lpPathName));
1617 return -1;
1618}
1619//******************************************************************************
1620//******************************************************************************
1621BOOL WIN32API FindNextChangeNotification(HANDLE hChange)
1622{
1623 dprintf(("KERNEL32: FindNextChangeNotification (%08xh), Not implemented\n",
1624 hChange));
1625
1626 return FALSE;
1627}
1628//******************************************************************************
1629//******************************************************************************
1630BOOL WIN32API FindCloseChangeNotification(HANDLE hChange)
1631{
1632 dprintf(("KERNEL32: OS2FindNextChangeNotification, Not implemented\n"));
1633
1634 return(TRUE);
1635}
1636/*****************************************************************************
1637 * Name : HANDLE WIN32API FindFirstChangeNotificationW
1638 * Purpose : The FindFirstChangeNotification function creates a change
1639 * notification handle and sets up initial change notification
1640 * filter conditions. A wait on a notification handle succeeds when
1641 * a change matching the filter conditions occurs in the specified
1642 * directory or subtree.
1643 * Parameters: LPCWSTR lpPathName pointer to name of directory to watch
1644 * BOOL bWatchSubtree flag for monitoring directory or
1645 * directory tree
1646 * DWORD dwNotifyFilter filter conditions to watch for
1647 * Variables :
1648 * Result : If the function succeeds, the return value is a handle to a find
1649 * change notification object.
1650 * If the function fails, the return value is INVALID_HANDLE_VALUE
1651 * Remark :
1652 * Status : UNTESTED STUB
1653 *
1654 * Author : Markus Montkowski [Tha, 1998/05/21 20:57]
1655 *****************************************************************************/
1656HANDLE WIN32API FindFirstChangeNotificationW(LPCWSTR lpPathName,
1657 BOOL bWatchSubtree,
1658 DWORD dwNotifyFilter)
1659{
1660 LPSTR lpAsciiPath;
1661 HANDLE hChange;
1662
1663 lpAsciiPath = UnicodeToAsciiString( (LPWSTR) lpPathName);
1664 hChange = FindFirstChangeNotificationA(lpAsciiPath, bWatchSubtree,
1665 dwNotifyFilter );
1666 if (lpAsciiPath) FreeAsciiString(lpAsciiPath);
1667 return hChange;
1668}
1669//******************************************************************************
1670//******************************************************************************
1671BOOL WIN32API DeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode,
1672 LPVOID lpInBuffer, DWORD nInBufferSize,
1673 LPVOID lpOutBuffer, DWORD nOutBufferSize,
1674 LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
1675{
1676 return HMDeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize,
1677 lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped);
1678}
1679/*****************************************************************************
1680 * Name : BOOL WIN32API CancelIo
1681 * Purpose : The CancelIO function cancels all pending input and output
1682 * (I/O) operations that were issued by the calling thread for
1683 * the specified file handle. The function does not cancel
1684 * I/O operations issued for the file handle by other threads.
1685 * Parameters: HANDLE hFile file handle for which to cancel I/O
1686 * Variables :
1687 * Result : If the function succeeds, the return value is nonzero All pending
1688 * I/O operations issued by the calling thread for the file handle
1689 * were successfully canceled.
1690 * If the function fails, the return value is zero.
1691 * To get extended error information, call GetLastError.
1692 * Remark : If there are any I/O operations in progress for the specified
1693 * file HANDLE and they were issued by the calling thread, the
1694 * CancelIO function cancels them.
1695 * Note that the I/O operations must have been issued as
1696 * overlapped I/O. If they were not, the I/O operations would not
1697 * have returned to allow the thread to call the CancelIO function.
1698 * Calling the CancelIO function with a file handle that was not
1699 * opened with FILE_FLAG_OVERLAPPED does nothing.
1700 * All I/O operations that are canceled will complete with the
1701 * error ERROR_OPERATION_ABORTED. All completion notifications
1702 * for the I/O operations will occur normally.
1703 * Status :
1704 *
1705 * Author : Markus Montkowski [Thu, 1998/05/19 11:46]
1706 *****************************************************************************/
1707BOOL WIN32API CancelIo(HANDLE hFile)
1708{
1709 return HMCancelIo(hFile);
1710}
1711/*****************************************************************************
1712 * Name : BOOL GetOverlappedResult
1713 * Purpose : forward call to Open32
1714 * Parameters:
1715 * Variables :
1716 * Result :
1717 * Remark : handle translation is done in GetOverlappedResult
1718 * Status :
1719 *
1720 * Author : Patrick Haller [Fri, 1999/06/18 03:44]
1721 *****************************************************************************/
1722
1723BOOL WIN32API GetOverlappedResult(HANDLE hFile, /* [in] handle of file to check on */
1724 LPOVERLAPPED lpOverlapped, /* [in/out] pointer to overlapped */
1725 LPDWORD lpTransferred, /* [in/out] number of bytes transferred */
1726 BOOL bWait) /* [in] wait for the transfer to complete ? */
1727{
1728 //NOTE: According to the SDK docs lpOverlapped->hEvent can be 0. This function
1729 // is supposed to wait on the file handle in that case. We don't support
1730 // this, so we just fail.
1731 if(lpOverlapped == NULL || lpOverlapped->hEvent == 0) {
1732 dprintf(("!ERROR!: lpOverlapped == NULL || lpOverlapped->hEvent == 0"));
1733 SetLastError(ERROR_INVALID_PARAMETER);
1734 return FALSE;
1735 }
1736
1737 return HMGetOverlappedResult(hFile,
1738 lpOverlapped,
1739 lpTransferred,
1740 bWait);
1741}
1742//******************************************************************************
1743//******************************************************************************
Note: See TracBrowser for help on using the repository browser.