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

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

Rewrote GetFileAttributesA & translate filename used from Windows to OS/2 codepage

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