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

Last change on this file since 9892 was 9892, checked in by sandervl, 22 years ago

DeleteFile: when deleting a .lnk file, verify if it's a shell link object file. if so, delete WPS object

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