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

Last change on this file since 7798 was 7798, checked in by sandervl, 24 years ago

Ported GetTempPathA/W from Wine

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