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

450 lines
11 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: association_win32.c 603 2006-01-19 13:00:33Z picard $
*
* The Core Pocket Media Player
* Copyright (c) 2004-2005 Gabor Kovacs
*
****************************************************************************/
#include "../common.h"
#if defined(TARGET_WIN32) || defined(TARGET_WINCE)
#define REG_ASSOCIATIONS 0x2C00
#ifndef STRICT
#define STRICT
#endif
#include <windows.h>
static void SetURLProtocol(const tchar_t* Base)
{
const tchar_t* Name = T("URL Protocol");
tchar_t Value[MAXPATH];
DWORD RegType;
DWORD RegSize;
DWORD Disp=0;
HKEY Key;
if (RegCreateKeyEx(HKEY_CLASSES_ROOT, Base, 0, NULL, 0, KEY_READ|KEY_WRITE, NULL, &Key, &Disp) == ERROR_SUCCESS)
{
RegSize=sizeof(Value);
if (RegQueryValueEx(Key, NULL, 0, &RegType, (LPBYTE)Value, &RegSize) != ERROR_SUCCESS ||
tcsnicmp(Value,T("URL:"),4)!=0)
{
stprintf_s(Value,TSIZEOF(Value),T("URL:%s protocol"),Base);
RegSetValueEx(Key, NULL, 0, REG_SZ, (LPBYTE)Value, (DWORD)((tcslen(Value)+1)*sizeof(tchar_t)));
}
RegSize=sizeof(Value);
if (RegQueryValueEx(Key, Name, 0, &RegType, (LPBYTE)Value, &RegSize) != ERROR_SUCCESS)
RegSetValueEx(Key, Name, 0, REG_SZ, (LPBYTE)T(""), sizeof(tchar_t));
RegCloseKey(Key);
}
}
static void SetEditFlags(const tchar_t* Base,DWORD Value)
{
DWORD Disp=0;
HKEY Key;
if (RegCreateKeyEx(HKEY_CLASSES_ROOT, Base, 0, NULL, 0, KEY_READ|KEY_WRITE, NULL, &Key, &Disp) == ERROR_SUCCESS)
{
RegSetValueEx(Key, T("EditFlags"), 0, REG_DWORD, (LPBYTE)&Value, sizeof(Value));
RegCloseKey(Key);
}
//BrowserFlags=8 (?)
}
static void SetReg(const tchar_t* Base,const tchar_t* New,bool_t State)
{
tchar_t Old[MAXPATH];
tchar_t Backup[MAXPATH];
DWORD Disp=0;
HKEY Key;
DWORD RegSize;
DWORD RegType;
stprintf_s(Backup,TSIZEOF(Backup),T("%s.bak"),Context()->ProgramName);
if (RegOpenKeyEx(HKEY_CLASSES_ROOT, Base, 0, KEY_READ|KEY_WRITE, &Key) == ERROR_SUCCESS)
{
RegSize=sizeof(Old);
if (RegQueryValueEx(Key, NULL, 0, &RegType, (LPBYTE)Old, &RegSize) != ERROR_SUCCESS)
Old[0] = 0;
if (tcsicmp(Old,New)!=0)
{
if (State)
{
RegSetValueEx(Key, NULL, 0, REG_SZ, (LPBYTE)New, (DWORD)((tcslen(New)+1)*sizeof(tchar_t)));
RegSetValueEx(Key, Backup, 0, REG_SZ, (LPBYTE)Old, RegSize);
}
}
else
if (!State)
{
RegSize = sizeof(Old);
if (RegQueryValueEx(Key, Backup, 0, &RegType, (LPBYTE)Old, &RegSize) == ERROR_SUCCESS)
{
RegSetValueEx(Key, NULL, 0, REG_SZ, (LPBYTE)Old, RegSize);
RegDeleteValue(Key, Backup);
}
}
RegCloseKey(Key);
}
else
if (State)
{
if (RegCreateKeyEx(HKEY_CLASSES_ROOT, Base, 0, NULL, 0, KEY_READ|KEY_WRITE, NULL, &Key, &Disp) == ERROR_SUCCESS)
{
RegSetValueEx(Key, NULL, 0, REG_SZ, (LPBYTE)New, (DWORD)((tcslen(New)+1)*sizeof(New)));
RegSetValueEx(Key, Backup, 0, REG_SZ, (LPBYTE)T(""), sizeof(tchar_t));
RegCloseKey(Key);
}
}
}
static bool_t CmpReg(const tchar_t* Base, const tchar_t* Value)
{
bool_t Result = 0;
HKEY Key;
DWORD RegSize;
DWORD RegType;
tchar_t s[MAXPATH];
if (RegOpenKeyEx(HKEY_CLASSES_ROOT, Base, 0, KEY_READ, &Key) == ERROR_SUCCESS)
{
RegSize = sizeof(s);
if (RegQueryValueEx(Key, NULL, 0, &RegType, (LPBYTE)s, &RegSize) == ERROR_SUCCESS && RegType == REG_SZ)
Result = tcsicmp(s,Value)==0;
RegCloseKey(Key);
}
return Result;
}
static void SetFileAssociation(const tchar_t* Ext,bool_t State,bool_t MIME,bool_t PlayList)
{
tchar_t Base[64];
tchar_t Type[64];
tchar_t Path[MAXPATH];
tchar_t Open[MAXPATH];
tchar_t Icon[MAXPATH];
GetModuleFileName(NULL,Path,MAXPATH);
if (tcschr(Path,' '))
stprintf_s(Open,TSIZEOF(Open),T("\"%s\" \"%%1\""),Path);
else
stprintf_s(Open,TSIZEOF(Open),T("%s \"%%1\""),Path);
stprintf_s(Icon,TSIZEOF(Icon),T("%s, -%d"),Path,1000);
stprintf_s(Base,TSIZEOF(Base),T(".%s"),Ext);
stprintf_s(Type,TSIZEOF(Type),MIME?T("%s"):T("%sFile"),Ext);
tcsupr(Type);
if (!MIME)
{
SetReg(Base,Type,State);
if (State)
SetEditFlags(Type,PlayList?0x10010000:0x10000);
}
else
if (State)
SetURLProtocol(Type);
stprintf_s(Base,TSIZEOF(Base),T("%s\\DefaultIcon"),Type);
SetReg(Base,Icon,State);
stprintf_s(Base,TSIZEOF(Base),T("%s\\Shell\\Open\\Command"),Type);
SetReg(Base,Open,State);
}
#if defined(NDEBUG) && !defined(TARGET_WIN32)
static bool_t GetReg(const tchar_t* Base, tchar_t* Value,DWORD ValueSize)
{
bool_t Result = 0;
HKEY Key;
DWORD RegType;
if (RegOpenKeyEx(HKEY_CLASSES_ROOT, Base, 0, KEY_READ, &Key) == ERROR_SUCCESS)
{
if (RegQueryValueEx(Key, NULL, 0, &RegType, (LPBYTE)Value, &ValueSize) == ERROR_SUCCESS && RegType == REG_SZ && Value[0])
Result = 1;
RegCloseKey(Key);
}
return Result;
}
static bool_t EmptyFileAssociation(const tchar_t* Ext,bool_t MIME)
{
tchar_t Base[MAXPATH];
tchar_t Type[MAXPATH];
stprintf_s(Base,TSIZEOF(Base),T(".%s"),Ext);
if (MIME || GetReg(Base,Type,sizeof(Type)))
{
if (MIME)
tcscpy_s(Type,TSIZEOF(Type),Ext);
stprintf_s(Base,TSIZEOF(Base),T("%s\\Shell\\Open\\Command"),Type);
if (GetReg(Base,Type,sizeof(Type)))
return 0;
}
return 1;
}
#endif
static bool_t GetFileAssociation(const tchar_t* Ext,bool_t MIME)
{
tchar_t Base[64];
tchar_t Type[64];
stprintf_s(Base,TSIZEOF(Base),T(".%s"),Ext);
stprintf_s(Type,TSIZEOF(Type),MIME?T("%s"):T("%sFile"),Ext);
tcsupr(Type);
if (MIME || CmpReg(Base,Type))
{
tchar_t Path[MAXPATH];
tchar_t Open[MAXPATH];
GetModuleFileName(NULL,Path,MAXPATH);
if (tcschr(Path,' '))
stprintf_s(Open,TSIZEOF(Open),T("\"%s\" \"%%1\""),Path);
else
stprintf_s(Open,TSIZEOF(Open),T("%s \"%%1\""),Path);
stprintf_s(Base,TSIZEOF(Base),T("%s\\Shell\\Open\\Command"),Type);
if (CmpReg(Base,Open))
return 1;
}
return 0;
}
static int Enum( node* p, int* No, datadef* Param )
{
array List;
NodeEnumClass(&List,MEDIA_CLASS);
if (*No>=0 && *No<ARRAYCOUNT(List,int))
{
memset(Param,0,sizeof(datadef));
Param->No = ARRAYBEGIN(List,int)[*No];
Param->Name = LangStr(Param->No,NODE_NAME);
Param->Type = TYPE_BOOL;
Param->Size = sizeof(bool_t);
Param->Flags = DF_SETUP|DF_NOSAVE|DF_CHECKLIST;
Param->Class = ASSOCIATION_ID;
if (!UniqueExts(ARRAYBEGIN(List,int),ARRAYBEGIN(List,int)+*No))
Param->Flags = DF_HIDDEN;
ArrayClear(&List);
return ERR_NONE;
}
*No -= ARRAYCOUNT(List,int);
ArrayClear(&List);
NodeEnumClass(&List,STREAM_CLASS);
if (*No>=0 && *No<ARRAYCOUNT(List,int))
{
tchar_t Mime[MAXPATH];
bool_t HasHost;
memset(Param,0,sizeof(datadef));
Param->No = ARRAYBEGIN(List,int)[*No];
Param->Name = LangStr(Param->No,NODE_NAME);
Param->Type = TYPE_BOOL;
Param->Size = sizeof(bool_t);
Param->Flags = DF_SETUP|DF_NOSAVE|DF_CHECKLIST;
Param->Class = ASSOCIATION_ID;
stprintf_s(Mime,TSIZEOF(Mime),T("%s://"),LangStr(Param->No,NODE_CONTENTTYPE));
GetMime(Mime,NULL,0,&HasHost);
if (!HasHost || tcsicmp(Mime,T("://"))==0 || tcsicmp(Mime,T("http://"))==0)
Param->Flags = DF_HIDDEN;
ArrayClear(&List);
return ERR_NONE;
}
*No -= ARRAYCOUNT(List,int);
ArrayClear(&List);
return ERR_INVALID_PARAM;
}
static int Get(node* p, int No, void* Data, int Size)
{
if (NodeIsClass(No,STREAM_CLASS))
{
assert(Size==sizeof(bool_t));
*(bool_t*)Data = GetFileAssociation(LangStr(No,NODE_CONTENTTYPE),1);
return ERR_NONE;
}
else
if (NodeIsClass(No,MEDIA_CLASS))
{
const tchar_t* Exts = LangStr(No,NODE_EXTS);
if (Exts && Exts[0])
{
tchar_t s[16];
const tchar_t *r,*q;
assert(Size==sizeof(bool_t));
*(bool_t*)Data = 1;
for (r=Exts;r;)
{
q = tcschr(r,':');
if (q)
{
tcsncpy_s(s,TSIZEOF(s),r,q-r);
if (!GetFileAssociation(s,0))
{
*(bool_t*)Data = 0;
break;
}
}
r = tcschr(r,';');
if (r) ++r;
}
return ERR_NONE;
}
}
return ERR_INVALID_PARAM;
}
static int Set(node* p, int No, const void* Data, int Size)
{
if (NodeIsClass(No,STREAM_CLASS))
{
assert(Size==sizeof(bool_t));
SetFileAssociation(LangStr(No,NODE_CONTENTTYPE),*(bool_t*)Data,1,0);
return ERR_NONE;
}
else
if (NodeIsClass(No,MEDIA_CLASS))
{
const tchar_t* Exts = LangStr(No,NODE_EXTS);
if (Exts && Exts[0])
{
tchar_t s[16];
const tchar_t *r,*q;
bool_t State;
assert(Size==sizeof(bool_t));
State = *(bool_t*)Data;
for (r=Exts;r;)
{
q = tcschr(r,':');
if (q)
{
tcsncpy_s(s,TSIZEOF(s),r,q-r);
SetFileAssociation(s,State,0,q[1]==FTYPE_PLAYLIST);
}
r = tcschr(r,';');
if (r) ++r;
}
return ERR_NONE;
}
}
return ERR_INVALID_PARAM;
}
static void AssignEmpty(node* p)
{
#if defined(NDEBUG) && !defined(TARGET_WIN32)
int v;
if (!NodeRegLoadValue(0,REG_ASSOCIATIONS,&v,sizeof(v),TYPE_INT) || !v)
{
// set default associations for empty extensions
array List;
int* i;
NodeEnumClass(&List,MEDIA_CLASS);
for (i=ARRAYBEGIN(List,int);i!=ARRAYEND(List,int);++i)
{
const tchar_t* Exts = LangStr(*i,NODE_EXTS);
if (Exts && Exts[0])
{
bool_t Empty = 1;
tchar_t s[16];
const tchar_t *r,*q;
for (r=Exts;r;)
{
q = tcschr(r,':');
if (q)
{
tcsncpy_s(s,TSIZEOF(s),r,q-r);
if (!EmptyFileAssociation(s,0))
{
Empty = 0;
break;
}
}
r = tcschr(r,';');
if (r) ++r;
}
if (Empty)
{
bool_t True = 1;
Set(p,*i,&True,sizeof(True));
}
}
}
ArrayClear(&List);
v = 1;
NodeRegSaveValue(0,REG_ASSOCIATIONS,&v,sizeof(v),TYPE_INT);
}
#endif
}
static int Create(node* p)
{
p->Enum = (nodeenum)Enum;
p->Get = (nodeget)Get;
p->Set = (nodeset)Set;
AssignEmpty(p);
return ERR_NONE;
}
static const nodedef Association =
{
sizeof(node)|CF_GLOBAL|CF_SETTINGS,
ASSOCIATION_ID,
NODE_CLASS,
PRI_MAXIMUM+500,
(nodecreate)Create,
};
void Association_Init()
{
NodeRegisterClass(&Association);
}
void Association_Done()
{
NodeUnRegisterClass(ASSOCIATION_ID);
}
#endif