📄 file_win32.c
字号:
/*****************************************************************************
*
* This program is free software ; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: file_win32.c 202 2005-01-25 01:27:33Z picard $
*
* BetaPlayer Core
* Copyright (c) 2004 Gabor Kovacs
*
****************************************************************************/
#include "../stdafx.h"
#if defined(_WIN32)
#ifndef STRICT
#define STRICT
#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#ifndef ERROR_DEVICE_REMOVED
#define ERROR_DEVICE_REMOVED 1617L
#endif
typedef struct filestream
{
stream VMT;
tchar_t URL[MAXPATH];
HANDLE Handle;
int Length;
int Pos;
bool_t Silent;
bool_t Create;
HANDLE Find;
const tchar_t* Exts;
bool_t ExtFilter;
WIN32_FIND_DATA FindData;
} filestream;
static int EnumType( void* p, int No, datadef* Param )
{
return NodeEnumType(&No,Param,NodeParams,StreamParams,NULL);
}
static int Get( filestream* p, int No, void* Data, int Size )
{
int Result = ERR_INVALID_PARAM;
switch (No)
{
case NODE_ID: GETVALUE(FILE_ID,int); break;
case STREAM_URL: GETSTRING(p->URL); break;
case STREAM_SILENT: GETVALUE(p->Silent,bool_t); break;
case STREAM_LENGTH: GETVALUECOND(p->Length,int,p->Length>=0); break;
case STREAM_CREATE: GETVALUE(p->Create,bool_t); break;
}
return Result;
}
static int Open( filestream* p, const tchar_t* URL, bool_t ReOpen )
{
if (p->Handle)
CloseHandle(p->Handle);
p->Handle = 0;
p->Length = -1;
if (!ReOpen)
p->URL[0] = 0;
else
Sleep(200);
if (URL && URL[0])
{
HANDLE Handle;
Handle = CreateFile(URL,p->Create?GENERIC_WRITE:GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,p->Create?CREATE_ALWAYS:OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,NULL);
if (Handle == INVALID_HANDLE_VALUE)
{
if (!ReOpen && !p->Silent)
NodeError(NULL,ERR_ID,ERR_FILE_NOT_FOUND,URL);
return ERR_FILE_NOT_FOUND;
}
TcsNCpy(p->URL,URL,MAXPATH);
p->Handle = Handle;
p->Length = GetFileSize(Handle,NULL);
if (ReOpen)
p->Pos = SetFilePointer(p->Handle,p->Pos,NULL,FILE_BEGIN);
else
{
p->Pos = 0;
#if defined(_WIN32_WCE)
// wince shortcut handling
if (p->Length < MAXPATH)
{
uint32_t Readed;
char ShortCut[MAXPATH];
tchar_t URL[MAXPATH];
char* ch;
if (ReadFile(p->Handle,ShortCut,p->Length,&Readed,NULL))
{
ShortCut[Readed] = 0;
for (ch=ShortCut;*ch && *ch!='#';++ch)
if (*ch < '0' || *ch > '9')
break;
if (ch[0] == '#' && ch[1]!=':')
{
char* Head = ++ch;
char* Tail;
if (*ch == '"')
{
Head++;
ch = strchr(ch+1,'"');
if (ch)
*(ch++) = 0;
}
if (ch)
{
Tail = strchr(ch,13);
if (Tail)
{
*Tail = 0;
ch = Tail+1;
}
if (!strchr(ch,13))
{
ch = strchr(ch,10);
if (!ch || !strchr(ch+1,10))
{
if (ch) *ch = 0;
StrToTcs(URL,Head,MAXPATH);
return Open(p,URL,0);
}
}
}
}
p->Pos = SetFilePointer(p->Handle,0,NULL,FILE_BEGIN);
}
}
#endif
}
}
return ERR_NONE;
}
static int Set( filestream* p, int No, const void* Data, int Size )
{
int Result = ERR_INVALID_PARAM;
switch (No)
{
case STREAM_MIME:
if (Data && TcsICmp(Data,T("file"))==0)
Result = ERR_NONE;
break;
case STREAM_SILENT: SETVALUE(p->Silent,bool_t,ERR_NONE); break;
case STREAM_CREATE: SETVALUE(p->Create,bool_t,ERR_NONE); break;
case STREAM_URL:
Result = Open(p,(const tchar_t*)Data,0);
break;
}
return Result;
}
static int Read(filestream* p,void* Data,int Size)
{
uint32_t Readed;
DWORD Error;
//Sleep(100);
//DEBUG_MSG3(-1,"FileRead: %08x %08x %d",p->Pos,SetFilePointer(p->Handle,0,NULL,FILE_CURRENT),Size);
if (ReadFile(p->Handle,Data,Size,&Readed,NULL))
{
//DEBUG_MSG2(T("READ pos:%d len:%d"),p->Pos,Readed);
p->Pos += Readed;
return Readed;
}
Error = GetLastError();
//DEBUG_MSG2(T("READ pos:%d error:%d"),p->Pos,Error);
if (Error == ERROR_DEVICE_REMOVED || Error == ERROR_INVALID_HANDLE || Error == ERROR_GEN_FAILURE)
Open(p,p->URL,1);
return -1;
}
static int Seek(filestream* p,int Pos,int SeekMode)
{
int ReTry=3;
int Result;
DWORD Error;
switch (SeekMode)
{
default:
case SEEK_SET: SeekMode = FILE_BEGIN; break;
case SEEK_CUR: SeekMode = FILE_CURRENT; break;
case SEEK_END: SeekMode = FILE_END; break;
}
do
{
//DEBUG_MSG3(-1,"FileSeek: %08x %08x %d",SetFilePointer(p->Handle,0,NULL,FILE_CURRENT),Pos,SeekMode);
Result = SetFilePointer(p->Handle,Pos,NULL,SeekMode);
if (Result != -1)
{
p->Pos = Result;
break;
}
Error = GetLastError();
if (Error != ERROR_DEVICE_REMOVED && Error != ERROR_INVALID_HANDLE)
break;
Open(p,p->URL,1);
}
while (--ReTry>0);
return Result;
}
static int Write(filestream* p,const void* Data,int Size)
{
DWORD Written;
if (WriteFile(p->Handle,Data,Size,&Written,NULL))
{
p->Pos += Written;
return Written;
}
return -1;
}
static int EnumDir(filestream* p,const tchar_t* URL,const tchar_t* Exts,bool_t ExtFilter,streamdir* Item)
{
if (URL)
{
DWORD Attrib;
tchar_t Path[MAXPATH];
p->Exts = Exts;
p->ExtFilter = ExtFilter;
if (p->Find != INVALID_HANDLE_VALUE)
{
FindClose(p->Find);
p->Find = INVALID_HANDLE_VALUE;
}
stprintf(Path,T("%s\\*.*"),URL);
Attrib = GetFileAttributes(URL);
if (Attrib != (DWORD)-1 && !(Attrib & FILE_ATTRIBUTE_DIRECTORY))
return ERR_NOT_DIRECTORY;
p->Find = FindFirstFile( Path, &p->FindData );
}
Item->FileName[0] = 0;
while (!Item->FileName[0] && p->Find != INVALID_HANDLE_VALUE)
{
if (tcscmp(p->FindData.cFileName,T("."))!=0 && tcscmp(p->FindData.cFileName,T(".."))!=0)
{
FILETIME Local;
TcsNCpy(Item->FileName,p->FindData.cFileName,MAXPATH);
if (FileTimeToLocalFileTime(&p->FindData.ftLastWriteTime,&Local))
Item->Date = ((int64_t)Local.dwHighDateTime << 32)|Local.dwLowDateTime;
else
Item->Date = -1;
if (p->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
Item->Size = -1;
else
{
Item->Size = p->FindData.nFileSizeLow;
Item->Type = CheckExts(Item->FileName,p->Exts);
if (!Item->Type && p->ExtFilter)
Item->FileName[0] = 0; // skip
}
}
if (!FindNextFile(p->Find,&p->FindData))
{
FindClose(p->Find);
p->Find = INVALID_HANDLE_VALUE;
}
}
return Item->FileName[0] ? ERR_NONE : ERR_END_OF_FILE;
}
static void* Create( filestream* p )
{
filestream* i = (filestream*) CAlloc(sizeof(filestream),1);
if (i)
{
i->VMT = p->VMT;
i->Find = INVALID_HANDLE_VALUE;
}
return i;
}
static void Delete( filestream* p )
{
Open(p,NULL,0);
if (p->Find != INVALID_HANDLE_VALUE)
FindClose(p->Find);
Free(p);
}
static filestream File =
{
EnumType,
Get,
Set,
Create,
Delete,
Read,
Seek,
EnumDir,
Write,
};
void File_Init()
{
File.Find = INVALID_HANDLE_VALUE;
File.Create = 0;
File.Silent = 0;
NodeRegister((node*)&File,PRI_MINIMUM);
}
void File_Done()
{
NodeUnRegister((node*)&File);
}
stream* FileCreate()
{
return Create(&File);
}
int FileDate( const tchar_t* Path )
{
int Date = -1;
HANDLE Find;
SYSTEMTIME Time;
WIN32_FIND_DATA FindData;
Find = FindFirstFile( Path, &FindData );
if (Find != INVALID_HANDLE_VALUE)
{
if (FileTimeToSystemTime(&FindData.ftCreationTime,&Time))
Date = (int)Time.wYear*10000+(int)Time.wMonth*100+(int)Time.wDay;
FindClose(Find);
}
return Date;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -