association_win32.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:11k
源码类别:

Windows CE

开发平台:

C/C++

  1. /*****************************************************************************
  2.  *
  3.  * This program is free software ; you can redistribute it and/or modify
  4.  * it under the terms of the GNU General Public License as published by
  5.  * the Free Software Foundation; either version 2 of the License, or
  6.  * (at your option) any later version.
  7.  *
  8.  * This program is distributed in the hope that it will be useful,
  9.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11.  * GNU General Public License for more details.
  12.  *
  13.  * You should have received a copy of the GNU General Public License
  14.  * along with this program; if not, write to the Free Software
  15.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  16.  *
  17.  * $Id: association_win32.c 603 2006-01-19 13:00:33Z picard $
  18.  *
  19.  * The Core Pocket Media Player
  20.  * Copyright (c) 2004-2005 Gabor Kovacs
  21.  *
  22.  ****************************************************************************/
  23. #include "../common.h"
  24. #if defined(TARGET_WIN32) || defined(TARGET_WINCE)
  25. #define REG_ASSOCIATIONS 0x2C00
  26. #ifndef STRICT
  27. #define STRICT
  28. #endif
  29. #include <windows.h>
  30. static void SetURLProtocol(const tchar_t* Base)
  31. {
  32. const tchar_t* Name = T("URL Protocol");
  33. tchar_t Value[MAXPATH];
  34. DWORD RegType;
  35. DWORD RegSize;
  36. DWORD Disp=0;
  37. HKEY Key;
  38. if (RegCreateKeyEx(HKEY_CLASSES_ROOT, Base, 0, NULL, 0, KEY_READ|KEY_WRITE, NULL, &Key, &Disp) == ERROR_SUCCESS)
  39. {
  40. RegSize=sizeof(Value);
  41. if (RegQueryValueEx(Key, NULL, 0, &RegType, (LPBYTE)Value, &RegSize) != ERROR_SUCCESS || 
  42. tcsnicmp(Value,T("URL:"),4)!=0)
  43. {
  44. stprintf_s(Value,TSIZEOF(Value),T("URL:%s protocol"),Base);
  45. RegSetValueEx(Key, NULL, 0, REG_SZ, (LPBYTE)Value, (DWORD)((tcslen(Value)+1)*sizeof(tchar_t)));
  46. }
  47. RegSize=sizeof(Value);
  48. if (RegQueryValueEx(Key, Name, 0, &RegType, (LPBYTE)Value, &RegSize) != ERROR_SUCCESS)
  49. RegSetValueEx(Key, Name, 0, REG_SZ, (LPBYTE)T(""), sizeof(tchar_t));
  50. RegCloseKey(Key);
  51. }
  52. }
  53. static void SetEditFlags(const tchar_t* Base,DWORD Value)
  54. {
  55. DWORD Disp=0;
  56. HKEY Key;
  57. if (RegCreateKeyEx(HKEY_CLASSES_ROOT, Base, 0, NULL, 0, KEY_READ|KEY_WRITE, NULL, &Key, &Disp) == ERROR_SUCCESS)
  58. {
  59. RegSetValueEx(Key, T("EditFlags"), 0, REG_DWORD, (LPBYTE)&Value, sizeof(Value));
  60. RegCloseKey(Key);
  61. }
  62. //BrowserFlags=8 (?)
  63. }
  64. static void SetReg(const tchar_t* Base,const tchar_t* New,bool_t State)
  65. {
  66. tchar_t Old[MAXPATH];
  67. tchar_t Backup[MAXPATH];
  68. DWORD Disp=0;
  69. HKEY Key;
  70. DWORD RegSize;
  71. DWORD RegType;
  72. stprintf_s(Backup,TSIZEOF(Backup),T("%s.bak"),Context()->ProgramName);
  73. if (RegOpenKeyEx(HKEY_CLASSES_ROOT, Base, 0, KEY_READ|KEY_WRITE, &Key) == ERROR_SUCCESS)
  74. {
  75. RegSize=sizeof(Old);
  76. if (RegQueryValueEx(Key, NULL, 0, &RegType, (LPBYTE)Old, &RegSize) != ERROR_SUCCESS)
  77. Old[0] = 0;
  78. if (tcsicmp(Old,New)!=0)
  79. {
  80. if (State)
  81. {
  82. RegSetValueEx(Key, NULL, 0, REG_SZ, (LPBYTE)New, (DWORD)((tcslen(New)+1)*sizeof(tchar_t)));
  83. RegSetValueEx(Key, Backup, 0, REG_SZ, (LPBYTE)Old, RegSize);
  84. }
  85. }
  86. else 
  87. if (!State)
  88. {
  89. RegSize = sizeof(Old);
  90. if (RegQueryValueEx(Key, Backup, 0, &RegType, (LPBYTE)Old, &RegSize) == ERROR_SUCCESS)
  91. {
  92. RegSetValueEx(Key, NULL, 0, REG_SZ, (LPBYTE)Old, RegSize);
  93. RegDeleteValue(Key, Backup);
  94. }
  95. }
  96. RegCloseKey(Key);
  97. }
  98. else 
  99. if (State)
  100. {
  101. if (RegCreateKeyEx(HKEY_CLASSES_ROOT, Base, 0, NULL, 0, KEY_READ|KEY_WRITE, NULL, &Key, &Disp) == ERROR_SUCCESS)
  102. {
  103. RegSetValueEx(Key, NULL, 0, REG_SZ, (LPBYTE)New, (DWORD)((tcslen(New)+1)*sizeof(New)));
  104. RegSetValueEx(Key, Backup, 0, REG_SZ, (LPBYTE)T(""), sizeof(tchar_t));
  105. RegCloseKey(Key);
  106. }
  107. }
  108. }
  109. static bool_t CmpReg(const tchar_t* Base, const tchar_t* Value)
  110. {
  111. bool_t Result = 0;
  112. HKEY Key;
  113. DWORD RegSize;
  114. DWORD RegType;
  115. tchar_t s[MAXPATH];
  116. if (RegOpenKeyEx(HKEY_CLASSES_ROOT, Base, 0, KEY_READ, &Key) == ERROR_SUCCESS)
  117. {
  118. RegSize = sizeof(s);
  119. if (RegQueryValueEx(Key, NULL, 0, &RegType, (LPBYTE)s, &RegSize) == ERROR_SUCCESS && RegType == REG_SZ)
  120. Result = tcsicmp(s,Value)==0;
  121. RegCloseKey(Key);
  122. }
  123. return Result;
  124. }
  125. static void SetFileAssociation(const tchar_t* Ext,bool_t State,bool_t MIME,bool_t PlayList)
  126. {
  127. tchar_t Base[64];
  128. tchar_t Type[64];
  129. tchar_t Path[MAXPATH];
  130. tchar_t Open[MAXPATH];
  131. tchar_t Icon[MAXPATH];
  132. GetModuleFileName(NULL,Path,MAXPATH);
  133. if (tcschr(Path,' '))
  134. stprintf_s(Open,TSIZEOF(Open),T(""%s" "%%1""),Path);
  135. else
  136. stprintf_s(Open,TSIZEOF(Open),T("%s "%%1""),Path);
  137. stprintf_s(Icon,TSIZEOF(Icon),T("%s, -%d"),Path,1000);
  138. stprintf_s(Base,TSIZEOF(Base),T(".%s"),Ext);
  139. stprintf_s(Type,TSIZEOF(Type),MIME?T("%s"):T("%sFile"),Ext);
  140. tcsupr(Type);
  141. if (!MIME)
  142. {
  143. SetReg(Base,Type,State);
  144. if (State)
  145. SetEditFlags(Type,PlayList?0x10010000:0x10000); 
  146. }
  147. else
  148. if (State)
  149. SetURLProtocol(Type);
  150. stprintf_s(Base,TSIZEOF(Base),T("%s\DefaultIcon"),Type);
  151. SetReg(Base,Icon,State);
  152. stprintf_s(Base,TSIZEOF(Base),T("%s\Shell\Open\Command"),Type);
  153. SetReg(Base,Open,State);
  154. }
  155. #if defined(NDEBUG) && !defined(TARGET_WIN32)
  156. static bool_t GetReg(const tchar_t* Base, tchar_t* Value,DWORD ValueSize)
  157. {
  158. bool_t Result = 0;
  159. HKEY Key;
  160. DWORD RegType;
  161. if (RegOpenKeyEx(HKEY_CLASSES_ROOT, Base, 0, KEY_READ, &Key) == ERROR_SUCCESS)
  162. {
  163. if (RegQueryValueEx(Key, NULL, 0, &RegType, (LPBYTE)Value, &ValueSize) == ERROR_SUCCESS && RegType == REG_SZ && Value[0])
  164. Result = 1;
  165. RegCloseKey(Key);
  166. }
  167. return Result;
  168. }
  169. static bool_t EmptyFileAssociation(const tchar_t* Ext,bool_t MIME)
  170. {
  171. tchar_t Base[MAXPATH];
  172. tchar_t Type[MAXPATH];
  173. stprintf_s(Base,TSIZEOF(Base),T(".%s"),Ext);
  174. if (MIME || GetReg(Base,Type,sizeof(Type)))
  175. {
  176. if (MIME)
  177. tcscpy_s(Type,TSIZEOF(Type),Ext);
  178. stprintf_s(Base,TSIZEOF(Base),T("%s\Shell\Open\Command"),Type);
  179. if (GetReg(Base,Type,sizeof(Type)))
  180. return 0;
  181. }
  182. return 1;
  183. }
  184. #endif
  185. static bool_t GetFileAssociation(const tchar_t* Ext,bool_t MIME)
  186. {
  187. tchar_t Base[64];
  188. tchar_t Type[64];
  189. stprintf_s(Base,TSIZEOF(Base),T(".%s"),Ext);
  190. stprintf_s(Type,TSIZEOF(Type),MIME?T("%s"):T("%sFile"),Ext);
  191. tcsupr(Type);
  192. if (MIME || CmpReg(Base,Type))
  193. {
  194. tchar_t Path[MAXPATH];
  195. tchar_t Open[MAXPATH];
  196. GetModuleFileName(NULL,Path,MAXPATH);
  197. if (tcschr(Path,' '))
  198. stprintf_s(Open,TSIZEOF(Open),T(""%s" "%%1""),Path);
  199. else
  200. stprintf_s(Open,TSIZEOF(Open),T("%s "%%1""),Path);
  201. stprintf_s(Base,TSIZEOF(Base),T("%s\Shell\Open\Command"),Type);
  202. if (CmpReg(Base,Open))
  203. return 1;
  204. }
  205. return 0;
  206. }
  207. static int Enum( node* p, int* No, datadef* Param )
  208. {
  209. array List;
  210. NodeEnumClass(&List,MEDIA_CLASS);
  211. if (*No>=0 && *No<ARRAYCOUNT(List,int))
  212. {
  213. memset(Param,0,sizeof(datadef));
  214. Param->No = ARRAYBEGIN(List,int)[*No];
  215. Param->Name = LangStr(Param->No,NODE_NAME);
  216. Param->Type = TYPE_BOOL;
  217. Param->Size = sizeof(bool_t);
  218. Param->Flags = DF_SETUP|DF_NOSAVE|DF_CHECKLIST;
  219. Param->Class = ASSOCIATION_ID;
  220. if (!UniqueExts(ARRAYBEGIN(List,int),ARRAYBEGIN(List,int)+*No))
  221. Param->Flags = DF_HIDDEN;
  222. ArrayClear(&List);
  223. return ERR_NONE;
  224. }
  225. *No -= ARRAYCOUNT(List,int);
  226. ArrayClear(&List);
  227. NodeEnumClass(&List,STREAM_CLASS);
  228. if (*No>=0 && *No<ARRAYCOUNT(List,int))
  229. {
  230. tchar_t Mime[MAXPATH];
  231. bool_t HasHost;
  232. memset(Param,0,sizeof(datadef));
  233. Param->No = ARRAYBEGIN(List,int)[*No];
  234. Param->Name = LangStr(Param->No,NODE_NAME);
  235. Param->Type = TYPE_BOOL;
  236. Param->Size = sizeof(bool_t);
  237. Param->Flags = DF_SETUP|DF_NOSAVE|DF_CHECKLIST;
  238. Param->Class = ASSOCIATION_ID;
  239. stprintf_s(Mime,TSIZEOF(Mime),T("%s://"),LangStr(Param->No,NODE_CONTENTTYPE));
  240. GetMime(Mime,NULL,0,&HasHost);
  241. if (!HasHost || tcsicmp(Mime,T("://"))==0 || tcsicmp(Mime,T("http://"))==0)
  242. Param->Flags = DF_HIDDEN;
  243. ArrayClear(&List);
  244. return ERR_NONE;
  245. }
  246. *No -= ARRAYCOUNT(List,int);
  247. ArrayClear(&List);
  248. return ERR_INVALID_PARAM;
  249. }
  250. static int Get(node* p, int No, void* Data, int Size)
  251. {
  252. if (NodeIsClass(No,STREAM_CLASS))
  253. {
  254. assert(Size==sizeof(bool_t));
  255. *(bool_t*)Data = GetFileAssociation(LangStr(No,NODE_CONTENTTYPE),1);
  256. return ERR_NONE;
  257. }
  258. else
  259. if (NodeIsClass(No,MEDIA_CLASS))
  260. {
  261. const tchar_t* Exts = LangStr(No,NODE_EXTS);
  262. if (Exts && Exts[0])
  263. {
  264. tchar_t s[16];
  265. const tchar_t *r,*q;
  266. assert(Size==sizeof(bool_t));
  267. *(bool_t*)Data = 1;
  268. for (r=Exts;r;)
  269. {
  270. q = tcschr(r,':');
  271. if (q)
  272. {
  273. tcsncpy_s(s,TSIZEOF(s),r,q-r);
  274. if (!GetFileAssociation(s,0))
  275. {
  276. *(bool_t*)Data = 0;
  277. break;
  278. }
  279. }
  280. r = tcschr(r,';');
  281. if (r) ++r;
  282. }
  283. return ERR_NONE;
  284. }
  285. }
  286. return ERR_INVALID_PARAM;
  287. }
  288. static int Set(node* p, int No, const void* Data, int Size)
  289. {
  290. if (NodeIsClass(No,STREAM_CLASS))
  291. {
  292. assert(Size==sizeof(bool_t));
  293. SetFileAssociation(LangStr(No,NODE_CONTENTTYPE),*(bool_t*)Data,1,0);
  294. return ERR_NONE;
  295. }
  296. else
  297. if (NodeIsClass(No,MEDIA_CLASS))
  298. {
  299. const tchar_t* Exts = LangStr(No,NODE_EXTS);
  300. if (Exts && Exts[0])
  301. {
  302. tchar_t s[16];
  303. const tchar_t *r,*q;
  304. bool_t State;
  305. assert(Size==sizeof(bool_t));
  306. State = *(bool_t*)Data;
  307. for (r=Exts;r;)
  308. {
  309. q = tcschr(r,':');
  310. if (q)
  311. {
  312. tcsncpy_s(s,TSIZEOF(s),r,q-r);
  313. SetFileAssociation(s,State,0,q[1]==FTYPE_PLAYLIST);
  314. }
  315. r = tcschr(r,';');
  316. if (r) ++r;
  317. }
  318. return ERR_NONE;
  319. }
  320. }
  321. return ERR_INVALID_PARAM;
  322. }
  323. static void AssignEmpty(node* p)
  324. {
  325. #if defined(NDEBUG) && !defined(TARGET_WIN32)
  326. int v;
  327. if (!NodeRegLoadValue(0,REG_ASSOCIATIONS,&v,sizeof(v),TYPE_INT) || !v)
  328. {
  329. // set default associations for empty extensions
  330. array List;
  331. int* i;
  332. NodeEnumClass(&List,MEDIA_CLASS);
  333. for (i=ARRAYBEGIN(List,int);i!=ARRAYEND(List,int);++i)
  334. {
  335. const tchar_t* Exts = LangStr(*i,NODE_EXTS);
  336. if (Exts && Exts[0])
  337. {
  338. bool_t Empty = 1;
  339. tchar_t s[16];
  340. const tchar_t *r,*q;
  341. for (r=Exts;r;)
  342. {
  343. q = tcschr(r,':');
  344. if (q)
  345. {
  346. tcsncpy_s(s,TSIZEOF(s),r,q-r);
  347. if (!EmptyFileAssociation(s,0))
  348. {
  349. Empty = 0;
  350. break;
  351. }
  352. }
  353. r = tcschr(r,';');
  354. if (r) ++r;
  355. }
  356. if (Empty)
  357. {
  358. bool_t True = 1;
  359. Set(p,*i,&True,sizeof(True));
  360. }
  361. }
  362. }
  363. ArrayClear(&List);
  364. v = 1;
  365. NodeRegSaveValue(0,REG_ASSOCIATIONS,&v,sizeof(v),TYPE_INT);
  366. }
  367. #endif
  368. }
  369. static int Create(node* p)
  370. {
  371. p->Enum = (nodeenum)Enum;
  372. p->Get = (nodeget)Get;
  373. p->Set = (nodeset)Set;
  374. AssignEmpty(p);
  375. return ERR_NONE;
  376. }
  377. static const nodedef Association =
  378. {
  379. sizeof(node)|CF_GLOBAL|CF_SETTINGS,
  380. ASSOCIATION_ID,
  381. NODE_CLASS,
  382. PRI_MAXIMUM+500,
  383. (nodecreate)Create,
  384. };
  385. void Association_Init()
  386. {
  387. NodeRegisterClass(&Association);
  388. }
  389. void Association_Done()
  390. {
  391. NodeUnRegisterClass(ASSOCIATION_ID);
  392. }
  393. #endif