⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 file_win32.c

📁 大名鼎鼎的CE下播放软件,TCPPMP的源代码!!!2410下可以流畅的解QVGA的H264,MPEG4等格式.
💻 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 543 2006-01-07 22:06:24Z picard $
 *
 * The Core Pocket Media Player
 * Copyright (c) 2004-2005 Gabor Kovacs
 *
 ****************************************************************************/

#include "../common.h"

#if defined(TARGET_WIN32) || defined(TARGET_WINCE)

#ifndef STRICT
#define STRICT
#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#ifndef ERROR_INVALID_DRIVE_OBJECT
#define ERROR_INVALID_DRIVE_OBJECT		4321L
#endif

#ifndef ERROR_DEVICE_NOT_AVAILABLE
#define ERROR_DEVICE_NOT_AVAILABLE		4319L
#endif

#ifndef ERROR_DEVICE_REMOVED
#define ERROR_DEVICE_REMOVED            1617L
#endif

typedef struct filestream
{
	stream Stream;
	tchar_t URL[MAXPATH];
	HANDLE Handle;
	filepos_t Length;
	filepos_t Pos;
	bool_t Silent;
	bool_t Create;

	HANDLE Find;
	const tchar_t* Exts;
	bool_t ExtFilter;
	WIN32_FIND_DATA FindData;

} filestream;

static int Get(filestream* p, int No, void* Data, int Size)
{
	int Result = ERR_INVALID_PARAM;
	switch (No)
	{
	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)
				ShowError(0,ERR_ID,ERR_FILE_NOT_FOUND,URL);
			return ERR_FILE_NOT_FOUND;
		}

		tcscpy_s(p->URL,TSIZEOF(p->URL),URL);
		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(TARGET_WINCE)

			// wince shortcut handling

			if (p->Length < MAXPATH && !p->Create)
			{
				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 (!IsDigit(*ch))
							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,TSIZEOF(URL),Head);
									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_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_DEVICE_NOT_AVAILABLE ||
		Error == ERROR_INVALID_HANDLE || 
		Error == ERROR_INVALID_DRIVE_OBJECT ||
		Error == ERROR_DEV_NOT_EXIST ||
		Error == ERROR_GEN_FAILURE)
		Open(p,p->URL,1);

	return -1;
}

static int ReadBlock(filestream* p,block* Block,int Ofs,int Size)
{
	return Read(p,(char*)(Block->Ptr+Ofs),Size);
}

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_s(Path,TSIZEOF(Path),T("%s\\*.*"),URL);

		Attrib = GetFileAttributes(URL);
		if (URL[0] && Attrib == (DWORD)-1)
			return ERR_FILE_NOT_FOUND;

		if (!(Attrib & FILE_ATTRIBUTE_DIRECTORY))
			return ERR_NOT_DIRECTORY;

		p->Find = FindFirstFile(Path, &p->FindData);
	}

	Item->FileName[0] = 0;
	Item->DisplayName[0] = 0;

	while (!Item->FileName[0] && p->Find != INVALID_HANDLE_VALUE)
	{
		if (p->FindData.cFileName[0]!='.') // skip unix/mac hidden files and . .. directory entries
		{
			FILETIME Local;

			tcscpy_s(Item->FileName,TSIZEOF(Item->FileName),p->FindData.cFileName);

			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;
		}
	}

	if (!Item->FileName[0])
	{
		if (p->Find != INVALID_HANDLE_VALUE)
		{
			FindClose(p->Find);
			p->Find = INVALID_HANDLE_VALUE;
		}
		return ERR_END_OF_FILE;
	}

	return ERR_NONE;
}

static int Create(filestream* p)
{
	p->Stream.Get = (nodeget)Get,
	p->Stream.Set = (nodeset)Set,
	p->Stream.Read = Read;
	p->Stream.ReadBlock = ReadBlock;
	p->Stream.Write = Write;
	p->Stream.Seek = Seek;
	p->Stream.EnumDir = EnumDir;
	p->Find = INVALID_HANDLE_VALUE;
	return ERR_NONE;
}

static void Delete(filestream* p)
{
	Open(p,NULL,0);
	if (p->Find != INVALID_HANDLE_VALUE)
		FindClose(p->Find);
}

static const nodedef File =
{
	sizeof(filestream),
	FILE_ID,
	STREAM_CLASS,
	PRI_MINIMUM,
	(nodecreate)Create,
	(nodedelete)Delete,
};

void File_Init()
{
	NodeRegisterClass(&File);
}

void File_Done()
{
	NodeUnRegisterClass(FILE_ID);
}

stream* FileCreate(const tchar_t* Path)
{
	// create fake stream
	filestream* p = (filestream*)malloc(sizeof(filestream));
	memset(p,0,sizeof(filestream));
	p->Stream.Class = FILE_ID;
	p->Stream.Enum = (nodeenum)StreamEnum;
	Create(p);
	return &p->Stream;
}

void FileRelease(stream* p)
{
	if (p)
	{
		Delete((filestream*)p);
		free(p);
	}
}

bool_t FileExits(const tchar_t* Path)
{
	return GetFileAttributes(Path) != (DWORD)-1;
}

int64_t FileDate(const tchar_t* Path)
{
	int64_t Date = -1;
	HANDLE Find;
	SYSTEMTIME Time;
	WIN32_FIND_DATA FindData;

	Find = FindFirstFile(Path, &FindData);
	if (Find != INVALID_HANDLE_VALUE)
	{
		if (FileTimeToSystemTime(&FindData.ftLastWriteTime,&Time))
			Date = ((((((int64_t)Time.wYear*100+(int64_t)Time.wMonth)*100+(int64_t)Time.wDay)*100+
			       (int64_t)Time.wHour)*100+(int64_t)Time.wMinute)*100+(int64_t)Time.wSecond)*1000+(int64_t)Time.wMilliseconds;
		FindClose(Find);
	}
	return Date;
}

#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -