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

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

FindFirstFile: return ERROR_FILE_NOT_FOUND if DosFindFirst returns ERROR_PATH_NOT_FOUND

File size: 64.3 KB
Line 
1/* $Id: Fileio.cpp,v 1.69 2003-02-17 11:31:42 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 dprintf(("FindFirstFileMultiA %s %x %x", lpFileName, lpFindFileData, count));
393 return (HANDLE)OSLibDosFindFirstMulti(lpFileName,lpFindFileData,count);
394}
395//******************************************************************************
396//******************************************************************************
397BOOL WIN32API FindNextFileA(HANDLE hFindFile, WIN32_FIND_DATAA * lpFindFileData)
398{
399 return OSLibDosFindNext(hFindFile,lpFindFileData);
400}
401//******************************************************************************
402// internal function for faster access (SHELL32)
403//******************************************************************************
404BOOL WIN32API FindNextFileMultiA(HANDLE hFindFile, WIN32_FIND_DATAA * lpFindFileData,
405 DWORD *count)
406{
407 dprintf(("FindNextFileMultiA %x %x %x", hFindFile, lpFindFileData, count));
408 return OSLibDosFindNextMulti(hFindFile,lpFindFileData,count);
409}
410//******************************************************************************
411//******************************************************************************
412BOOL WIN32API FindNextFileW(HANDLE hFindFile, WIN32_FIND_DATAW * lpFindFileData)
413{
414 WIN32_FIND_DATAA wfda;
415 BOOL rc;
416
417 rc = OSLibDosFindNext(hFindFile,&wfda);
418
419 if(rc == 0) {
420 memset(lpFindFileData, 0, sizeof(WIN32_FIND_DATAW));
421 }
422 else {
423 // convert back the result structure
424 memcpy(lpFindFileData,
425 &wfda,
426 sizeof(WIN32_FIND_DATAA));
427
428 lstrcpynAtoW (lpFindFileData->cFileName,
429 wfda.cFileName,
430 sizeof(wfda.cFileName));
431
432 lstrcpynAtoW (lpFindFileData->cAlternateFileName,
433 wfda.cAlternateFileName,
434 sizeof(wfda.cAlternateFileName));
435 }
436 return rc;
437}
438//******************************************************************************
439//******************************************************************************
440BOOL WIN32API FindClose(HANDLE hFindFile)
441{
442 return OSLibDosFindClose(hFindFile);
443}
444//******************************************************************************
445//******************************************************************************
446DWORD WIN32API GetFileType(HANDLE hFile)
447{
448 return(HMGetFileType(hFile));
449}
450//******************************************************************************
451//******************************************************************************
452DWORD WIN32API GetFileInformationByHandle(HANDLE arg1, BY_HANDLE_FILE_INFORMATION * arg2)
453{
454 return(HMGetFileInformationByHandle(arg1,arg2));
455}
456//******************************************************************************
457//******************************************************************************
458BOOL WIN32API SetEndOfFile(HANDLE arg1)
459{
460 return HMSetEndOfFile(arg1);
461}
462//******************************************************************************
463//******************************************************************************
464BOOL WIN32API SetFileTime(HANDLE arg1, const FILETIME * arg2,
465 const FILETIME * arg3,
466 const FILETIME * arg4)
467{
468 return HMSetFileTime(arg1,
469 arg2,
470 arg3,
471 arg4);
472}
473//******************************************************************************
474//******************************************************************************
475INT WIN32API CompareFileTime(FILETIME * lpft1, FILETIME * lpft2)
476{
477 if (lpft1 == NULL || lpft2 == NULL) {
478 SetLastError(ERROR_INVALID_PARAMETER);
479 return -1;
480 }
481
482 if(lpft1->dwHighDateTime > lpft2->dwHighDateTime)
483 return 1;
484
485 if(lpft1->dwHighDateTime < lpft2->dwHighDateTime)
486 return -1;
487
488 if(lpft1->dwLowDateTime > lpft2->dwLowDateTime)
489 return 1;
490
491 if(lpft1->dwLowDateTime < lpft2->dwLowDateTime)
492 return -1;
493
494 return 0; //equal
495}
496//******************************************************************************
497//******************************************************************************
498BOOL WIN32API GetFileTime(HANDLE hFile, LPFILETIME arg2, LPFILETIME arg3, LPFILETIME arg4)
499{
500 return HMGetFileTime(hFile, arg2, arg3, arg4);
501}
502//******************************************************************************
503//******************************************************************************
504BOOL WIN32API CopyFileA(LPCSTR arg1, LPCSTR arg2, BOOL arg3)
505{
506 return OSLibDosCopyFile(arg1, arg2, arg3);
507}
508//******************************************************************************
509//******************************************************************************
510BOOL WIN32API CopyFileW(LPCWSTR arg1, LPCWSTR arg2, BOOL arg3)
511{
512 BOOL rc;
513 char *astring1, *astring2;
514
515 astring1 = UnicodeToAsciiString((LPWSTR)arg1);
516 astring2 = UnicodeToAsciiString((LPWSTR)arg2);
517 rc = CopyFileA(astring1, astring2, arg3);
518 FreeAsciiString(astring2);
519 FreeAsciiString(astring1);
520 return(rc);
521}
522/*****************************************************************************
523 * Name : BOOL WIN32API CopyFileExA
524 * Purpose : The CopyFileExA function copies an existing file to a new file.
525 * This function preserves extended attributes, OLE structured
526 * storage, NTFS alternate data streams, and file attributes.
527 * Security attributes for the existing file are not copied to
528 * the new file.
529 * Parameters: LPCSTR lpExistingFileName pointer to name of an existing file
530 * LPCSTR lpNewFileName pointer to filename to copy to
531 * LPPROGRESS_ROUTINE lpProgressRoutine pointer to the callback function
532 * LPVOID lpData to be passed to the callback function
533 * LPBOOL pbCancel flag that can be used to cancel the operation
534 * DWORD dwCopyFlags flags that specify how the file is copied
535 * Variables :
536 * Result : f the function succeeds, the return value is nonzero.
537 * If the function fails, the return value is zero.
538 * To get extended error information call GetLastError.
539 * Remark :
540 * Status : UNTESTED STUB
541 *
542 * Author : Markus Montkowski [Thu, 1998/05/19 11:46]
543 *****************************************************************************/
544
545BOOL WIN32API CopyFileExA( LPCSTR lpExistingFileName,
546 LPCSTR lpNewFileName,
547 LPPROGRESS_ROUTINE lpProgressRoutine,
548 LPVOID lpData,
549 LPBOOL pbCancel,
550 DWORD dwCopyFlags)
551{
552
553 dprintf(("KERNEL32: CopyFileExA(%08x,%08x,%08x,%08x,%08x,%08x) not properly implemented\n",
554 lpExistingFileName,
555 lpNewFileName,
556 lpProgressRoutine,
557 lpData,
558 pbCancel,
559 dwCopyFlags
560 ));
561
562 BOOL failIfExists = FALSE;
563
564 /*
565 * Interpret the only flag that CopyFile can interpret.
566 */
567 if((dwCopyFlags & COPY_FILE_FAIL_IF_EXISTS) != 0)
568 {
569 failIfExists = TRUE;
570 }
571
572 return CopyFileA(lpExistingFileName, lpNewFileName, failIfExists);
573}
574
575
576/*****************************************************************************
577 * Name : BOOL WIN32API CopyFileExW
578 * Purpose : The CopyFileExW function copies an existing file to a new file.
579 * This function preserves extended attributes, OLE structured
580 * storage, NTFS alternate data streams, and file attributes.
581 * Security attributes for the existing file are not copied to
582 * the new file.
583 * Parameters: LPCWSTR lpExistingFileName pointer to name of an existing file
584 * LPCWSTR lpNewFileName pointer to filename to copy to
585 * LPPROGRESS_ROUTINE lpProgressRoutine pointer to the callback function
586 * LPVOID lpData to be passed to the callback function
587 * LPBOOL pbCancel flag that can be used to cancel the operation
588 * DWORD dwCopyFlags flags that specify how the file is copied
589 * Variables :
590 * Result : f the function succeeds, the return value is nonzero.
591 * If the function fails, the return value is zero.
592 * To get extended error information call GetLastError.
593 * Remark :
594 * Status : UNTESTED STUB
595 *
596 * Author : Markus Montkowski [Thu, 1998/05/19 11:46]
597 *****************************************************************************/
598
599BOOL WIN32API CopyFileExW( LPCWSTR lpExistingFileName,
600 LPCWSTR lpNewFileName,
601 LPPROGRESS_ROUTINE lpProgressRoutine,
602 LPVOID lpData,
603 LPBOOL pbCancel,
604 DWORD dwCopyFlags)
605{
606 LPSTR sourceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpExistingFileName );
607 LPSTR destA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpNewFileName );
608
609 BOOL ret = CopyFileExA(sourceA,
610 destA,
611 lpProgressRoutine,
612 lpData,
613 pbCancel,
614 dwCopyFlags);
615
616 HeapFree( GetProcessHeap(), 0, sourceA );
617 HeapFree( GetProcessHeap(), 0, destA );
618
619 return ret;
620}
621//******************************************************************************
622//******************************************************************************
623DWORD WIN32API GetFileSize(HANDLE arg1, PDWORD arg2)
624{
625 return HMGetFileSize(arg1,
626 arg2);
627}
628//******************************************************************************
629//******************************************************************************
630BOOL WIN32API DeleteFileA(LPCSTR lpszFile)
631{
632 BOOL rc;
633
634#if 0
635 if((strstr(lpszFile, "odin32_") || strstr(lpszFile, "pe_")) && strstr(lpszFile, ".log")) {
636 return TRUE;
637 }
638#endif
639 rc = OSLibDosDelete((LPSTR)lpszFile);
640 if(!rc) {
641 dprintf(("DeleteFileA %s returned FALSE; last error %x", lpszFile, GetLastError()));
642 if(GetLastError() == ERROR_BAD_UNIT) {
643 return TRUE;
644 }
645 }
646 else dprintf(("DeleteFileA %s", lpszFile));
647
648 return rc;
649}
650//******************************************************************************
651//******************************************************************************
652BOOL WIN32API DeleteFileW(LPCWSTR arg1)
653{
654 BOOL rc;
655 char *astring;
656
657 astring = UnicodeToAsciiString((LPWSTR)arg1);
658 rc = DeleteFileA(astring);
659 FreeAsciiString(astring);
660 return(rc);
661}
662//******************************************************************************
663//******************************************************************************
664UINT WIN32API GetTempFileNameA(LPCSTR lpPathName, LPCSTR lpPrefixString,
665 UINT uUnique, LPSTR lpTempFileName)
666{
667 dprintf(("GetTempFileNameA %s %s", lpPathName, lpPrefixString));
668 return O32_GetTempFileName(lpPathName, lpPrefixString, uUnique, lpTempFileName);
669}
670//******************************************************************************
671//******************************************************************************
672UINT WIN32API GetTempFileNameW(LPCWSTR lpPathName, LPCWSTR lpPrefixString,
673 UINT uUnique, LPWSTR lpTempFileName)
674{
675 char *asciipath, *asciiprefix;
676 char *asciitemp = (char *)malloc(MAX_PATH+1);
677 UINT rc;
678
679 asciipath = UnicodeToAsciiString((LPWSTR)lpPathName);
680 asciiprefix = UnicodeToAsciiString((LPWSTR)lpPrefixString);
681 rc = GetTempFileNameA(asciipath, asciiprefix, uUnique, asciitemp);
682 if(rc) AsciiToUnicode(asciitemp, lpTempFileName);
683 FreeAsciiString(asciiprefix);
684 FreeAsciiString(asciipath);
685 free(asciitemp);
686 return(rc);
687}
688//******************************************************************************
689//******************************************************************************
690BOOL WIN32API ReadFile(HANDLE hFile, PVOID pBuffer, DWORD dwLength,
691 PDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
692{
693 if(lpNumberOfBytesRead) *lpNumberOfBytesRead = 0;
694 if(dwLength == 0) {
695 dprintf(("!WARNING!: Nothing to do"));
696 //TODO: should we fail here instead?? (wine doesn't)
697 return TRUE;
698 }
699 return (HMReadFile(hFile,
700 pBuffer,
701 dwLength,
702 lpNumberOfBytesRead,
703 lpOverlapped, NULL));
704}
705//******************************************************************************
706//******************************************************************************
707BOOL WIN32API ReadFileEx(HANDLE hFile,
708 LPVOID lpBuffer,
709 DWORD nNumberOfBytesToRead,
710 LPOVERLAPPED lpOverlapped,
711 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
712{
713 if(nNumberOfBytesToRead == 0) {
714 dprintf(("!WARNING!: Nothing to do"));
715 //TODO: should we fail here instead?? (wine doesn't)
716 return TRUE;
717 }
718 if(!lpOverlapped || !lpCompletionRoutine) {
719 dprintf(("!WARNING!: !lpOverlapped || !lpCompletionRoutine"));
720 SetLastError(ERROR_INVALID_PARAMETER);
721 return FALSE;
722 }
723 //SDK docs say ReadFileEx will fail if this condition is true
724 if(GetFileType(hFile) == FILE_TYPE_PIPE && (lpOverlapped->Offset || lpOverlapped->OffsetHigh)) {
725 dprintf(("!WARNING!: lpOverlapped->Offset & lpOverlapped->OffsetHigh must be ZERO for named pipes"));
726 SetLastError(ERROR_INVALID_PARAMETER);
727 return FALSE;
728 }
729 return (HMReadFile(hFile,
730 lpBuffer,
731 nNumberOfBytesToRead, NULL,
732 lpOverlapped, lpCompletionRoutine));
733}
734//******************************************************************************
735//******************************************************************************
736BOOL WIN32API WriteFile(HANDLE hFile, LPCVOID buffer, DWORD nrbytes,
737 LPDWORD nrbyteswritten, LPOVERLAPPED lpOverlapped)
738{
739 if(nrbyteswritten) *nrbyteswritten = 0;
740 if(nrbytes == 0) {
741 dprintf(("!WARNING!: Nothing to do"));
742 //TODO: should we fail here instead?? (wine doesn't)
743 return TRUE;
744 }
745
746 return (HMWriteFile(hFile,
747 buffer,
748 nrbytes,
749 nrbyteswritten,
750 lpOverlapped, NULL));
751}
752/*****************************************************************************
753 * Name : BOOL WriteFileEx
754 * Purpose : The WriteFileEx function writes data to a file. It is designed
755 * solely for asynchronous operation, unlike WriteFile, which is
756 * designed for both synchronous and asynchronous operation.
757 * WriteFileEx reports its completion status asynchronously,
758 * calling a specified completion routine when writing is completed
759 * and the calling thread is in an alertable wait state.
760 * Parameters: HANDLE hFile handle of file to write
761 * LPVOID lpBuffer address of buffer
762 * DWORD nNumberOfBytesToRead number of bytes to write
763 * LPOVERLAPPED lpOverlapped address of offset
764 * LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine address of completion routine
765 * Variables :
766 * Result : TRUE / FALSE
767 * Remark :
768 * Status : UNTESTED STUB
769 *
770 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
771 *****************************************************************************/
772
773BOOL WIN32API WriteFileEx(HANDLE hFile,
774 LPCVOID lpBuffer,
775 DWORD nNumberOfBytesToWrite,
776 LPOVERLAPPED lpOverlapped,
777 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
778{
779 if(nNumberOfBytesToWrite == 0) {
780 dprintf(("!WARNING!: Nothing to do"));
781 //TODO: should we fail here instead?? (wine doesn't)
782 return TRUE;
783 }
784 if(!lpOverlapped || !lpCompletionRoutine) {
785 dprintf(("!WARNING!: !lpOverlapped || !lpCompletionRoutine"));
786 SetLastError(ERROR_INVALID_PARAMETER);
787 return FALSE;
788 }
789 //SDK docs say WriteFileEx will fail if this condition is true
790 if(GetFileType(hFile) == FILE_TYPE_PIPE && (lpOverlapped->Offset || lpOverlapped->OffsetHigh)) {
791 dprintf(("!WARNING!: lpOverlapped->Offset & lpOverlapped->OffsetHigh must be ZERO for named pipes"));
792 SetLastError(ERROR_INVALID_PARAMETER);
793 return FALSE;
794 }
795 return (HMWriteFile(hFile,
796 (LPVOID)lpBuffer,
797 nNumberOfBytesToWrite, NULL,
798 lpOverlapped, lpCompletionRoutine));
799}
800//******************************************************************************
801//******************************************************************************
802DWORD WIN32API SetFilePointer(HANDLE hFile, LONG lDistanceToMove,
803 PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod)
804{
805 return(HMSetFilePointer(hFile,
806 lDistanceToMove,
807 lpDistanceToMoveHigh,
808 dwMoveMethod));
809}
810//******************************************************************************
811//******************************************************************************
812DWORD WIN32API GetFileAttributesA(LPCSTR lpszFileName)
813{
814 DWORD rc, error;
815
816 rc = OSLibGetFileAttributes((LPSTR)lpszFileName);
817
818 //SvL: Open32 returns FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_NORMAL for
819 // directories whereas NT 4 (SP6) only returns FILE_ATTRIBUTE_DIRECTORY
820 if(rc != -1 && (rc & FILE_ATTRIBUTE_DIRECTORY)) {
821 rc = FILE_ATTRIBUTE_DIRECTORY;
822 }
823
824#if 0 // need more tests, maybe there is also a better way to hide simulated b:
825 if(rc == -1 && lpszFileName != NULL && !strnicmp(lpszFileName, "B:", 2))
826 {
827 error = GetLastError();
828 if(error = ERROR_DISK_CHANGE)
829 SetLastError(ERROR_NOT_READY);
830 else
831 SetLastError(error);
832 }
833#endif
834 dprintf(("KERNEL32: GetFileAttributes of %s returned %d\n", lpszFileName, rc));
835 return(rc);
836}
837//******************************************************************************
838//******************************************************************************
839DWORD WIN32API GetFileAttributesW(LPCWSTR arg1)
840{
841 DWORD rc;
842 char *astring;
843
844 astring = UnicodeToAsciiString((LPWSTR)arg1);
845 rc = GetFileAttributesA(astring);
846 FreeAsciiString(astring);
847 return(rc);
848}
849//******************************************************************************
850//******************************************************************************
851BOOL WIN32API SetFileAttributesA(LPCSTR lpFileName, DWORD dwFileAttributes)
852{
853 dprintf(("KERNEL32: SetFileAttributes of %s", lpFileName));
854 return O32_SetFileAttributes(lpFileName, dwFileAttributes);
855}
856//******************************************************************************
857//******************************************************************************
858BOOL WIN32API SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
859{
860 char *asciifile;
861 BOOL rc;
862
863 asciifile = UnicodeToAsciiString((LPWSTR)lpFileName);
864 rc = SetFileAttributesA(asciifile, dwFileAttributes);
865 FreeAsciiString(asciifile);
866 return(rc);
867}
868//******************************************************************************
869//******************************************************************************
870DWORD WIN32API GetFullPathNameA(LPCSTR arg1, DWORD arg2, LPSTR arg3,
871 LPSTR * arg4)
872{
873 char *ptr;
874 DWORD rc;
875 dprintf(("KERNEL32: GetFullPathName called with %s %d %x", arg1, arg2, arg3));
876 while((ptr = strchr(arg1, '/')) != NULL)
877 *ptr = '\\';
878
879 return O32_GetFullPathName(arg1, arg2, arg3, arg4);
880}
881//******************************************************************************
882//******************************************************************************
883DWORD WIN32API GetFullPathNameW(LPCWSTR lpFileName, DWORD nBufferLength,
884 LPWSTR lpBuffer, LPWSTR *lpFilePart)
885{
886 char *astring = NULL, *asciibuffer = NULL, *asciipart = NULL;
887 DWORD rc;
888
889 if(nBufferLength) {
890 asciibuffer = (char *)malloc(nBufferLength+1);
891 }
892 astring = UnicodeToAsciiString((LPWSTR)lpFileName);
893
894 rc = GetFullPathNameA(astring, nBufferLength,
895 asciibuffer, &asciipart);
896
897 dprintf(("KERNEL32: GetFullPathNameW %s returns %s\n%s",
898 astring,
899 asciibuffer, asciipart));
900
901 if(rc && asciibuffer)
902 AsciiToUnicode(asciibuffer,
903 lpBuffer);
904
905 if(lpFilePart) {
906 if (asciipart == NULL)
907 *lpFilePart = NULL;
908 else
909 *lpFilePart = lpBuffer + ((int)asciipart - (int)asciibuffer);
910 }
911
912 FreeAsciiString(astring);
913 if(asciibuffer) free(asciibuffer);
914 return(rc);
915}
916//******************************************************************************
917//******************************************************************************
918BOOL WIN32API LockFile(HANDLE arg1, DWORD arg2,
919 DWORD arg3, DWORD arg4,
920 DWORD arg5)
921{
922 return HMLockFile(arg1,
923 arg2,
924 arg3,
925 arg4,
926 arg5);
927}
928
929
930/*****************************************************************************
931 * Name : BOOL LockFileEx
932 * Purpose : The LockFileEx function locks a byte range within an open file for shared or exclusive access.
933 * Parameters: HANDLE hFile handle of file to lock
934 * DWORD dwFlags functional behavior modification flags
935 * DWORD dwReserved reserved, must be set to zero
936 * DWORD nNumberOfBytesToLockLow low-order 32 bits of length to lock
937 * DWORD nNumberOfBytesToLockHigh high-order 32 bits of length to lock
938 * LPOVERLAPPED LPOVERLAPPED addr. of structure with lock region start offset
939 * Variables :
940 * Result : TRUE / FALSE
941 * Remark :
942 * Status : UNTESTED STUB
943 *
944 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
945 *****************************************************************************/
946
947BOOL LockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved,
948 DWORD nNumberOfBytesToLockLow,
949 DWORD nNumberOfBytesToLockHigh,
950 LPOVERLAPPED lpOverlapped)
951{
952 return(HMLockFile(hFile,
953 lpOverlapped->Offset,
954 lpOverlapped->OffsetHigh,
955 nNumberOfBytesToLockLow,
956 nNumberOfBytesToLockHigh));
957}
958//******************************************************************************
959//******************************************************************************
960BOOL WIN32API MoveFileA(LPCSTR arg1, LPCSTR arg2)
961{
962 dprintf(("KERNEL32: MoveFileA %s %s", arg1, arg2));
963 return OSLibDosMoveFile(arg1, arg2);
964}
965//******************************************************************************
966//******************************************************************************
967
968
969/*****************************************************************************
970 * Name : MoveFileExA
971 * Purpose : Move or delete a file
972 * Parameters: LPCSTR lpExistingFileName
973 * LPCSTR lpNewFileName
974 * DWORD dwFlags
975 * Variables :
976 * Result :
977 * Remark : "delete on system-reboot" feature is not supported!
978 * Status :
979 *
980 * Author : Patrick Haller [2001-08-30]
981 *****************************************************************************/
982
983BOOL WIN32API MoveFileExA(LPCSTR lpszOldFilename,
984 LPCSTR lpszNewFilename,
985 DWORD fdwFlags)
986{
987 dprintf(("KERNEL32: MoveFileExA %s to %s %x, not complete!\n",
988 lpszOldFilename,
989 lpszNewFilename,
990 fdwFlags));
991
992 // this parameter combination is illegal
993 if ( (fdwFlags & MOVEFILE_DELAY_UNTIL_REBOOT) &&
994 (fdwFlags & MOVEFILE_COPY_ALLOWED) )
995 {
996 // Note: error code not verified
997 SetLastError(ERROR_INVALID_PARAMETER);
998 return FALSE;
999 }
1000
1001 // first, we take care about the special cases
1002 if (fdwFlags && MOVEFILE_DELAY_UNTIL_REBOOT)
1003 {
1004 // We cannot really support this in any other way than
1005 // to call the IBMCSFLK driver. As the first place I've encountered
1006 // this call is Microsoft ACMSETUP wanting to replace OLEPRO32.DLL
1007 // in the ODIN system directory, we are better skipping the call.
1008
1009 // Anyway, this is only supported under Windows NT
1010 fdwFlags &= ~MOVEFILE_DELAY_UNTIL_REBOOT;
1011
1012 // Until we support this, we have to intercept
1013 // lpszNewFilename == NULL
1014 if (NULL == lpszNewFilename)
1015 {
1016 // try to delete the filename
1017 dprintf(("KERNEL32-MoveFileExA: trying to delete file [%s], skipped.",
1018 lpszOldFilename));
1019
1020 SetLastError( NO_ERROR );
1021 return TRUE;
1022 }
1023 }
1024
1025 if (fdwFlags && MOVEFILE_COPY_ALLOWED)
1026 {
1027 // if lpszOldFilename and lpszNewFilename refer to different
1028 // volumes, this flag controls if a copy operation is allowed.
1029 }
1030
1031 if (fdwFlags && MOVEFILE_REPLACE_EXISTING)
1032 {
1033 // We can only attempt to
1034 // 1 move away the current file if existing,
1035 // 2 do the current move operation
1036 // 3 if succesful, delete the backup
1037 // otherwise restore the original file
1038 }
1039
1040 return OSLibDosMoveFile(lpszOldFilename,
1041 lpszNewFilename);
1042}
1043//******************************************************************************
1044//******************************************************************************
1045BOOL WIN32API MoveFileW(LPCWSTR lpSrc, LPCWSTR lpDest)
1046{
1047 char *asciisrc, *asciidest;
1048 BOOL rc;
1049
1050 asciisrc = UnicodeToAsciiString((LPWSTR)lpSrc);
1051 asciidest = UnicodeToAsciiString((LPWSTR)lpDest);
1052 rc = MoveFileA(asciisrc, asciidest);
1053 FreeAsciiString(asciisrc);
1054 FreeAsciiString(asciidest);
1055 return(rc);
1056}
1057//******************************************************************************
1058//******************************************************************************
1059BOOL WIN32API MoveFileExW(LPCWSTR lpSrc, LPCWSTR lpDest, DWORD fdwFlags)
1060{
1061 dprintf(("KERNEL32: MoveFileExW %ls to %ls %x",
1062 lpSrc,
1063 lpDest,
1064 fdwFlags));
1065
1066 char *asciisrc,
1067 *asciidest;
1068 BOOL rc;
1069
1070 asciisrc = UnicodeToAsciiString((LPWSTR)lpSrc);
1071 if (NULL != lpDest)
1072 asciidest = UnicodeToAsciiString((LPWSTR)lpDest);
1073 else
1074 asciidest = NULL;
1075
1076 rc = MoveFileExA(asciisrc,
1077 asciidest,
1078 fdwFlags);
1079
1080 if (NULL != asciidest)
1081 FreeAsciiString(asciidest);
1082
1083 FreeAsciiString(asciisrc);
1084
1085 return(rc);
1086}
1087//******************************************************************************
1088/*****************************************************************************
1089ODINFUNCTION3(*, :,
1090 HFILE, WIN32API,
1091 OpenFile *, Purpose,
1092 :, forwardOpenFile to Open32
1093 * Parameters:
1094 * Variables :
1095 * Result : API returncode
1096 * Remark : modified for handle translation support
1097 * Status : @@@PH verify if 0 is a valid "invalid handle" :)
1098 *
1099 * Author : Patrick Haller [Fri, 1998/06/12 02:53]
1100 *****************************************************************************/
1101
1102HFILE WIN32API OpenFile(LPCSTR lpszFile, OFSTRUCT *lpOpenBuff,
1103 UINT fuMode)
1104{
1105 HFILE hFile;
1106
1107 dprintf(("KERNEL32: OpenFile(%s, %08xh, %08xh)\n",
1108 lpszFile,
1109 lpOpenBuff,
1110 fuMode));
1111
1112 hFile = HMOpenFile(lpszFile, /* call open32 */
1113 lpOpenBuff,
1114 fuMode);
1115
1116 return (hFile);
1117}
1118//******************************************************************************
1119//******************************************************************************
1120BOOL WIN32API UnlockFile(HANDLE arg1, DWORD arg2, DWORD arg3,
1121 DWORD arg4, DWORD arg5)
1122{
1123 return HMUnlockFile(arg1,
1124 arg2,
1125 arg3,
1126 arg4,
1127 arg5);
1128}
1129
1130
1131/*****************************************************************************
1132 * Name : BOOL UnlockFileEx
1133 * Purpose : The UnlockFileEx function unlocks a previously locked byte range in an open file.
1134 * Parameters: HANDLE hFile handle of file to lock
1135 * DWORD dwReserved reserved, must be set to zero
1136 * DWORD nNumberOfBytesToLockLow low-order 32 bits of length to lock
1137 * DWORD nNumberOfBytesToLockHigh high-order 32 bits of length to lock
1138 * LPOVERLAPPED LPOVERLAPPED addr. of structure with lock region start offset
1139 * Variables :
1140 * Result : TRUE / FALSE
1141 * Remark :
1142 * Status : UNTESTED STUB
1143 *
1144 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
1145 *****************************************************************************/
1146
1147BOOL WIN32API UnlockFileEx(HANDLE hFile, DWORD dwReserved,
1148 DWORD nNumberOfBytesToLockLow,
1149 DWORD nNumberOfBytesToLockHigh,
1150 LPOVERLAPPED lpOverlapped)
1151{
1152 return(HMUnlockFileEx(hFile, dwReserved,
1153 nNumberOfBytesToLockLow,
1154 nNumberOfBytesToLockHigh,
1155 lpOverlapped));
1156}
1157//******************************************************************************
1158//Behaviour in NT 4, SP6:
1159//- converts long filename to 8.3 short filname (TODO: not yet done here!)
1160//- fails on volume that doesn't support 8.3 filenames
1161//- if lpszShortPath 0 or cchBuffer too small -> return required length
1162// (INCLUDING 0 terminator)
1163//- if lpszLongPath == NULL -> ERROR_INVALID_PARAMETER (return 0)
1164//- if lpszLongPath empty -> proceed as if nothing is wrong
1165//- does NOT clear the last error if successful!
1166//- if successful -> return length of string (excluding 0 terminator)
1167//******************************************************************************
1168DWORD WIN32API GetShortPathNameA(LPCTSTR lpszLongPath,
1169 LPTSTR lpszShortPath,
1170 DWORD cchBuffer)
1171{
1172 char short_name[MAX_PATHNAME_LEN]; /* Long pathname in Unix format */
1173 int length, marker = 0;
1174 LPSTR tmpshortpath,tmplongpath;
1175 DWORD attr, sp = 0, lp = 0;
1176 int tmplen, drive;
1177
1178 dprintf(("KERNEL32: GetShortPathNameA %s", lpszLongPath));
1179
1180 if(!lpszLongPath) {
1181 SetLastError(ERROR_INVALID_PARAMETER);
1182 return 0;
1183 }
1184 if (!lpszLongPath[0]) {
1185 SetLastError(ERROR_BAD_PATHNAME);
1186 return 0;
1187 }
1188
1189 if ( ( tmpshortpath = (char*) HeapAlloc ( GetProcessHeap(), 0, MAX_PATHNAME_LEN ) ) == NULL ) {
1190 SetLastError ( ERROR_NOT_ENOUGH_MEMORY );
1191 return 0;
1192 }
1193
1194 if ( ( tmplongpath = (char*) HeapAlloc ( GetProcessHeap(), 0, MAX_PATHNAME_LEN ) ) == NULL ) {
1195 SetLastError ( ERROR_NOT_ENOUGH_MEMORY );
1196 return 0;
1197 }
1198
1199 lstrcpyA(tmplongpath,lpszLongPath);
1200
1201 /* check for drive letter */
1202 if ( lpszLongPath[1] == ':' ) {
1203 tmpshortpath[0] = lpszLongPath[0];
1204 tmpshortpath[1] = ':';
1205 sp = 2;
1206 lp = 2;
1207 }
1208
1209 //todo: check drive validity!
1210
1211 while ( lpszLongPath[lp] ) {
1212 marker = 0;
1213 /* check for path delimiters and reproduce them */
1214 if ( lpszLongPath[lp] == '\\' || lpszLongPath[lp] == '/' ) {
1215 if (!sp || tmpshortpath[sp-1]!= '\\')
1216 {
1217 /* strip double "\\" */
1218 tmpshortpath[sp] = '\\';
1219 sp++;
1220 }
1221 tmpshortpath[sp]=0;/*terminate string*/
1222 lp++;
1223 continue;
1224 }
1225
1226 tmplen = strcspn ( lpszLongPath + lp, "\\/" );
1227 lstrcpynA ( tmpshortpath+sp, lpszLongPath + lp, tmplen+1 );
1228
1229 /* Check, if the current element is a valid dos name */
1230 if ( DOSFS_ValidDOSName ( lpszLongPath + lp, TRUE ) ) {
1231 sp += tmplen;
1232 lp += tmplen;
1233 continue;
1234 }
1235
1236 if (tmplongpath[lp + tmplen] == '\\')
1237 {
1238 tmplongpath[lp + tmplen] = 0;
1239 marker = 1;
1240 }
1241
1242 attr = GetFileAttributesA(tmplongpath);
1243
1244 if (attr == -1)
1245 {
1246 SetLastError ( ERROR_FILE_NOT_FOUND );
1247 HeapFree ( GetProcessHeap(), 0, tmpshortpath );
1248 HeapFree ( GetProcessHeap(), 0, tmplongpath );
1249 return 0;
1250 }
1251
1252 DOSFS_Hash(tmpshortpath+sp, short_name, FALSE, TRUE );
1253
1254 strcpy( tmpshortpath+sp, short_name);
1255 sp += strlen ( tmpshortpath+sp );
1256 if (marker)
1257 tmplongpath[lp + tmplen] = '\\';
1258 lp += tmplen;
1259
1260 }
1261
1262 tmpshortpath[sp] = 0;
1263
1264 lstrcpynA ( lpszShortPath, tmpshortpath, cchBuffer );
1265 dprintf(("returning %s\n", lpszShortPath));
1266 tmplen = strlen ( lpszShortPath );
1267
1268 HeapFree ( GetProcessHeap(), 0, tmpshortpath );
1269 HeapFree ( GetProcessHeap(), 0, tmplongpath );
1270
1271 return tmplen;
1272}
1273//******************************************************************************
1274//******************************************************************************
1275DWORD WIN32API GetShortPathNameW(LPCWSTR lpszLongPath, LPWSTR lpszShortPath,
1276 DWORD cchBuffer)
1277{
1278 LPSTR longpathA, shortpathA;
1279 DWORD ret = 0;
1280
1281 longpathA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszLongPath );
1282 shortpathA = (LPSTR) HeapAlloc ( GetProcessHeap(), 0, cchBuffer );
1283
1284 ret = GetShortPathNameA ( longpathA, shortpathA, cchBuffer );
1285 if (cchBuffer > 0 && !MultiByteToWideChar( CP_ACP, 0, shortpathA, -1, lpszShortPath, cchBuffer ))
1286 lpszShortPath[cchBuffer-1] = 0;
1287 HeapFree( GetProcessHeap(), 0, longpathA );
1288 HeapFree( GetProcessHeap(), 0, shortpathA );
1289
1290 return ret;
1291}
1292//******************************************************************************
1293//Behaviour in NT 4, SP6: (presumably the same as GetShortPathNameA; TODO check)
1294//- converts short filename to long filenames (TODO: not yet done here!)
1295//- if lpszShortPath 0 or cchBuffer too small -> return required length
1296// (INCLUDING 0 terminator)
1297//- if lpszLongPath == NULL -> ERROR_INVALID_PARAMETER (return 0)
1298//- if lpszLongPath empty -> proceed as if nothing is wrong
1299//- does NOT clear the last error if successful!
1300//- if successful -> return length of string (excluding 0 terminator)
1301//******************************************************************************
1302DWORD WINAPI GetLongPathNameA( LPCSTR lpszShortPath, LPSTR lpszLongPath,
1303 DWORD cchBuffer )
1304{
1305 int tmplen;
1306 char short_name[MAX_PATHNAME_LEN]; /* Long pathname in Unix format */
1307 WIN32_FIND_DATAA FindFileData;
1308 HANDLE hFind;
1309 DWORD sp = 0, lp = 0,attr;
1310 LPSTR tmpshortpath,tmplongpath;
1311
1312 dprintf(("GetLongPathNameA %s %x %d", lpszShortPath, lpszLongPath, cchBuffer));
1313
1314 if(!lpszShortPath) {
1315 SetLastError(ERROR_INVALID_PARAMETER);
1316 return 0;
1317 }
1318
1319 if ( ( tmpshortpath = (char*) HeapAlloc ( GetProcessHeap(), 0, MAX_PATHNAME_LEN ) ) == NULL ) {
1320 SetLastError ( ERROR_NOT_ENOUGH_MEMORY );
1321 return 0;
1322 }
1323
1324 if ( ( tmplongpath = (char*) HeapAlloc ( GetProcessHeap(), 0, MAX_PATHNAME_LEN ) ) == NULL ) {
1325 SetLastError ( ERROR_NOT_ENOUGH_MEMORY );
1326 return 0;
1327 }
1328
1329 lstrcpyA(tmpshortpath,lpszShortPath);
1330
1331 /* check for drive letter */
1332 if ( lpszShortPath[1] == ':' ) {
1333 tmplongpath[0] = lpszShortPath[0];
1334 tmplongpath[1] = ':';
1335 sp = 2;
1336 lp = 2;
1337 }
1338
1339 //todo: check drive validity!
1340
1341 while ( lpszShortPath[lp] ) {
1342
1343 /* check for path delimiters and reproduce them */
1344 if ( lpszShortPath[lp] == '\\' || lpszShortPath[lp] == '/' ) {
1345 if (!sp || tmplongpath[sp-1]!= '\\')
1346 {
1347 /* strip double "\\" */
1348 tmplongpath[sp] = '\\';
1349 sp++;
1350 }
1351 tmplongpath[sp]=0;/*terminate string*/
1352 lp++;
1353 continue;
1354 }
1355
1356 tmplen = strcspn ( lpszShortPath + lp, "\\/" );
1357 lstrcpynA ( tmplongpath+sp, lpszShortPath + lp, tmplen+1 );
1358
1359 attr = GetFileAttributesA(tmplongpath);
1360 if (attr != -1)
1361 {
1362 sp += tmplen;
1363 lp += tmplen;
1364 continue;
1365 }
1366 else
1367 // it may be hashed name or name with weird characters!
1368 if ((tmplongpath+sp)[4] == '~')
1369 {
1370 //hashed entry Wine does linear dir search.. incredible.. we will be
1371 //better ;)
1372 if (strchr(tmplongpath+sp,'_'))
1373 {
1374 (tmplongpath+sp)[0] = '*';
1375 (tmplongpath+sp)[1] = 0;
1376 }
1377 else
1378 {
1379 (tmplongpath+sp)[4] = '*';
1380 (tmplongpath+sp)[5] = 0;
1381 }
1382 hFind = FindFirstFileExA(tmplongpath, FindExInfoStandard, &FindFileData,
1383 FindExSearchNameMatch, NULL, 0 );
1384
1385 if (hFind == INVALID_HANDLE_VALUE)
1386 {
1387 //no possible variants!
1388 SetLastError ( ERROR_FILE_NOT_FOUND );
1389 HeapFree ( GetProcessHeap(), 0, tmpshortpath );
1390 HeapFree ( GetProcessHeap(), 0, tmplongpath );
1391 return 0;
1392 }
1393 else
1394 do
1395 {
1396 DOSFS_Hash(FindFileData.cFileName, short_name, FALSE, TRUE );
1397 //this happens on files like [hello world]
1398 if (!lstrncmpA(short_name, lpszShortPath+lp, (lpszShortPath+lp+tmplen)[-1] == '.' ? tmplen-1 : tmplen ))
1399 {
1400 strcpy( tmplongpath+sp, FindFileData.cFileName);
1401 sp += strlen ( tmplongpath+sp );
1402 lp += tmplen;
1403 break;
1404 }
1405 }
1406 while (FindNextFileA(hFind, &FindFileData));
1407
1408 // no FindClose() here or else GetLastError() will not give its error
1409 if (GetLastError() == ERROR_NO_MORE_FILES)
1410 {
1411 FindClose(hFind);
1412 SetLastError ( ERROR_FILE_NOT_FOUND );
1413 HeapFree ( GetProcessHeap(), 0, tmpshortpath );
1414 HeapFree ( GetProcessHeap(), 0, tmplongpath );
1415 return 0;
1416 }
1417 FindClose(hFind);
1418 }
1419 else
1420 {
1421 // if this file can't be found in common or hashed files
1422 // it does not exist
1423 SetLastError ( ERROR_FILE_NOT_FOUND );
1424 HeapFree ( GetProcessHeap(), 0, tmpshortpath );
1425 HeapFree ( GetProcessHeap(), 0, tmplongpath );
1426 return 0;
1427 }
1428 }
1429 tmplongpath[sp] = 0;
1430
1431 lstrcpynA ( lpszLongPath, tmplongpath, cchBuffer );
1432 dprintf(("returning %s\n", lpszLongPath));
1433 tmplen = strlen ( lpszLongPath );
1434
1435 HeapFree ( GetProcessHeap(), 0, tmpshortpath );
1436 HeapFree ( GetProcessHeap(), 0, tmplongpath );
1437
1438 return tmplen;
1439}
1440//******************************************************************************
1441//******************************************************************************
1442DWORD WINAPI GetLongPathNameW( LPCWSTR lpszShortPath, LPWSTR lpszLongPath,
1443 DWORD cchBuffer )
1444{
1445 int length;
1446
1447 dprintf(("GetLongPathNameW %x %ls %d", lpszShortPath, lpszLongPath, cchBuffer));
1448 dprintf(("WARNING: WIN98 ONLY!!"));
1449
1450 if(!lpszShortPath) {
1451 SetLastError(ERROR_INVALID_PARAMETER);
1452 return 0;
1453 }
1454
1455 length = lstrlenW(lpszShortPath) + 1;
1456 if(length > cchBuffer) {
1457 if(lpszLongPath) {
1458 *lpszLongPath = 0;
1459 }
1460 return(length); //return length required (including 0 terminator)
1461 }
1462 lstrcpyW(lpszLongPath, lpszShortPath);
1463 return(length-1);
1464}
1465//******************************************************************************
1466//******************************************************************************
1467void WIN32API SetFileApisToANSI()
1468{
1469 dprintf(("!WARNING! SetFileApisToANSI() stub\n"));
1470}
1471
1472/*****************************************************************************
1473 * Name : DWORD GetCompressedFileSizeA
1474 * Purpose : The GetCompressedFileSizeA function obtains the compressed
1475 * size, in bytes, of a specified file.
1476 * Parameters: LPCTSTR lpFileName, // pointer to name of file
1477 * LPDWORD lpFileSizeHigh // pointer to DWORD to receive
1478 * high-order doubleword of file size
1479 * Variables :
1480 * Result : size of compressed file
1481 * Remark :
1482 * Status : UNTESTED
1483 *
1484 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
1485 *****************************************************************************/
1486
1487DWORD WIN32API GetCompressedFileSizeA(LPCTSTR lpFileName, LPDWORD lpFileSizeHigh)
1488{
1489 dprintf(("KERNEL32: GetCompressedFileSizeA (%s, %08xh) not implemented.\n",
1490 lpFileName,
1491 lpFileSizeHigh));
1492
1493 /* @@@PH: simply return the standard filesize */
1494 return 0;
1495}
1496
1497
1498/*****************************************************************************
1499 * Name : DWORD GetCompressedFileSizeW
1500 * Purpose : The GetCompressedFileSizeE function obtains the compressed
1501 * size, in bytes, of a specified file.
1502 * Parameters: LPCWSTR lpFileName, // pointer to name of file
1503 * LPDWORD lpFileSizeHigh // pointer to DWORD to receive
1504 * high-order doubleword of file size
1505 * Variables :
1506 * Result : size of compressed file
1507 * Remark :
1508 * Status : UNTESTED
1509 *
1510 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
1511 *****************************************************************************/
1512
1513DWORD WIN32API GetCompressedFileSizeW(LPCWSTR lpFileName, LPDWORD lpFileSizeHigh)
1514{
1515 LPCTSTR lpAsciiFileName; /* converted filename */
1516 DWORD rc; /* function result */
1517
1518 dprintf(("KERNEL32: GetCompressedFileSizeW (%s, %08xh)\n",
1519 lpFileName,
1520 lpFileSizeHigh));
1521
1522 lpAsciiFileName = UnicodeToAsciiString( (LPWSTR) lpFileName);
1523
1524 rc = GetCompressedFileSizeA(lpAsciiFileName,
1525 lpFileSizeHigh);
1526
1527 FreeAsciiString( (char *) lpAsciiFileName);
1528
1529 return (rc); /* return result */
1530}
1531
1532
1533/*****************************************************************************
1534 * Name : BOOL GetFileAttributesExA
1535 * Purpose :
1536 * Parameters:
1537 * Variables :
1538 * Result :
1539 * Remark : KERNEL32.874
1540 * Status : UNTESTED
1541 *
1542 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
1543 *****************************************************************************/
1544
1545BOOL WIN32API GetFileAttributesExA(LPCSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
1546 LPVOID lpFileInformation)
1547{
1548 BOOL rc;
1549
1550 dprintf(("KERNEL32: GetFileAttributesExA(%s,%08xh,%08xh) mostly implemented.\n",
1551 lpFileName,
1552 fInfoLevelId,
1553 lpFileInformation));
1554
1555 if (lpFileName == NULL) return FALSE;
1556 if (lpFileInformation == NULL) return FALSE;
1557
1558 if (fInfoLevelId == GetFileExInfoStandard)
1559 {
1560 LPWIN32_FILE_ATTRIBUTE_DATA lpFad = (LPWIN32_FILE_ATTRIBUTE_DATA) lpFileInformation;
1561
1562 rc = OSLibDosGetFileAttributesEx((LPSTR)lpFileName,
1563 fInfoLevelId,
1564 lpFileInformation);
1565 return (rc);
1566 }
1567 else
1568 {
1569 dprintf(("KERNEL32: GetFileAttributesExA - invalid info level %d!\n",
1570 fInfoLevelId));
1571 return FALSE;
1572 }
1573}
1574
1575
1576/*****************************************************************************
1577 * Name : BOOL GetFileAttributesExW
1578 * Purpose :
1579 * Parameters:
1580 * Variables :
1581 * Result :
1582 * Remark : KERNEL32.875
1583 * Status : UNTESTED
1584 *
1585 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
1586 *****************************************************************************/
1587
1588BOOL WIN32API GetFileAttributesExW(LPCWSTR lpFileName,
1589 GET_FILEEX_INFO_LEVELS fInfoLevelId,
1590 LPVOID lpFileInformation)
1591{
1592 LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFileName );
1593 BOOL res = GetFileAttributesExA( nameA, fInfoLevelId, lpFileInformation);
1594 HeapFree( GetProcessHeap(), 0, nameA );
1595 return res;
1596}
1597
1598//******************************************************************************
1599//******************************************************************************
1600HANDLE WIN32API FindFirstChangeNotificationA(LPCSTR lpPathName,
1601 BOOL bWatchSubtree,
1602 DWORD dwNotifyFilter)
1603{
1604 dprintf(("KERNEL32: FindFirstChangeNotificationA %s, Not implemented (faked)", lpPathName));
1605 return -1;
1606}
1607//******************************************************************************
1608//******************************************************************************
1609BOOL WIN32API FindNextChangeNotification(HANDLE hChange)
1610{
1611 dprintf(("KERNEL32: FindNextChangeNotification (%08xh), Not implemented\n",
1612 hChange));
1613
1614 return FALSE;
1615}
1616//******************************************************************************
1617//******************************************************************************
1618BOOL WIN32API FindCloseChangeNotification(HANDLE hChange)
1619{
1620 dprintf(("KERNEL32: OS2FindNextChangeNotification, Not implemented\n"));
1621
1622 return(TRUE);
1623}
1624/*****************************************************************************
1625 * Name : HANDLE WIN32API FindFirstChangeNotificationW
1626 * Purpose : The FindFirstChangeNotification function creates a change
1627 * notification handle and sets up initial change notification
1628 * filter conditions. A wait on a notification handle succeeds when
1629 * a change matching the filter conditions occurs in the specified
1630 * directory or subtree.
1631 * Parameters: LPCWSTR lpPathName pointer to name of directory to watch
1632 * BOOL bWatchSubtree flag for monitoring directory or
1633 * directory tree
1634 * DWORD dwNotifyFilter filter conditions to watch for
1635 * Variables :
1636 * Result : If the function succeeds, the return value is a handle to a find
1637 * change notification object.
1638 * If the function fails, the return value is INVALID_HANDLE_VALUE
1639 * Remark :
1640 * Status : UNTESTED STUB
1641 *
1642 * Author : Markus Montkowski [Tha, 1998/05/21 20:57]
1643 *****************************************************************************/
1644HANDLE WIN32API FindFirstChangeNotificationW(LPCWSTR lpPathName,
1645 BOOL bWatchSubtree,
1646 DWORD dwNotifyFilter)
1647{
1648 LPSTR lpAsciiPath;
1649 HANDLE hChange;
1650
1651 lpAsciiPath = UnicodeToAsciiString( (LPWSTR) lpPathName);
1652 hChange = FindFirstChangeNotificationA(lpAsciiPath, bWatchSubtree,
1653 dwNotifyFilter );
1654 if (lpAsciiPath) FreeAsciiString(lpAsciiPath);
1655 return hChange;
1656}
1657//******************************************************************************
1658//******************************************************************************
1659BOOL WIN32API DeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode,
1660 LPVOID lpInBuffer, DWORD nInBufferSize,
1661 LPVOID lpOutBuffer, DWORD nOutBufferSize,
1662 LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
1663{
1664 return HMDeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize,
1665 lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped);
1666}
1667/*****************************************************************************
1668 * Name : BOOL WIN32API CancelIo
1669 * Purpose : The CancelIO function cancels all pending input and output
1670 * (I/O) operations that were issued by the calling thread for
1671 * the specified file handle. The function does not cancel
1672 * I/O operations issued for the file handle by other threads.
1673 * Parameters: HANDLE hFile file handle for which to cancel I/O
1674 * Variables :
1675 * Result : If the function succeeds, the return value is nonzero All pending
1676 * I/O operations issued by the calling thread for the file handle
1677 * were successfully canceled.
1678 * If the function fails, the return value is zero.
1679 * To get extended error information, call GetLastError.
1680 * Remark : If there are any I/O operations in progress for the specified
1681 * file HANDLE and they were issued by the calling thread, the
1682 * CancelIO function cancels them.
1683 * Note that the I/O operations must have been issued as
1684 * overlapped I/O. If they were not, the I/O operations would not
1685 * have returned to allow the thread to call the CancelIO function.
1686 * Calling the CancelIO function with a file handle that was not
1687 * opened with FILE_FLAG_OVERLAPPED does nothing.
1688 * All I/O operations that are canceled will complete with the
1689 * error ERROR_OPERATION_ABORTED. All completion notifications
1690 * for the I/O operations will occur normally.
1691 * Status :
1692 *
1693 * Author : Markus Montkowski [Thu, 1998/05/19 11:46]
1694 *****************************************************************************/
1695BOOL WIN32API CancelIo(HANDLE hFile)
1696{
1697 return HMCancelIo(hFile);
1698}
1699/*****************************************************************************
1700 * Name : BOOL GetOverlappedResult
1701 * Purpose : forward call to Open32
1702 * Parameters:
1703 * Variables :
1704 * Result :
1705 * Remark : handle translation is done in GetOverlappedResult
1706 * Status :
1707 *
1708 * Author : Patrick Haller [Fri, 1999/06/18 03:44]
1709 *****************************************************************************/
1710
1711BOOL WIN32API GetOverlappedResult(HANDLE hFile, /* [in] handle of file to check on */
1712 LPOVERLAPPED lpOverlapped, /* [in/out] pointer to overlapped */
1713 LPDWORD lpTransferred, /* [in/out] number of bytes transferred */
1714 BOOL bWait) /* [in] wait for the transfer to complete ? */
1715{
1716 //NOTE: According to the SDK docs lpOverlapped->hEvent can be 0. This function
1717 // is supposed to wait on the file handle in that case. We don't support
1718 // this, so we just fail.
1719 if(lpOverlapped == NULL || lpOverlapped->hEvent == 0) {
1720 dprintf(("!ERROR!: lpOverlapped == NULL || lpOverlapped->hEvent == 0"));
1721 SetLastError(ERROR_INVALID_PARAMETER);
1722 return FALSE;
1723 }
1724
1725 return HMGetOverlappedResult(hFile,
1726 lpOverlapped,
1727 lpTransferred,
1728 bWait);
1729}
1730//******************************************************************************
1731//******************************************************************************
Note: See TracBrowser for help on using the repository browser.