Newer
Older
*p++ = '\\';
}
if (IS_END_OF_NAME(name[1]))
{
name++;
while ((*name == '\\') || (*name == '/')) name++;
continue;
}
else if ((name[1] == '.') && IS_END_OF_NAME(name[2]))
{
name += 2;
while ((*name == '\\') || (*name == '/')) name++;
if (p < buffer + 3) /* no previous dir component */
continue;
p--; /* skip previously added '\\' */
while ((*p == '\\') || (*p == '/')) p--;
/* skip previous dir component */
while ((*p != '\\') && (*p != '/')) p--;
p++;
if ( *endchar )
{ DOS_ERROR( ER_PathNotFound, EC_NotFound, SA_Abort, EL_Disk );
while (!IS_END_OF_NAME(*name) && (!*endchar) )
while (((*name == '\\') || (*name == '/')) && (!*endchar) )
*p++ = *name++;
if (!(DRIVE_GetFlags(drive) & DRIVE_CASE_PRESERVING))
CharUpper32A( buffer );
if (unicode)
lstrcpynAtoW( (LPWSTR)result, buffer, len );
else
lstrcpyn32A( result, buffer, len );
TRACE(dosfs, "returning '%s'\n", buffer );
/* If the lpBuffer buffer is too small, the return value is the
size of the buffer, in characters, required to hold the path. */
ret = strlen(buffer);
if (ret >= len )
SetLastError( ERROR_INSUFFICIENT_BUFFER );
return ret;
}
/***********************************************************************
* GetFullPathName32A (KERNEL32.272)
* NOTES
* if the path closed with '\', *lastpart is 0
DWORD WINAPI GetFullPathName32A( LPCSTR name, DWORD len, LPSTR buffer,
LPSTR *lastpart )
{
DWORD ret = DOSFS_DoGetFullPathName( name, len, buffer, FALSE );
if (ret && lastpart)
{
LPSTR p = buffer + strlen(buffer);
if (*p != '\\')
{
while ((p > buffer + 2) && (*p != '\\')) p--;
*lastpart = p + 1;
}
else *lastpart = NULL;
}
return ret;
}
/***********************************************************************
* GetFullPathName32W (KERNEL32.273)
*/
DWORD WINAPI GetFullPathName32W( LPCWSTR name, DWORD len, LPWSTR buffer,
LPWSTR *lastpart )
{
LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
DWORD ret = DOSFS_DoGetFullPathName( nameA, len, (LPSTR)buffer, TRUE );
HeapFree( GetProcessHeap(), 0, nameA );
if (ret && lastpart)
{
LPWSTR p = buffer + lstrlen32W(buffer);
if (*p != (WCHAR)'\\')
{
while ((p > buffer + 2) && (*p != (WCHAR)'\\')) p--;
*lastpart = p + 1;
}
else *lastpart = NULL;
}
/***********************************************************************
static int DOSFS_FindNextEx( FIND_FIRST_INFO *info, WIN32_FIND_DATA32A *entry )
BYTE attr = info->attr | FA_UNUSED | FA_ARCHIVE | FA_RDONLY;
UINT32 flags = DRIVE_GetFlags( info->drive );
char *p, buffer[MAX_PATHNAME_LEN];
const char *drive_path;
int drive_root;
BY_HANDLE_FILE_INFORMATION fileinfo;
char dos_name[13];
if ((info->attr & ~(FA_UNUSED | FA_ARCHIVE | FA_RDONLY)) == FA_LABEL)
DOSFS_UnixTimeToFileTime( (time_t)0, &entry->ftCreationTime, 0 );
DOSFS_UnixTimeToFileTime( (time_t)0, &entry->ftLastAccessTime, 0 );
DOSFS_UnixTimeToFileTime( (time_t)0, &entry->ftLastWriteTime, 0 );
entry->nFileSizeHigh = 0;
entry->nFileSizeLow = 0;
entry->dwReserved0 = 0;
entry->dwReserved1 = 0;
DOSFS_ToDosDTAFormat( DRIVE_GetLabel( info->drive ), entry->cFileName );
strcpy( entry->cAlternateFileName, entry->cFileName );
info->cur_pos++;
drive_path = info->path + strlen(DRIVE_GetRoot( info->drive ));
while ((*drive_path == '/') || (*drive_path == '\\')) drive_path++;
drive_root = !*drive_path;
lstrcpyn32A( buffer, info->path, sizeof(buffer) - 1 );
strcat( buffer, "/" );
p = buffer + strlen(buffer);
while (DOSFS_ReadDir( info->dir, &long_name, &short_name ))
/* Don't return '.' and '..' in the root of the drive */
if (drive_root && (long_name[0] == '.') &&
(!long_name[1] || ((long_name[1] == '.') && !long_name[2])))
continue;
flags & DRIVE_CASE_SENSITIVE )) continue;
}
/* Check the short mask */
{
DOSFS_Hash( long_name, dos_name, TRUE,
!(flags & DRIVE_CASE_SENSITIVE) );
short_name = dos_name;
}
if (!DOSFS_MatchShort( info->short_mask, short_name )) continue;
lstrcpyn32A( p, long_name, sizeof(buffer) - (int)(p - buffer) );
/* We now have a matching entry; fill the result and return */
entry->dwFileAttributes = fileinfo.dwFileAttributes;
entry->ftCreationTime = fileinfo.ftCreationTime;
entry->ftLastAccessTime = fileinfo.ftLastAccessTime;
entry->ftLastWriteTime = fileinfo.ftLastWriteTime;
entry->nFileSizeHigh = fileinfo.nFileSizeHigh;
entry->nFileSizeLow = fileinfo.nFileSizeLow;
if (short_name)
DOSFS_ToDosDTAFormat( short_name, entry->cAlternateFileName );
else
DOSFS_Hash( long_name, entry->cAlternateFileName, FALSE,
!(flags & DRIVE_CASE_SENSITIVE) );
lstrcpyn32A( entry->cFileName, long_name, sizeof(entry->cFileName) );
if (!(flags & DRIVE_CASE_PRESERVING)) CharLower32A( entry->cFileName );
entry->cFileName, entry->cAlternateFileName,
entry->dwFileAttributes, entry->nFileSizeLow );
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
/***********************************************************************
* DOSFS_FindNext
*
* Find the next matching file. Return the number of entries read to find
* the matching one, or 0 if no more entries.
* 'short_mask' is the 8.3 mask (in FCB format), 'long_mask' is the long
* file name mask. Either or both can be NULL.
*
* NOTE: This is supposed to be only called by the int21 emulation
* routines. Thus, we should own the Win16Mutex anyway.
* Nevertheless, we explicitly enter it to ensure the static
* directory cache is protected.
*/
int DOSFS_FindNext( const char *path, const char *short_mask,
const char *long_mask, int drive, BYTE attr,
int skip, WIN32_FIND_DATA32A *entry )
{
static FIND_FIRST_INFO info = { NULL };
LPCSTR short_name, long_name;
int count;
SYSLEVEL_EnterWin16Lock();
/* Check the cached directory */
if (!(info.dir && info.path == path && info.short_mask == short_mask
&& info.long_mask == long_mask && info.drive == drive
&& info.attr == attr && info.cur_pos <= skip))
{
/* Not in the cache, open it anew */
if (info.dir) DOSFS_CloseDir( info.dir );
info.path = (LPSTR)path;
info.long_mask = (LPSTR)long_mask;
info.short_mask = (LPSTR)short_mask;
info.attr = attr;
info.drive = drive;
info.cur_pos = 0;
info.dir = DOSFS_OpenDir( info.path );
}
/* Skip to desired position */
while (info.cur_pos < skip)
if (info.dir && DOSFS_ReadDir( info.dir, &long_name, &short_name ))
if (info.dir && info.cur_pos == skip && DOSFS_FindNextEx( &info, entry ))
count = info.cur_pos - skip;
else
count = 0;
if (!count)
{
memset( &info, '\0', sizeof(info) );
}
SYSLEVEL_LeaveWin16Lock();
return count;
}
/*************************************************************************
* FindFirstFile16 (KERNEL.413)
*/
HANDLE16 WINAPI FindFirstFile16( LPCSTR path, WIN32_FIND_DATA32A *data )
return INVALID_HANDLE_VALUE16;
if (!(handle = GlobalAlloc16( GMEM_MOVEABLE, sizeof(FIND_FIRST_INFO) )))
return INVALID_HANDLE_VALUE16;
info = (FIND_FIRST_INFO *)GlobalLock16( handle );
info->path = HEAP_strdupA( SystemHeap, 0, full_name.long_name );
info->long_mask = strrchr( info->path, '/' );
*(info->long_mask++) = '\0';
info->short_mask = NULL;
info->attr = 0xff;
if (path[0] && (path[1] == ':')) info->drive = toupper(*path) - 'A';
else info->drive = DRIVE_GetCurrentDrive();
info->cur_pos = 0;
info->dir = DOSFS_OpenDir( info->path );
GlobalUnlock16( handle );
if (!FindNextFile16( handle, data ))
{
FindClose16( handle );
DOS_ERROR( ER_NoMoreFiles, EC_MediaError, SA_Abort, EL_Disk );
return INVALID_HANDLE_VALUE16;
}
return handle;
}
/*************************************************************************
* FindFirstFile32A (KERNEL32.123)
*/
HANDLE32 WINAPI FindFirstFile32A( LPCSTR path, WIN32_FIND_DATA32A *data )
{
HANDLE32 handle = FindFirstFile16( path, data );
if (handle == INVALID_HANDLE_VALUE16) return INVALID_HANDLE_VALUE32;
return handle;
}
/*************************************************************************
* FindFirstFile32W (KERNEL32.124)
*/
HANDLE32 WINAPI FindFirstFile32W( LPCWSTR path, WIN32_FIND_DATA32W *data )
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
{
WIN32_FIND_DATA32A dataA;
LPSTR pathA = HEAP_strdupWtoA( GetProcessHeap(), 0, path );
HANDLE32 handle = FindFirstFile32A( pathA, &dataA );
HeapFree( GetProcessHeap(), 0, pathA );
if (handle != INVALID_HANDLE_VALUE32)
{
data->dwFileAttributes = dataA.dwFileAttributes;
data->ftCreationTime = dataA.ftCreationTime;
data->ftLastAccessTime = dataA.ftLastAccessTime;
data->ftLastWriteTime = dataA.ftLastWriteTime;
data->nFileSizeHigh = dataA.nFileSizeHigh;
data->nFileSizeLow = dataA.nFileSizeLow;
lstrcpyAtoW( data->cFileName, dataA.cFileName );
lstrcpyAtoW( data->cAlternateFileName, dataA.cAlternateFileName );
}
return handle;
}
/*************************************************************************
* FindNextFile16 (KERNEL.414)
*/
BOOL16 WINAPI FindNextFile16( HANDLE16 handle, WIN32_FIND_DATA32A *data )
{
FIND_FIRST_INFO *info;
if (!(info = (FIND_FIRST_INFO *)GlobalLock16( handle )))
{
DOS_ERROR( ER_InvalidHandle, EC_ProgramError, SA_Abort, EL_Disk );
return FALSE;
}
GlobalUnlock16( handle );
{
DOS_ERROR( ER_NoMoreFiles, EC_MediaError, SA_Abort, EL_Disk );
return FALSE;
}
DOS_ERROR( ER_NoMoreFiles, EC_MediaError, SA_Abort, EL_Disk );
return FALSE;
}
return TRUE;
}
/*************************************************************************
* FindNextFile32A (KERNEL32.126)
*/
BOOL32 WINAPI FindNextFile32A( HANDLE32 handle, WIN32_FIND_DATA32A *data )
{
return FindNextFile16( handle, data );
}
/*************************************************************************
* FindNextFile32W (KERNEL32.127)
*/
BOOL32 WINAPI FindNextFile32W( HANDLE32 handle, WIN32_FIND_DATA32W *data )
{
WIN32_FIND_DATA32A dataA;
if (!FindNextFile32A( handle, &dataA )) return FALSE;
data->dwFileAttributes = dataA.dwFileAttributes;
data->ftCreationTime = dataA.ftCreationTime;
data->ftLastAccessTime = dataA.ftLastAccessTime;
data->ftLastWriteTime = dataA.ftLastWriteTime;
data->nFileSizeHigh = dataA.nFileSizeHigh;
data->nFileSizeLow = dataA.nFileSizeLow;
lstrcpyAtoW( data->cFileName, dataA.cFileName );
lstrcpyAtoW( data->cAlternateFileName, dataA.cAlternateFileName );
return TRUE;
}
/*************************************************************************
* FindClose16 (KERNEL.415)
*/
{
FIND_FIRST_INFO *info;
if ((handle == INVALID_HANDLE_VALUE16) ||
!(info = (FIND_FIRST_INFO *)GlobalLock16( handle )))
{
DOS_ERROR( ER_InvalidHandle, EC_ProgramError, SA_Abort, EL_Disk );
return FALSE;
}
if (info->path) HeapFree( SystemHeap, 0, info->path );
GlobalUnlock16( handle );
GlobalFree16( handle );
return TRUE;
}
/*************************************************************************
* FindClose32 (KERNEL32.119)
*/
{
return FindClose16( (HANDLE16)handle );
}
/***********************************************************************
* DOSFS_UnixTimeToFileTime
*
* Convert a Unix time to FILETIME format.
* The FILETIME structure is a 64-bit value representing the number of
* 100-nanosecond intervals since January 1, 1601, 0:00.
* 'remainder' is the nonnegative number of 100-ns intervals
* corresponding to the time fraction smaller than 1 second that
* couldn't be stored in the time_t value.
void DOSFS_UnixTimeToFileTime( time_t unix_time, FILETIME *filetime,
DWORD remainder )
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
/* NOTES:
CONSTANTS:
The time difference between 1 January 1601, 00:00:00 and
1 January 1970, 00:00:00 is 369 years, plus the leap years
from 1604 to 1968, excluding 1700, 1800, 1900.
This makes (1968 - 1600) / 4 - 3 = 89 leap days, and a total
of 134774 days.
Any day in that period had 24 * 60 * 60 = 86400 seconds.
The time difference is 134774 * 86400 * 10000000, which can be written
116444736000000000
27111902 * 2^32 + 3577643008
413 * 2^48 + 45534 * 2^32 + 54590 * 2^16 + 32768
If you find that these constants are buggy, please change them in all
instances in both conversion functions.
VERSIONS:
There are two versions, one of them uses long long variables and
is presumably faster but not ISO C. The other one uses standard C
data types and operations but relies on the assumption that negative
numbers are stored as 2's complement (-1 is 0xffff....). If this
assumption is violated, dates before 1970 will not convert correctly.
This should however work on any reasonable architecture where WINE
will run.
DETAILS:
Take care not to remove the casts. I have tested these functions
(in both versions) for a lot of numbers. I would be interested in
results on other compilers than GCC.
The operations have been designed to account for the possibility
of 64-bit time_t in future UNICES. Even the versions without
internal long long numbers will work if time_t only is 64 bit.
A 32-bit shift, which was necessary for that operation, turned out
not to work correctly in GCC, besides giving the warning. So I
used a double 16-bit shift instead. Numbers are in the ISO version
represented by three limbs, the most significant with 32 bit, the
other two with 16 bit each.
As the modulo-operator % is not well-defined for negative numbers,
negative divisors have been avoided in DOSFS_FileTimeToUnixTime.
There might be quicker ways to do this in C. Certainly so in
assembler.
Claus Fischer, fischer@iue.tuwien.ac.at
*/
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
# define USE_LONG_LONG 1
#else
# define USE_LONG_LONG 0
#endif
#if USE_LONG_LONG /* gcc supports long long type */
long long int t = unix_time;
t *= 10000000;
t += 116444736000000000LL;
t += remainder;
filetime->dwLowDateTime = (UINT32)t;
filetime->dwHighDateTime = (UINT32)(t >> 32);
#else /* ISO version */
UINT32 a0; /* 16 bit, low bits */
UINT32 a1; /* 16 bit, medium bits */
UINT32 a2; /* 32 bit, high bits */
/* Copy the unix time to a2/a1/a0 */
a0 = unix_time & 0xffff;
a1 = (unix_time >> 16) & 0xffff;
/* This is obsolete if unix_time is only 32 bits, but it does not hurt.
Do not replace this by >> 32, it gives a compiler warning and it does
not work. */
a2 = (unix_time >= 0 ? (unix_time >> 16) >> 16 :
~((~unix_time >> 16) >> 16));
/* Multiply a by 10000000 (a = a2/a1/a0)
Split the factor into 10000 * 1000 which are both less than 0xffff. */
a0 *= 10000;
a1 = a1 * 10000 + (a0 >> 16);
a2 = a2 * 10000 + (a1 >> 16);
a0 &= 0xffff;
a1 &= 0xffff;
a0 *= 1000;
a1 = a1 * 1000 + (a0 >> 16);
a2 = a2 * 1000 + (a1 >> 16);
a0 &= 0xffff;
a1 &= 0xffff;
/* Add the time difference and the remainder */
a0 += 32768 + (remainder & 0xffff);
a1 += 54590 + (remainder >> 16 ) + (a0 >> 16);
a2 += 27111902 + (a1 >> 16);
a0 &= 0xffff;
a1 &= 0xffff;
/* Set filetime */
filetime->dwLowDateTime = (a1 << 16) + a0;
filetime->dwHighDateTime = a2;
#endif
/***********************************************************************
* DOSFS_FileTimeToUnixTime
*
* Convert a FILETIME format to Unix time.
* If not NULL, 'remainder' contains the fractional part of the filetime,
* in the range of [0..9999999] (even if time_t is negative).
time_t DOSFS_FileTimeToUnixTime( const FILETIME *filetime, DWORD *remainder )
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
/* Read the comment in the function DOSFS_UnixTimeToFileTime. */
#if USE_LONG_LONG
long long int t = filetime->dwHighDateTime;
t <<= 32;
t += (UINT32)filetime->dwLowDateTime;
t -= 116444736000000000LL;
if (t < 0)
{
if (remainder) *remainder = 9999999 - (-t - 1) % 10000000;
return -1 - ((-t - 1) / 10000000);
}
else
{
if (remainder) *remainder = t % 10000000;
return t / 10000000;
}
#else /* ISO version */
UINT32 a0; /* 16 bit, low bits */
UINT32 a1; /* 16 bit, medium bits */
UINT32 a2; /* 32 bit, high bits */
UINT32 r; /* remainder of division */
unsigned int carry; /* carry bit for subtraction */
int negative; /* whether a represents a negative value */
/* Copy the time values to a2/a1/a0 */
a2 = (UINT32)filetime->dwHighDateTime;
a1 = ((UINT32)filetime->dwLowDateTime ) >> 16;
a0 = ((UINT32)filetime->dwLowDateTime ) & 0xffff;
/* Subtract the time difference */
if (a0 >= 32768 ) a0 -= 32768 , carry = 0;
else a0 += (1 << 16) - 32768 , carry = 1;
if (a1 >= 54590 + carry) a1 -= 54590 + carry, carry = 0;
else a1 += (1 << 16) - 54590 - carry, carry = 1;
a2 -= 27111902 + carry;
/* If a is negative, replace a by (-1-a) */
negative = (a2 >= ((UINT32)1) << 31);
if (negative)
{
/* Set a to -a - 1 (a is a2/a1/a0) */
a0 = 0xffff - a0;
a1 = 0xffff - a1;
a2 = ~a2;
}
/* Divide a by 10000000 (a = a2/a1/a0), put the rest into r.
Split the divisor into 10000 * 1000 which are both less than 0xffff. */
a1 += (a2 % 10000) << 16;
a2 /= 10000;
a0 += (a1 % 10000) << 16;
a1 /= 10000;
r = a0 % 10000;
a0 /= 10000;
a1 += (a2 % 1000) << 16;
a2 /= 1000;
a0 += (a1 % 1000) << 16;
a1 /= 1000;
r += (a0 % 1000) * 10000;
a0 /= 1000;
/* If a was negative, replace a by (-1-a) and r by (9999999 - r) */
if (negative)
{
/* Set a to -a - 1 (a is a2/a1/a0) */
a0 = 0xffff - a0;
a1 = 0xffff - a1;
a2 = ~a2;
r = 9999999 - r;
}
if (remainder) *remainder = r;
/* Do not replace this by << 32, it gives a compiler warning and it does
not work. */
return ((((time_t)a2) << 16) << 16) + (a1 << 16) + a0;
#endif
/***********************************************************************
* DosDateTimeToFileTime (KERNEL32.76)
*/
BOOL32 WINAPI DosDateTimeToFileTime( WORD fatdate, WORD fattime, LPFILETIME ft)
struct tm newtm;
newtm.tm_sec = (fattime & 0x1f) * 2;
newtm.tm_min = (fattime >> 5) & 0x3f;
newtm.tm_hour = (fattime >> 11);
newtm.tm_mday = (fatdate & 0x1f);
newtm.tm_mon = ((fatdate >> 5) & 0x0f) - 1;
newtm.tm_year = (fatdate >> 9) + 80;
DOSFS_UnixTimeToFileTime( mktime( &newtm ), ft, 0 );
return TRUE;
}
/***********************************************************************
* FileTimeToDosDateTime (KERNEL32.111)
*/
BOOL32 WINAPI FileTimeToDosDateTime( const FILETIME *ft, LPWORD fatdate,
LPWORD fattime )
time_t unixtime = DOSFS_FileTimeToUnixTime( ft, NULL );
struct tm *tm = localtime( &unixtime );
if (fattime)
*fattime = (tm->tm_hour << 11) + (tm->tm_min << 5) + (tm->tm_sec / 2);
if (fatdate)
*fatdate = ((tm->tm_year - 80) << 9) + ((tm->tm_mon + 1) << 5)
+ tm->tm_mday;
return TRUE;
}
/***********************************************************************
* LocalFileTimeToFileTime (KERNEL32.373)
*/
BOOL32 WINAPI LocalFileTimeToFileTime( const FILETIME *localft,
LPFILETIME utcft )
/* convert from local to UTC. Perhaps not correct. FIXME */
time_t unixtime = DOSFS_FileTimeToUnixTime( localft, &remainder );
xtm = gmtime( &unixtime );
DOSFS_UnixTimeToFileTime( mktime(xtm), utcft, remainder );
return TRUE;
}
/***********************************************************************
* FileTimeToLocalFileTime (KERNEL32.112)
*/
BOOL32 WINAPI FileTimeToLocalFileTime( const FILETIME *utcft,
LPFILETIME localft )
/* convert from UTC to local. Perhaps not correct. FIXME */
time_t unixtime = DOSFS_FileTimeToUnixTime( utcft, &remainder );
#ifdef HAVE_TIMEGM
struct tm *xtm = localtime( &unixtime );
time_t localtime;
localtime = timegm(xtm);
DOSFS_UnixTimeToFileTime( localtime, localft, remainder );
#else
struct tm *xtm,*gtm;
time_t time1,time2;
gtm = gmtime( &unixtime );
time1 = mktime(xtm);
time2 = mktime(gtm);
DOSFS_UnixTimeToFileTime( 2*time1-time2, localft, remainder );
#endif
return TRUE;
}
/***********************************************************************
* FileTimeToSystemTime (KERNEL32.113)
*/
BOOL32 WINAPI FileTimeToSystemTime( const FILETIME *ft, LPSYSTEMTIME syst )
DWORD remainder;
time_t xtime = DOSFS_FileTimeToUnixTime( ft, &remainder );
syst->wDayOfWeek = xtm->tm_wday;
syst->wDay = xtm->tm_mday;
syst->wHour = xtm->tm_hour;
syst->wMinute = xtm->tm_min;
syst->wSecond = xtm->tm_sec;
syst->wMilliseconds = remainder / 10000;
/***********************************************************************
* QueryDosDeviceA (KERNEL32.413)
*
* returns array of strings terminated by \0, terminated by \0
*/
DWORD WINAPI QueryDosDevice32A(LPCSTR devname,LPSTR target,DWORD bufsize)
TRACE(dosfs,"(%s,...)\n",devname?devname:"<null>");
if (!devname) {
/* return known MSDOS devices */
lstrcpy32A(buffer,"CON COM1 COM2 LPT1 NUL ");
while ((s=strchr(buffer,' ')))
*s='\0';
lstrcpyn32A(target,buffer,bufsize);
return strlen(buffer);
}
lstrcpy32A(buffer,"\\DEV\\");
lstrcat32A(buffer,devname);
lstrcpyn32A(target,buffer,bufsize);
return strlen(buffer);
}
/***********************************************************************
* QueryDosDeviceW (KERNEL32.414)
*
* returns array of strings terminated by \0, terminated by \0
*/
DWORD WINAPI QueryDosDevice32W(LPCWSTR devname,LPWSTR target,DWORD bufsize)
{
LPSTR devnameA = devname?HEAP_strdupWtoA(GetProcessHeap(),0,devname):NULL;
LPSTR targetA = (LPSTR)HEAP_xalloc(GetProcessHeap(),0,bufsize);
DWORD ret = QueryDosDevice32A(devnameA,targetA,bufsize);
lstrcpynAtoW(target,targetA,bufsize);
if (devnameA) HeapFree(GetProcessHeap(),0,devnameA);
if (targetA) HeapFree(GetProcessHeap(),0,targetA);
return ret;
}
/***********************************************************************
* SystemTimeToFileTime (KERNEL32.526)
*/
BOOL32 WINAPI SystemTimeToFileTime( const SYSTEMTIME *syst, LPFILETIME ft )
time_t utctime;
#else
struct tm xtm,*local_tm,*utc_tm;
time_t localtim,utctime;
#endif
xtm.tm_wday = syst->wDayOfWeek;
xtm.tm_mday = syst->wDay;
xtm.tm_hour = syst->wHour;
xtm.tm_min = syst->wMinute;
xtm.tm_sec = syst->wSecond; /* this is UTC */
xtm.tm_isdst = -1;
#ifdef HAVE_TIMEGM
utctime = timegm(&xtm);
DOSFS_UnixTimeToFileTime( utctime, ft,
syst->wMilliseconds * 10000 );
#else
localtim = mktime(&xtm); /* now we've got local time */
local_tm = localtime(&localtim);
utc_tm = gmtime(&localtim);
utctime = mktime(utc_tm);
DOSFS_UnixTimeToFileTime( 2*localtim -utctime, ft,
syst->wMilliseconds * 10000 );
#endif
BOOL32 WINAPI DefineDosDevice32A(DWORD flags,LPCSTR devname,LPCSTR targetpath) {
FIXME(dosfs,"(0x%08lx,%s,%s),stub!\n",flags,devname,targetpath);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}