source: trunk/src/kernel32/Fileio.cpp

Last change on this file was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

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