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

Last change on this file since 21329 was 21329, checked in by vladest, 16 years ago

Added functionality, required for Flash10 to kernel32

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