?? misc.c
字號:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*++
Module Name:
misc.c
Abstract:
This file contains miscellaneous routines.
Revision History:
--*/
#include "fatfs.h"
#ifndef _PREFAST_
#pragma warning(disable: 4068) // Disable pragma warnings
#endif
// 計算傳入參數n應該是2的多少次冪,即2^x=n,返回值為n
int Log2(unsigned int n)
{
int l;
if ((n & n-1) != 0)
return -1; // n is not a power of 2
for (l = -1 ; n ; ++l)
n >>= 1;
return l;
}
void InitList(PDLINK pdl)
{
pdl->next = pdl->prev = pdl;
}
int ListIsEmpty(PDLINK pdl)
{
return pdl->next == pdl;
}
void AddItem(PDLINK pdlIns, PDLINK pdlNew)
{
pdlNew->prev = pdlIns;
(pdlNew->next = pdlIns->next)->prev = pdlNew;
pdlIns->next = pdlNew;
}
void RemoveItem(PDLINK pdl)
{
pdl->prev->next = pdl->next;
pdl->next->prev = pdl->prev;
}
/* pchtoi - convert decimal string to integer
*
* ENTRY
* pch - pointer to CHAR (not WCHAR or TCHAR) array
* cch - number of characters required (0 if any number allowed)
*
* EXIT
* value of number, -1 if error (numbers < 0 are not supported)
*/
int pchtoi(PCHAR pch, int cch)
{
int i = 0;
while (TRUE) {
if (*pch < '0' || *pch > '9')
break;
i = i * 10 + (*pch++ - '0');
if (cch) {
if (--cch == 0)
break;
}
}
if (cch)
i = -1;
return i;
}
/* itopch - convert integer to decimal string
*
* ENTRY
* i - integer to convert (numbers < 0 or > 9999 are not supported)
* pch - pointer to CHAR (not WCHAR or TCHAR) array
*
* EXIT
* number of characters in string; note the string is NOT null-terminated
*/
#pragma prefast(disable: 394, "Private implementation for not null-terminated string.")
int itopch(int i, PCHAR pch)
{
int c, q;
CONST int *piDiv;
static CONST int iDiv[] = {10000,1000,100,10,1};
c = 0; // total number of digits output
if (i >= 0 && i < iDiv[0]) {
piDiv = &iDiv[1];
do {
if (c != 0 || *piDiv == 1 || i >= *piDiv) {
q = i / (*piDiv);
*pch++ = '0' + q;
i -= q * (*piDiv);
c++;
}
} while (*piDiv++ != 1);
}
return c;
}
#pragma prefast(pop)
/* SetBitArray - set bit in bit array
*
* ENTRY
* pdwBitArray - pointer to bit array
* i - 0-based position of bit to set (i is range-checked)
*
* EXIT
* None
*
* NOTES
* Bit arrays start with two special DWORDs that are not part of
* of the actual array of bits. The first DWORD is initialized to
* the number of bits that can be held, and the second DWORD keeps track
* of the total number of SET bits.
*
* You can either allocate and initialize the bit array yourself, or
* call CreateBitArray; the latter is a macro in FATFS.H that creates a
* temporary array that's automatically freed upon leaving the current
* scope.
*/
void SetBitArray(PDWORD pdwBitArray, int i)
{
DWORD mask;
PDWORD pdw;
if (i >= 0 && (DWORD)i < pdwBitArray[0]) {
mask = 1 << (i % 32);
pdw = pdwBitArray + i/32+2;
if ((*pdw & mask) == 0)
pdwBitArray[1]++;
*pdw |= mask;
}
}
#ifdef LATER // no one needs this function yet -JTP
/* ClearBitArray - clear bit in bit array
*
* ENTRY
* pdwBitArray - pointer to bit array
* i - 0-based position of bit to clear (i is range-checked)
*
* EXIT
* None
*
* NOTES
* Bit arrays start with two special DWORDs that are not part of
* of the actual array of bits. The first DWORD is initialized to
* the number of bits that can be held, and the second DWORD keeps track
* of the total number of SET bits.
*
* You can either allocate and initialize the bit array yourself, or
* call CreateBitArray; the latter is a macro in FATFS.H that creates a
* temporary array that's automatically freed upon leaving the current
* scope.
*/
void ClearBitArray(PDWORD pdwBitArray, int i)
{
DWORD mask;
PDWORD pdw;
if (i >= 0 && (DWORD)i < pdwBitArray[0]) {
mask = 1 << (i % 32);
pdw = pdwBitArray + i/32+2;
if ((*pdw & mask) != 0) {
ASSERT(pdwBitArray[1] != 0);
pdwBitArray[1]--;
}
*pdw &= ~mask;
}
}
#endif
/* TestBitArray - test bit in bit array
*
* ENTRY
* pdwBitArray - pointer to bit array
* i - 0-based position of bit to test (i is range-checked)
*
* EXIT
* TRUE if bit is set, FALSE if bit is not set
*
* NOTES
* Bit arrays start with two special DWORDs that are not part of
* of the actual array of bits. The first DWORD is initialized to
* the number of bits that can be held, and the second DWORD keeps track
* of the total number of SET bits.
*
* You can either allocate and initialize the bit array yourself, or
* call CreateBitArray; the latter is a macro in FATFS.H that creates a
* temporary array that's automatically freed upon leaving the current
* scope.
*/
BOOL TestBitArray(PDWORD pdwBitArray, int i)
{
ASSERT(i >= 0 && (DWORD)i < pdwBitArray[0]);
return i >= 0 && (DWORD)i < pdwBitArray[0]?
(pdwBitArray[i/32+2] & (1 << (i % 32))) != 0 : FALSE;
}
/* DOSTimeToFileTime - convert DOS format time to NT FILETIME
*
* FAT files use a bit-packed date & time format versus NT's 64bit integer
* time format.
*
* DOS Date format: YYYY YYYM MMMD DDDD (Year since 1980, Month, Day of month)
* DOS Time format: HHHH HMMM MMMS SSSS (Hour, Minute, Seconds/2 (0-29))
*
* ENTRY
* dosDate - date in DOS bitpacked format
* dosTime - time in DOS bitpacked format
* tenMSec - milliseconds / 10
* pft - pointer to FILETIME structure to fill in
*
* EXIT
* TRUE if successful, FALSE if error
*/
BOOL DOSTimeToFileTime(WORD dosDate, WORD dosTime, BYTE tenMSec, PFILETIME pft)
{
FILETIME ft;
SYSTEMTIME st;
WORD wMSec = tenMSec * 10;
st.wYear = (dosDate >> 9) + 1980;
st.wMonth = (dosDate >> 5) & 0xf;
st.wDayOfWeek = 0;
st.wDay = dosDate & 0x1f;
st.wHour = dosTime >> 11;
st.wMinute = (dosTime >> 5) & 0x3f;
st.wSecond = (dosTime & 0x1f) << 1;
// The ms field can range from 0 - 1999 ms inclusive.
// Use if statements to avoid expensive division operation.
if (wMSec >= 2000) {
DEBUGMSG(ZONE_ERRORS,(DBGTEXT("FATFS!DOSTimeToFileTime failed: invalid milliseconds value: %d.\r\n"), wMSec));
return FALSE;
} else if (wMSec >= 1000) {
st.wSecond++;
st.wMilliseconds = wMSec - 1000;
} else {
st.wMilliseconds = wMSec;
}
DEBUGMSG(ZONE_STREAMS && ZONE_LOGIO,(DBGTEXT("FATFS!DOSTimeToFileTime: local file system time: y=%d,m=%d,d=%d,h=%d,m=%d,s=%d\r\n"), st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond));
if (SystemTimeToFileTime(&st, &ft)) {
DEBUGMSG(ZONE_STREAMS && ZONE_LOGIO,(DBGTEXT("FATFS!DOSTimeToFileTime: local file time: %08x,%08x\r\n"), ft.dwLowDateTime, ft.dwHighDateTime));
if (LocalFileTimeToFileTime(&ft, pft)) {
DEBUGMSG(ZONE_STREAMS && ZONE_LOGIO,(DBGTEXT("FATFS!DOSTimeToFileTime: file time: %08x,%08x\r\n"), pft->dwLowDateTime, pft->dwHighDateTime));
return TRUE;
}
}
return FALSE;
}
/* FileTimeToDOSTime - convert NT FILETIME to DOS format time
*
* FAT files use a bit-packed date & time format versus NT's 64bit integer
* time format.
*
* DOS Date format: YYYY YYYM MMMD DDDD (Year since 1980, Month, Day of month)
* DOS Time format: HHHH HMMM MMMS SSSS (Hour, Minute, Seconds/2 (0-29))
*
* ENTRY
* dosDate - date in DOS bitpacked format
* dosTime - time in DOS bitpacked format
* tenMSec - milliseconds / 10
* pft - pointer to FILETIME structure to fill in
*
* EXIT
* TRUE if successful, FALSE if error
*/
BOOL FileTimeToDOSTime(PFILETIME pft, PWORD pdosDate, PWORD pdosTime, PBYTE ptenMSec)
{
FILETIME ft;
SYSTEMTIME st;
ASSERT(pdosDate);
DEBUGMSG(ZONE_STREAMS && ZONE_LOGIO,(DBGTEXT("FATFS!FileTimeToDOSTime: file time: %08x,%08x\r\n"), pft->dwLowDateTime, pft->dwHighDateTime));
FileTimeToLocalFileTime(pft, &ft);
DEBUGMSG(ZONE_STREAMS && ZONE_LOGIO,(DBGTEXT("FATFS!FileTimeToDOSTime: local file time: %08x,%08x\n"), ft.dwLowDateTime, ft.dwHighDateTime));
FileTimeToSystemTime(&ft, &st);
DEBUGMSG(ZONE_STREAMS && ZONE_LOGIO,(DBGTEXT("FATFS!FileTimeToDOSTime: local file system time: y=%d,m=%d,d=%d,h=%d,m=%d,s=%d\n"), st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond));
*pdosDate = ((st.wYear-1980) << 9) | (st.wMonth << 5) | (st.wDay);
if (pdosTime)
*pdosTime = (st.wHour << 11) | (st.wMinute << 5) | (st.wSecond >> 1);
if (ptenMSec)
*ptenMSec = (st.wMilliseconds / 10);
return TRUE;
}
#ifdef OLD_IOCTLS // defunct code
/* SetSizePointer - update a SIZEPTR structure as appropriate
*
* For consistency, certain APIs (like IOCTLs) pass us DWORD/PVOID pairs,
* where the DWORD represents the number of elements in an array, and the
* PVOID is the address of the array. Furthermore, if the caller doesn't
* know how many elements are in the array yet, then the convention is for
* the caller to pass us a NULL PVOID, and we'll set the DWORD to the
* number of elements. Then the caller can allocate the appropriate amount
* of memory and call us again with a non-NULL PVOID.
*
* ENTRY
* psp - pointer to a DWORD/PVOID pair
* cb - size of each element in bytes
* c - count of elements
* pSrc - pointer to caller's buffer, NULL if none
* hproc - handle to caller's process, NULL if current process
*
* EXIT
* None; either the caller's PVOID buffer is filled in, or the DWORD
* size is filled in. The calling function should have a try/except in
* place.
*/
void SetSizePointer(PSIZEPTR psp, DWORD cb, DWORD c, PVOID pSrc, HANDLE hProc)
{
if (psp->p == NULL) {
psp->c = c; // just return number of elements to caller
} else {
PVOID pDst = psp->p;
if (hProc)
pDst = MapPtrToProcess(pDst, hProc);
if (c > psp->c) // if there are more elements than caller wants,
c = psp->c; // reduce it
memcpy(pDst, pSrc, cb * c);
}
}
#endif // OLD_IOCTLS
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -