gps/GPSResources/tcpmp/common/win32/node_win32.c

527 lines
12 KiB
C
Executable File

/*****************************************************************************
*
* 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: node_win32.c 622 2006-01-31 19:02:53Z 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>
#if defined(TARGET_WINCE)
#define TWIN(a) L ## a
#define HKEY_ROOT HKEY_LOCAL_MACHINE
#else
#define TWIN(a) a
#define HKEY_ROOT HKEY_CURRENT_USER
#endif
void NOINLINE NodeBase(int Class, tchar_t* Base, int BaseLen)
{
tcscpy_s(Base,BaseLen,T("SOFTWARE\\"));
tcscat_s(Base,BaseLen,Context()->ProgramName);
if (Class)
{
tchar_t s[16];
FourCCToString(s,TSIZEOF(s),Class);
tcscat_s(Base,BaseLen,T("\\"));
tcscat_s(Base,BaseLen,s);
}
}
static bool_t LoadValue(HKEY Key,int Id,void* Data,int Size,int Type)
{
uint8_t Buffer[MAXDATA];
tchar_t Name[16];
DWORD RegType;
DWORD RegSize = sizeof(Buffer);
IntToString(Name,TSIZEOF(Name),Id,0);
if (RegQueryValueEx(Key, Name, 0, &RegType, Buffer, &RegSize) == ERROR_SUCCESS)
{
switch (Type)
{
case TYPE_BOOL:
if (RegType == REG_DWORD)
{
*(bool_t*)Data = *(DWORD*)Buffer;
return 1;
}
break;
case TYPE_RGB:
if (RegType == REG_DWORD)
{
*(rgbval_t*)Data = *(DWORD*)Buffer;
return 1;
}
break;
case TYPE_TICK:
if (RegType == REG_DWORD)
{
*(tick_t*)Data = *(DWORD*)Buffer;
return 1;
}
break;
case TYPE_INT:
case TYPE_HOTKEY:
if (RegType == REG_DWORD)
{
*(int*)Data = *(DWORD*)Buffer;
return 1;
}
break;
case TYPE_POINT:
case TYPE_RECT:
case TYPE_BINARY:
case TYPE_FRACTION:
if (RegType == REG_BINARY && Size<=MAXDATA)
{
memcpy(Data,Buffer,Size);
return 1;
}
break;
case TYPE_STRING:
if (RegType == REG_SZ && Size<=MAXDATA)
{
memcpy(Data,Buffer,Size);
return 1;
}
break;
}
}
return 0;
}
static void SaveValue(HKEY Key,int Id,const void* Data,int Size,int Type)
{
tchar_t Name[16];
IntToString(Name,TSIZEOF(Name),Id,0);
if (!Data)
RegDeleteValue(Key,Name);
else
{
DWORD RegType,RegSize,v;
RegType = REG_DWORD;
RegSize = sizeof(DWORD);
switch (Type)
{
case TYPE_BOOL:
v = *(bool_t*)Data;
break;
case TYPE_RGB:
v = *(int32_t*)Data;
break;
case TYPE_TICK:
v = *(tick_t*)Data;
break;
case TYPE_INT:
case TYPE_HOTKEY:
v = *(int*)Data;
break;
case TYPE_POINT:
case TYPE_RECT:
case TYPE_BINARY:
case TYPE_FRACTION:
RegType = REG_BINARY;
RegSize = Size;
break;
case TYPE_STRING:
RegType = REG_SZ;
RegSize = (DWORD)((tcslen((const tchar_t*)Data)+1)*sizeof(tchar_t));
break;
default:
return;
}
if (RegType == REG_DWORD)
Data = &v;
RegSetValueEx(Key, Name, 0, RegType, Data, RegSize);
}
}
bool_t NodeRegLoadValue(int Class, int Id, void* Data, int Size, int Type)
{
bool_t Result = 0;
HKEY Key;
tchar_t Base[256];
NodeBase(Class,Base,TSIZEOF(Base));
if (RegOpenKeyEx(HKEY_ROOT, Base, 0, KEY_READ, &Key) == ERROR_SUCCESS)
{
Result = LoadValue(Key,Id,Data,Size,Type);
RegCloseKey(Key);
}
return Result;
}
void NodeRegSaveValue(int Class, int Id, const void* Data, int Size, int Type)
{
DWORD Disp;
HKEY Key;
tchar_t Base[256];
NodeBase(Class,Base,TSIZEOF(Base));
if (RegCreateKeyEx(HKEY_ROOT, Base, 0, NULL, 0, KEY_READ|KEY_WRITE, NULL, &Key, &Disp) == ERROR_SUCCESS)
{
SaveValue(Key,Id,Data,Size,Type);
RegCloseKey(Key);
}
}
void NodeRegLoad(node* p)
{
if (p)
{
uint8_t Buffer[MAXDATA];
tchar_t Base[256];
datadef Type;
HKEY Key;
int No;
NodeBase(p->Class,Base,TSIZEOF(Base));
if (RegOpenKeyEx(HKEY_ROOT, Base, 0, KEY_READ, &Key) == ERROR_SUCCESS)
{
for (No=0;NodeEnum(p,No,&Type)==ERR_NONE;++No)
if ((Type.Flags & DF_SETUP) && !(Type.Flags & (DF_NOSAVE|DF_RDONLY)) &&
LoadValue(Key,Type.No,Buffer,Type.Size,Type.Type))
p->Set(p,Type.No,Buffer,Type.Size);
RegCloseKey(Key);
}
}
}
void NodeRegSave(node* p)
{
if (p)
{
uint8_t Buffer[MAXDATA];
datadef Type;
DWORD Disp;
HKEY Key;
tchar_t Base[256];
NodeBase(p->Class,Base,TSIZEOF(Base));
if (RegCreateKeyEx(HKEY_ROOT, Base, 0, NULL, 0, KEY_READ|KEY_WRITE, NULL, &Key, &Disp) == ERROR_SUCCESS)
{
int No;
int* i;
DWORD RegSize;
DWORD RegType;
tchar_t Name[64];
array List = {NULL};
RegSize = TSIZEOF(Name);
for (No=0;RegEnumValue(Key,No,Name,&RegSize,NULL,&RegType,NULL,NULL)==ERROR_SUCCESS;++No)
{
int Id = StringToInt(Name,0);
if (Id >= NODE_MAX_REGISTRY)
ArrayAppend(&List,&Id,sizeof(Id),256);
RegSize = TSIZEOF(Name);
}
for (No=0;NodeEnum(p,No,&Type)==ERR_NONE;++No)
if ((Type.Flags & DF_SETUP) && !(Type.Flags & (DF_NOSAVE|DF_RDONLY)))
{
int Result = p->Get(p,Type.No,Buffer,Type.Size);
if (Result == ERR_NONE || Result == ERR_NOT_SUPPORTED) // not supported settings should be still saved
{
for (i=ARRAYBEGIN(List,int);i!=ARRAYEND(List,int);++i)
if (*i == Type.No)
*i = 0;
SaveValue(Key,Type.No,Buffer,Type.Size,Type.Type);
}
}
for (i=ARRAYBEGIN(List,int);i!=ARRAYEND(List,int);++i)
if (*i)
SaveValue(Key,*i,NULL,0,TYPE_INT);
ArrayClear(&List);
RegCloseKey(Key);
}
}
}
void NodeRegLoadGlobal() {}
void NodeRegSaveGlobal() {}
void GetModulePath(tchar_t* Path,const tchar_t* Module);
void FindFiles(const tchar_t* Path, const tchar_t* Mask,void(*Process)(const tchar_t*,void*),void* Param);
static void PluginError(const tchar_t* FileName)
{
tchar_t Name[MAXPATH];
tchar_t Ext[MAXPATH];
SplitURL(FileName,NULL,0,NULL,0,Name,TSIZEOF(Name),Ext,TSIZEOF(Ext));
tcsupr(Name);
ShowError(0,ERR_ID,ERR_NOT_COMPATIBLE,Name);
}
void* NodeLoadModule(const tchar_t* Path,int* Id,void** AnyFunc,void** Db)
{
HMODULE Module;
int Error = 0;
#if !defined(TARGET_WINCE)
int OldMode = SetErrorMode(SEM_NOOPENFILEERRORBOX| SEM_FAILCRITICALERRORS);
#endif
Module = LoadLibrary(Path);
if (!Module)
{
Error = GetLastError();
if (Error == ERROR_NOT_ENOUGH_MEMORY || Error == ERROR_OUTOFMEMORY)
{
NodeHibernate();
Module = LoadLibrary(Path);
if (!Module)
Error = GetLastError();
}
}
Context()->LoadModule = Module;
#if !defined(TARGET_WINCE)
SetErrorMode(OldMode);
#endif
if (Module)
{
FARPROC Func = GetProcAddress(Module,TWIN("DLLRegister"));
if (!Func)
Func = GetProcAddress(Module,TWIN("_DLLRegister@4"));
if (Func)
{
int Result;
if (AnyFunc)
*(FARPROC*)AnyFunc = Func; // set before calling DLLRegister
Result = ((int(*)(int))Func)(CONTEXT_VERSION);
if (Result != ERR_NONE)
{
Func = NULL;
if (AnyFunc)
*(FARPROC*)AnyFunc = NULL;
if (Result == ERR_NOT_COMPATIBLE)
PluginError(Path);
}
}
if (!Func)
{
FreeLibrary(Module);
Module = NULL;
}
}
else
if (Error == ERROR_NOT_ENOUGH_MEMORY || Error == ERROR_OUTOFMEMORY)
ShowOutOfMemory();
else
PluginError(Path);
return Module;
}
void NodeFreeModule(void* Module,void* Db)
{
if (Module)
{
FARPROC UnRegister = GetProcAddress(Module,TWIN("DLLUnRegister"));
if (!UnRegister)
UnRegister = GetProcAddress(Module,TWIN("_DLLUnRegister@4"));
if (UnRegister)
((void(*)())UnRegister)();
FreeLibrary(Module);
}
}
static void AddModule(const tchar_t* Path,HKEY* Key)
{
int64_t Date = FileDate(Path);
if (Date != -1)
{
int64_t Value;
DWORD RegType;
DWORD RegSize = sizeof(Value);
bool_t Changed = *Key==NULL || RegQueryValueEx(*Key, Path, 0, &RegType, (PBYTE)&Value, &RegSize) != ERROR_SUCCESS || Value != Date;
NodeAddModule(Path,0,Date,Changed,0);
if (Changed && *Key) // save file stamp to registry
RegSetValueEx(*Key, Path, 0, REG_BINARY, (PBYTE)&Date, sizeof(Date));
}
}
static void FindPlugins(array* List)
{
tchar_t* s;
tchar_t Name[64];
tchar_t Path[MAXPATH];
tchar_t Path2[MAXPATH];
DWORD RegSize,RegType,NameSize,Disp;
HKEY Key,KeyStamp;
int No,Class;
NodeBase(0,Path,TSIZEOF(Path));
tcscat_s(Path,TSIZEOF(Path),T("\\DLLStamp"));
if (RegCreateKeyEx(HKEY_ROOT, Path, 0, NULL, 0, KEY_READ|KEY_WRITE, NULL, &KeyStamp, &Disp) != ERROR_SUCCESS)
KeyStamp = NULL;
// add plugins in exe directory
GetModulePath(Path,NULL);
FindFiles(Path,T("*.plg"),AddModule,&KeyStamp);
// maybe exe is in different directory as common.dll and other plugins (mostly with debugging)
GetModulePath(Path2,T("common.dll"));
if (tcsicmp(Path2,Path)!=0)
FindFiles(Path2,T("*.plg"),AddModule,&KeyStamp);
// additional plugins
NodeBase(0,Path,TSIZEOF(Path));
tcscat_s(Path,TSIZEOF(Path),T(".Plugins"));
if (RegOpenKeyEx(HKEY_ROOT, Path, 0, KEY_READ, &Key) == ERROR_SUCCESS)
{
for (No=0;;++No)
{
NameSize = TSIZEOF(Name);
RegSize = sizeof(Path);
if (RegEnumValue(Key,No,Name,&NameSize,NULL,&RegType,(LPBYTE)Path,&RegSize)!=ERROR_SUCCESS)
break;
if (RegType == REG_SZ)
AddModule(Path,&KeyStamp);
}
RegCloseKey(Key);
}
if (KeyStamp)
{
// delete unused stamps
ArrayClear(List);
RegSize = TSIZEOF(Path);
for (No=0;RegEnumValue(KeyStamp,No,Path,&RegSize,NULL,NULL,NULL,NULL)==ERROR_SUCCESS;++No)
{
if (!NodeFindModule(Path,0))
ArrayAppend(List,Path,(tcslen(Path)+1)*sizeof(tchar_t),256);
RegSize = TSIZEOF(Path);
}
for (s=ARRAYBEGIN(*List,tchar_t);s!=ARRAYEND(*List,tchar_t);s+=tcslen(s)+1)
RegDeleteValue(KeyStamp,s);
RegCloseKey(KeyStamp);
}
ArrayClear(List);
NodeBase(0,Path,TSIZEOF(Path));
if (RegOpenKeyEx(HKEY_ROOT, Path, 0, KEY_READ, &Key) == ERROR_SUCCESS)
{
RegSize = TSIZEOF(Name);
for (No=0;RegEnumKeyEx(Key,No,Name,&RegSize,NULL,NULL,NULL,NULL)==ERROR_SUCCESS;++No)
{
if (tcslen(Name)==4)
{
Class = StringToFourCC(Name,0);
ArrayAppend(List,&Class,sizeof(Class),128);
}
RegSize = TSIZEOF(Name);
}
RegCloseKey(Key);
}
}
static void LoadValueString(HKEY Key,int Class,int Id)
{
uint8_t Buffer[MAXDATA];
if (LoadValue(Key,Id,Buffer,sizeof(Buffer),TYPE_STRING))
StringAdd(1,Class,Id,(tchar_t*)Buffer);
}
void Plugins_Init()
{
tchar_t Path[MAXPATH];
array List = {NULL};
nodedef Def;
int* i;
FindPlugins(&List);
for (i=ARRAYBEGIN(List,int);i!=ARRAYEND(List,int);++i)
{
int Class = *i;
HKEY Key;
tchar_t Base[256];
NodeBase(Class,Base,TSIZEOF(Base));
if (RegOpenKeyEx(HKEY_ROOT, Base, 0, KEY_READ, &Key) == ERROR_SUCCESS)
{
if (LoadValue(Key,NODE_MODULE_PATH,Path,sizeof(Path),TYPE_STRING) && NodeFindModule(Path,0))
{
memset(&Def,0,sizeof(Def));
Def.Class = Class;
Def.Flags = 0;
Def.ParentClass = 0;
Def.Priority = PRI_DEFAULT;
LoadValue(Key,NODE_PARENT,&Def.ParentClass,sizeof(int),TYPE_INT);
LoadValue(Key,NODE_PRIORITY,&Def.Priority,sizeof(int),TYPE_INT);
LoadValue(Key,NODE_FLAGS,&Def.Flags,sizeof(int),TYPE_INT);
LoadValueString(Key,Class,NODE_NAME);
LoadValueString(Key,Class,NODE_CONTENTTYPE);
LoadValueString(Key,Class,NODE_EXTS);
LoadValueString(Key,Class,NODE_PROBE);
NodeLoadClass(&Def,Path,0);
}
RegCloseKey(Key);
}
}
ArrayClear(&List);
}
void Plugins_Done()
{
}
#endif