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

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: platform_win32.c 622 2006-01-31 19:02:53Z 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. #ifndef STRICT
  26. #define STRICT
  27. #endif
  28. #include <windows.h>
  29. // registry backups of original value
  30. #define REG_BATTERYTIMEOUT  0x2000
  31. #define REG_ACTIMEOUT  0x2001
  32. #define REG_SCREENSAVER  0x2002
  33. #define REG_DISPPOWER    0x2003
  34. #define REG_ACSUSPEND  0x2004
  35. #define REG_BATTSUSPEND  0x2005
  36. #define REG_ACUSERIDLE  0x2006
  37. #define REG_BATTUSERIDLE  0x2007
  38. #define REG_ACSYSTEMIDLE  0x2008
  39. #define REG_BATTSYSTEMIDLE  0x2009
  40. #define REG_BATTERYTIMEOUT2  0x200A
  41. #define REG_ACTIMEOUT2  0x200B
  42. void DMO_Init();
  43. void DMO_Done();
  44. void File_Init();
  45. void File_Done();
  46. #if defined(TARGET_WINCE)
  47. #define HKEY_ROOT HKEY_LOCAL_MACHINE
  48. #else
  49. #define HKEY_ROOT HKEY_CURRENT_USER
  50. #endif
  51. #if defined(TARGET_WINCE)
  52. #define POWER_NAME 1
  53. #define POWER_UNSPEC -1
  54. #define POWER_D0 0
  55. #define POWER_D4 4
  56. #ifndef DISP_CHANGE_SUCCESSFUL
  57. #define DISP_CHANGE_SUCCESSFUL 0
  58. #endif
  59. #ifndef CDS_TEST
  60. #define CDS_TEST            0x00000002
  61. #endif
  62. #ifndef DM_DISPLAYORIENTATION
  63. #define DM_DISPLAYORIENTATION 0x00800000L
  64. #endif
  65. #ifndef DM_DISPLAYQUERYORIENTATION 
  66. #define DM_DISPLAYQUERYORIENTATION 0x01000000L
  67. #endif
  68. #ifndef DMDO_0
  69. #define DMDO_0      0
  70. #endif
  71. #ifndef DMDO_90
  72. #define DMDO_90     1
  73. #endif
  74. #ifndef DMDO_180
  75. #define DMDO_180    2
  76. #endif
  77. #ifndef DMDO_270
  78. #define DMDO_270    4
  79. #endif
  80. #define SPI_GETOEMINFO 258
  81. #define SPI_GETPLATFORMTYPE 257
  82. typedef struct MSGQUEUEOPTIONS2 
  83. {
  84. DWORD dwSize;
  85. DWORD dwFlags;
  86. DWORD dwMaxMessages;
  87. DWORD cbMaxMessage;
  88. BOOL  bReadAccess;
  89. } MSGQUEUEOPTIONS2;
  90. BOOL (WINAPI* FuncCeSetThreadQuantum)(HANDLE, DWORD) = NULL;
  91. static HANDLE (WINAPI* FuncSetPowerRequirement)(PVOID,int,ULONG,PVOID,ULONG) = NULL;
  92. static DWORD (WINAPI* FuncReleasePowerRequirement)(HANDLE) = NULL;
  93. static DWORD (WINAPI* FuncSetDevicePower)(PVOID,DWORD,int) = NULL;
  94. static DWORD (WINAPI* FuncGetDevicePower)(PVOID,DWORD,int*) = NULL;
  95. static BOOL (WINAPI* FuncSHGetDocumentsFolder)(LPCTSTR,LPTSTR) = NULL;
  96. static BOOL (WINAPI* FuncSHGetSpecialFolderPath)(HWND,LPTSTR,int,BOOL) = NULL;
  97. static LONG (WINAPI* FuncChangeDisplaySettingsEx)(LPCTSTR,LPDEVMODE,HWND,DWORD,LPVOID) = NULL;
  98. static BOOL (WINAPI* FuncSetKMode)(BOOL) = NULL;
  99. static BOOL (WINAPI* FuncRedrawWindow)(HWND,CONST RECT*,HRGN,UINT) = NULL;
  100. static void (WINAPI* FuncSHIdleTimerReset)() = NULL;
  101. static BOOL (WINAPI* FuncReadMsgQueue)(HANDLE hMsgQ, LPVOID lpBuffer, DWORD cbBufferSize, LPDWORD lpNumberOfBytesRead, DWORD dwTimeout, DWORD *pdwFlags) = NULL;
  102. static HANDLE (WINAPI* FuncCreateMsgQueue)(LPCWSTR lpName, MSGQUEUEOPTIONS2* lpOptions) = NULL;
  103. static BOOL (WINAPI* FuncCloseMsgQueue)(HANDLE hMsgQ) = NULL;
  104. static HANDLE (WINAPI* FuncRequestPowerNotifications)(HANDLE  hMsgQ,DWORD Flags) = NULL;
  105. static DWORD (WINAPI* FuncStopPowerNotifications)(HANDLE h) = NULL;
  106. static HMODULE CoreDLL = NULL;
  107. static HMODULE CEShellDLL = NULL;
  108. static HANDLE BacklightEvent = NULL;
  109. static HANDLE PowerHandle = NULL;
  110. #endif
  111. static HMODULE AygShellDLL = NULL;
  112. static const tchar_t RegBacklight[] = T("ControlPanel\Backlight");
  113. static const tchar_t RegBatteryTimeout[] = T("BatteryTimeout");
  114. static const tchar_t RegACTimeout[] = T("ACTimeout");
  115. static const tchar_t RegScreenSaver[] = T("ControlPanel\ScreenSaver");
  116. static const tchar_t RegMode[] = T("Mode");
  117. static const tchar_t RegPower[] = T("ControlPanel\Power");
  118. static const tchar_t RegDisplay[] = T("Display");
  119. static const tchar_t RegPowerTimouts[] = T("SYSTEM\CurrentControlSet\Control\Power\Timeouts");
  120. static const tchar_t RegBattUserIdle[] = T("BattUserIdle");
  121. static const tchar_t RegACUserIdle[] = T("ACUserIdle");
  122. static const tchar_t RegBattSystemIdle[] = T("BattSystemIdle");
  123. static const tchar_t RegACSystemIdle[] = T("ACSystemIdle");
  124. static const tchar_t RegBattSuspend[] = T("BattSuspend");
  125. static const tchar_t RegACSuspend[] = T("ACSuspend");
  126. static const tchar_t RegCASIOBacklight[] = T("Drivers\CASIO\BackLight");
  127. static const tchar_t RegTimeoutBattery[] = T("TimeoutBattery");
  128. static const tchar_t RegTimeoutExPower[] = T("TimeoutExPower");
  129. #define GETVFRAMEPHYSICAL 6144
  130. #define GETVFRAMELEN 6145
  131. #define DBGDRIVERSTAT 6146
  132. #define SETPOWERMANAGEMENT 6147
  133. #define GETPOWERMANAGEMENT 6148
  134. typedef struct VIDEO_POWER_MANAGEMENT {
  135.     ULONG Length;
  136.     ULONG DPMSVersion;
  137.     ULONG PowerState;
  138. } VIDEO_POWER_MANAGEMENT;
  139. static rgb Palette[256];
  140. static tchar_t DocumentPath[MAX_PATH]; //important! has to be the MAX_PATH
  141. static tchar_t SystemPath[MAX_PATH]; //important! has to be the MAX_PATH
  142. static bool_t DisplayPower = 1;
  143. static int Orientation = -1;
  144. static bool_t WaitCursor = 0;
  145. static bool_t WaitCursorDisable = 0;
  146. static stream* Debug = NULL;
  147. #if defined(MIPS)
  148. int GetTimeFreq() 
  149. return 1000; 
  150. }
  151. int GetTimeTick()
  152. {
  153. SYSTEMTIME t;
  154. GetSystemTime(&t);
  155. return (t.wDay*24+t.wHour)*60*60*1000+(t.wMinute*60+t.wSecond)*1000+t.wMilliseconds;
  156. }
  157. void GetTimeCycle(int* p)
  158. {
  159. SYSTEMTIME i,j;
  160. int n=0;
  161. GetSystemTime(&i);
  162. do
  163. {
  164. ++n;
  165. GetSystemTime(&j);
  166. }
  167. while (j.wMilliseconds==i.wMilliseconds);
  168. p[0] = (j.wDay*24+j.wHour)*60*60*1000+(j.wMinute*60+j.wSecond)*1000+j.wMilliseconds;
  169. p[1] = n;
  170. }
  171. #elif defined(TARGET_WINCE)
  172. int GetTimeFreq() 
  173. return 1000; 
  174. }
  175. int GetTimeTick()
  176. {
  177. return GetTickCount();
  178. }
  179. void GetTimeCycle(int* p)
  180. {
  181. int n=1;
  182. int j;
  183. int i = GetTickCount();
  184. while ((j = GetTickCount())==i)
  185. ++n;
  186. p[0] = j;
  187. p[1] = n;
  188. }
  189. #else
  190. int GetTimeFreq() 
  191. return 1000; 
  192. }
  193. int GetTimeTick()
  194. {
  195. return timeGetTime();
  196. }
  197. void GetTimeCycle(int* p)
  198. {
  199. int n=1;
  200. int j;
  201. int i = timeGetTime();
  202. while ((j = timeGetTime())==i)
  203. ++n;
  204. p[0] = j;
  205. p[1] = n;
  206. }
  207. #endif
  208. void ReleaseModule(void** Module)
  209. {
  210. if (*Module)
  211. {
  212. FreeLibrary(*Module);
  213. *Module = NULL;
  214. }
  215. }
  216. void GetProc(void** Module,void* Ptr,const tchar_t* ProcName,int Optional)
  217. {
  218. FARPROC* Func = (FARPROC*)Ptr;
  219. if (*Module)
  220. {
  221. #if !defined(TARGET_WINCE) && defined(UNICODE)
  222. char ProcName8[256];
  223. TcsToStr(ProcName8,sizeof(ProcName8),ProcName);
  224. *Func = GetProcAddress(*Module,ProcName8);
  225. #else
  226. *Func = GetProcAddress(*Module,ProcName);
  227. #endif
  228. if (!*Func && !Optional)
  229. ReleaseModule(Module);
  230. }
  231. else
  232. *Func = NULL;
  233. }
  234. int DefaultLang()
  235. {
  236. tchar_t Lang[16];
  237. if (GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_SABBREVLANGNAME,Lang,TSIZEOF(Lang)) >= 2)
  238. {
  239. tcsupr(Lang);
  240. if (tcscmp(Lang,T("JPN"))==0) tcscpy_s(Lang,TSIZEOF(Lang),T("JA"));
  241. if (tcscmp(Lang,T("GER"))==0) tcscpy_s(Lang,TSIZEOF(Lang),T("DE"));
  242. if (tcscmp(Lang,T("SPA"))==0) tcscpy_s(Lang,TSIZEOF(Lang),T("ES"));
  243. // special three letter cases: Chinese traditional (CHT) and Chinese simplified (CHS)
  244. if (tcscmp(Lang,T("CHS"))==0 || tcscmp(Lang,T("ZHI"))==0 || tcscmp(Lang,T("ZHM"))==0)
  245. return FOURCC('C','H','S','_');
  246. else
  247. if (tcscmp(Lang,T("CHT"))==0 || tcscmp(Lang,T("ZHH"))==0)
  248. return FOURCC('C','H','T','_');
  249. else
  250. if (tcscmp(Lang,T("PTB"))==0)
  251. return FOURCC('P','T','B','_');
  252. else
  253. return FOURCC(Lang[0],Lang[1],'_','_'); // two letter version
  254. }
  255. return LANG_DEFAULT;
  256. }
  257. void PlatformDetect(platform* p)
  258. {
  259. #if defined(TARGET_WINCE)
  260. tchar_t OemUpper[64];
  261. HKEY Key;
  262. RECT WorkArea;
  263. #endif
  264. OSVERSIONINFO Ver;
  265. Ver.dwOSVersionInfoSize = sizeof(Ver);
  266. GetVersionEx(&Ver);
  267. p->Ver = Ver.dwMajorVersion*100 + Ver.dwMinorVersion;
  268. stprintf_s(p->Version,TSIZEOF(p->Version),T("%d.%02d"),p->Ver/100,p->Ver%100);
  269. #if defined(TARGET_WINCE)
  270. p->WMPVersion = 9;
  271. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, T("SOFTWARE\Microsoft\MediaPlayer\ASFCodecs"), 0, KEY_READ, &Key) == ERROR_SUCCESS)
  272. {
  273. p->WMPVersion = 10;
  274. RegCloseKey(Key);
  275. }
  276. p->Type = TYPE_WINCE;
  277. if (SystemParametersInfo(SPI_GETPLATFORMTYPE,sizeof(p->PlatformType),p->PlatformType,0)!=0)
  278. {
  279. if (tcsicmp(p->PlatformType,T("PocketPC"))==0)
  280. p->Type = TYPE_POCKETPC;
  281. else
  282. if (tcsicmp(p->PlatformType,T("Smartphone"))==0)
  283. p->Type = TYPE_SMARTPHONE;
  284. }
  285. else
  286. if (GetLastError()==ERROR_ACCESS_DENIED)
  287. {
  288. tcscpy_s(p->PlatformType,TSIZEOF(p->PlatformType),T("Smartphone"));
  289. p->Type = TYPE_SMARTPHONE;
  290. }
  291. else
  292. tcscpy_s(p->PlatformType,TSIZEOF(p->PlatformType),T("Windows CE"));
  293. SystemParametersInfo(SPI_GETOEMINFO,sizeof(p->OemInfo),p->OemInfo,0);
  294. tcscpy_s(OemUpper,TSIZEOF(OemUpper),p->OemInfo);
  295. tcsupr(OemUpper);
  296. #if defined(ARM)
  297. if (tcsstr(OemUpper,T("NOVOGO")))
  298. p->Model = MODEL_NOVOGO; // more models...
  299. else
  300. if (tcsstr(OemUpper,T("TYPHOON")))
  301. p->Model = MODEL_SPV_C500_ORIGROM;
  302. else
  303. if (tcsstr(OemUpper,T("PW10B")) ||
  304. tcsstr(OemUpper,T("PW10A")))
  305. {
  306. p->Model = MODEL_O2_XDA;
  307. p->Caps |= CAPS_ONLY12BITRGB;
  308. }
  309. else
  310. if (tcsstr(OemUpper,T("Compal P6C")))
  311. p->Model = MODEL_AMIGO_600C;
  312. else
  313. if (tcsstr(OemUpper,T("Pocket PC J710")))
  314. p->Model = MODEL_CASIO_E200;
  315. else
  316. if (tcsstr(OemUpper,T("JORNADA")))
  317. {
  318. p->Caps |= CAPS_LANDSCAPE;
  319. if (tcsstr(OemUpper,T("680")))
  320. p->Model = MODEL_JORNADA_680;
  321. else
  322. if (tcsstr(OemUpper,T("690")))
  323. p->Model = MODEL_JORNADA_690;
  324. else
  325. if (tcsstr(OemUpper,T("710")))
  326. p->Model = MODEL_JORNADA_710;
  327. else
  328. if (tcsstr(OemUpper,T("720")))
  329. p->Model = MODEL_JORNADA_720;
  330. }
  331. else
  332. if (tcsstr(OemUpper,T("IPAQ")))
  333. {
  334. p->Caps |= CAPS_PORTRAIT;
  335. if (tcsstr(OemUpper,T("H3600")))
  336. {
  337. p->Model = MODEL_IPAQ_H3600;
  338. p->Caps |= CAPS_ONLY12BITRGB;
  339. }
  340. else
  341. if (tcsstr(OemUpper,T("H3700")))
  342. {
  343. p->Model = MODEL_IPAQ_H3700;
  344. p->Caps |= CAPS_ONLY12BITRGB;
  345. }
  346. else
  347. if (tcsstr(OemUpper,T("H3800")))
  348. p->Model = MODEL_IPAQ_H3800;
  349. else
  350. if (tcsstr(OemUpper,T("H3900")))
  351. p->Model = MODEL_IPAQ_H3900;
  352. else
  353. if (tcsstr(OemUpper,T("HX4700")))
  354. p->Model = MODEL_IPAQ_HX4700;
  355. }
  356. else
  357. if (tcsstr(OemUpper,T("TOSHIBA")))
  358. {
  359. p->Caps |= CAPS_PORTRAIT;
  360. if (tcsstr(OemUpper,T("E740")))
  361. p->Model = MODEL_TOSHIBA_E740;
  362. else
  363. if (tcsstr(OemUpper,T("E750")))
  364. p->Model = MODEL_TOSHIBA_E750;
  365. else
  366. if (tcsstr(OemUpper,T("E80")))
  367. p->Model = MODEL_TOSHIBA_E800;
  368. }
  369. else
  370. if (tcsstr(OemUpper,T("AXIM")))
  371. {
  372. if (tcscmp(OemUpper+tcslen(OemUpper)-2,T("X5"))==0)
  373. p->Model = MODEL_AXIM_X5;
  374. if (tcscmp(OemUpper+tcslen(OemUpper)-3,T("X50"))==0 ||
  375. tcscmp(OemUpper+tcslen(OemUpper)-4,T("X50V"))==0)
  376. p->Model = MODEL_AXIM_X50;
  377. }
  378. else
  379. if (tcsstr(OemUpper,T("LOOX")))
  380. {
  381. if (tcsstr(OemUpper,T("720")))
  382. p->Model = MODEL_LOOX_720;
  383. }
  384. else
  385. if (tcsstr(OemUpper,T("NEXIO")))
  386. {
  387. if (tcsstr(OemUpper,T("XP40")))
  388. p->Model = MODEL_NEXIO_XP40;
  389. else
  390. if (tcsstr(OemUpper,T("XP30")))
  391. p->Model = MODEL_NEXIO_XP30;
  392. }
  393. #elif defined(MIPS)
  394. if (tcsstr(OemUpper,T("BSQUARE")))
  395. {
  396. tcscpy_s(OemUpper,TSIZEOF(OemUpper),p->PlatformType);
  397. tcsupr(OemUpper);
  398. if (tcsstr(OemUpper,T("ALCHEMY")))
  399. p->Model = MODEL_BSQUARE_ALCHEMY;
  400. tcscpy_s(OemUpper,TSIZEOF(OemUpper),p->OemInfo);
  401. tcsupr(OemUpper);
  402. }
  403. if (tcsstr(OemUpper,T("POCKET")))
  404. {
  405. if (tcsstr(OemUpper,T(" J74")))
  406. {
  407. p->Model = MODEL_CASIO_BE300;
  408. p->Caps |= CAPS_OLDSHELL;
  409. }
  410. }
  411. if (tcsstr(OemUpper,T("POCKET PC")))
  412. {
  413. p->Caps |= CAPS_PORTRAIT;
  414. if (tcsstr(OemUpper,T(" J67")))
  415. p->Model = MODEL_CASIO_E125;
  416. else
  417. if (tcsstr(OemUpper,T(" J76")))
  418. p->Model = MODEL_CASIO_EM500;
  419. else
  420. if (tcsstr(OemUpper,T(" J58")))
  421. p->Model = MODEL_CASIO_E115;
  422. else
  423. if (tcsstr(OemUpper,T(" J53")) || tcsstr(OemUpper,T(" JX53")))
  424. p->Model = MODEL_CASIO_E105;
  425. }
  426. if (tcsstr(OemUpper,T("HC-VJ")))
  427. p->Model = MODEL_INTERMEC_6651;
  428. if (tcsstr(OemUpper,T("JVC")))
  429. {
  430. if (tcsstr(OemUpper,T("C33")))
  431. p->Model = MODEL_JVC_C33;
  432. }
  433. if (tcsstr(OemUpper,T("COMPAQ AERO 15")))
  434. p->Model = MODEL_COMPAQ_AERO_1500;
  435. #elif defined(SH3)
  436. if (tcsstr(OemUpper,T("JORNADA")))
  437. {
  438. if (tcsstr(OemUpper,T(" 43")))
  439. {
  440. p->Caps |= CAPS_ONLY12BITRGB;
  441. }
  442. if (tcsstr(OemUpper,T(" 54")))
  443. {
  444. p->Model = MODEL_JORNADA_540;
  445. p->Caps |= CAPS_ONLY12BITRGB | CAPS_PORTRAIT;
  446. }
  447. }
  448. #endif
  449. if (!AygShellDLL && p->Ver < 300)
  450. p->Caps |= CAPS_OLDSHELL;
  451. // detect fake navigator bar and use old style menu
  452. if (p->Type != TYPE_SMARTPHONE && AygShellDLL && 
  453. SystemParametersInfo(SPI_GETWORKAREA,0,&WorkArea,0) && WorkArea.top==0)
  454. p->Caps |= CAPS_OLDSHELL;
  455. #else
  456. tcscpy_s(p->PlatformType,TSIZEOF(p->PlatformType),T("Windows"));
  457. p->Type = TYPE_WIN32;
  458. #endif
  459. }
  460. #if defined(TARGET_WINCE)
  461. /*
  462. #define PBT_TRANSITION      1
  463. #define POWER_STATE(i) ((i)&0xFFFF0000)
  464. #define POWER_STATE_ON 0x00010000
  465. #define POWER_STATE_SUSPEND 0x00200000
  466. typedef struct POWER_BROADCAST
  467. {
  468. DWORD Message;
  469. DWORD Flags;
  470. DWORD Length;
  471. WCHAR SystemPowerState[64];
  472. } POWER_BROADCAST;
  473. static HANDLE Power = NULL;
  474. static HANDLE PowerMsgQueue = NULL;
  475. static HANDLE PowerExitEvent = NULL;
  476. static HANDLE PowerThreadHandle = NULL;
  477. static DWORD WINAPI PowerThread( LPVOID Parameter )
  478. {
  479. DWORD PowerState = POWER_STATE_ON;
  480. POWER_BROADCAST Msg;
  481. DWORD Size;
  482. DWORD Flags;
  483. HANDLE Handles[2];
  484. Handles[0] = PowerExitEvent;
  485. Handles[1] = PowerMsgQueue;
  486. for (;;)
  487. {
  488. DWORD Result = WaitForMultipleObjects(2, Handles, FALSE, INFINITE);
  489. if (Result == WAIT_OBJECT_0 || Result == WAIT_ABANDONED_0)
  490. break;
  491. if (FuncReadMsgQueue(PowerMsgQueue,&Msg,sizeof(Msg),&Size,0,&Flags))
  492. {
  493. if (Size >= sizeof(DWORD)*2 && Msg.Message == PBT_TRANSITION && Msg.Flags &&
  494. PowerState != POWER_STATE(Msg.Flags))
  495. {
  496. PowerState = POWER_STATE(Msg.Flags);
  497. if (PowerState == POWER_STATE_ON || PowerState == POWER_STATE_SUSPEND)
  498. {
  499. bool_t b = PowerState == POWER_STATE_SUSPEND;
  500. node* Player = Context()->Player;
  501. if (Player)
  502. Player->Set(Player,PLAYER_POWEROFF,&b,sizeof(b));
  503. }
  504. }
  505. }
  506. }
  507. return 0;
  508. }
  509. static void Power_Init()
  510. {
  511. DWORD Id;
  512. MSGQUEUEOPTIONS2 MsgOpt;
  513. if (FuncRequestPowerNotifications && FuncReadMsgQueue && FuncStopPowerNotifications &&
  514. FuncCreateMsgQueue && FuncCloseMsgQueue)
  515. {
  516. memset(&MsgOpt,0,sizeof(MsgOpt));
  517. MsgOpt.dwSize = sizeof(MsgOpt);
  518. MsgOpt.dwFlags = 0;
  519. MsgOpt.dwMaxMessages = 8;
  520. MsgOpt.cbMaxMessage = sizeof(POWER_BROADCAST);
  521. MsgOpt.bReadAccess = TRUE;
  522. PowerExitEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
  523. if (PowerExitEvent)
  524. {
  525. PowerMsgQueue = FuncCreateMsgQueue(NULL,&MsgOpt);
  526. if (PowerMsgQueue)
  527. {
  528. Power = FuncRequestPowerNotifications(PowerMsgQueue,PBT_TRANSITION);
  529. if (Power)
  530. PowerThreadHandle = CreateThread(NULL,0,PowerThread,0,0,&Id);
  531. }
  532. }
  533. }
  534. }
  535. static void Power_Done()
  536. {
  537. if (PowerThreadHandle)
  538. {
  539. SetEvent(PowerExitEvent);
  540. if (WaitForSingleObject(PowerThreadHandle,1000) == WAIT_TIMEOUT)
  541. TerminateThread(PowerThreadHandle,0);
  542. PowerThreadHandle = NULL;
  543. }
  544. if (Power)
  545. {
  546. FuncStopPowerNotifications(Power);
  547. Power = NULL;
  548. }
  549. if (PowerMsgQueue)
  550. {
  551. FuncCloseMsgQueue(PowerMsgQueue);
  552. PowerMsgQueue = NULL;
  553. }
  554. if (PowerExitEvent)
  555. {
  556. CloseHandle(PowerExitEvent);
  557. PowerExitEvent = NULL;
  558. }
  559. }
  560. */
  561. static void Power_Init() {}
  562. static void Power_Done() {}
  563. #endif
  564. void Platform_Init()
  565. {
  566. #if defined(TARGET_WINCE)
  567. AygShellDLL = LoadLibrary(T("aygshell.dll"));
  568. if (AygShellDLL)
  569. *(FARPROC*)&FuncSHIdleTimerReset = GetProcAddress(AygShellDLL,MAKEINTRESOURCE(2006));
  570. CoreDLL = LoadLibrary(T("coredll.dll"));
  571. if (CoreDLL)
  572. {
  573. *(FARPROC*)&FuncChangeDisplaySettingsEx = GetProcAddress(CoreDLL,T("ChangeDisplaySettingsEx"));
  574. *(FARPROC*)&FuncCeSetThreadQuantum = GetProcAddress(CoreDLL,T("CeSetThreadQuantum"));
  575. *(FARPROC*)&FuncSetKMode = GetProcAddress(CoreDLL,T("SetKMode"));
  576. *(FARPROC*)&FuncRedrawWindow = GetProcAddress(CoreDLL,T("RedrawWindow"));
  577. *(FARPROC*)&FuncSHGetSpecialFolderPath = GetProcAddress(CoreDLL,T("SHGetSpecialFolderPath"));
  578. *(FARPROC*)&FuncSetPowerRequirement = GetProcAddress(CoreDLL,T("SetPowerRequirement"));
  579. *(FARPROC*)&FuncReleasePowerRequirement = GetProcAddress(CoreDLL,T("ReleasePowerRequirement"));
  580. *(FARPROC*)&FuncSetDevicePower = GetProcAddress(CoreDLL,T("SetDevicePower"));
  581. *(FARPROC*)&FuncGetDevicePower = GetProcAddress(CoreDLL,T("GetDevicePower"));
  582. *(FARPROC*)&FuncReadMsgQueue = GetProcAddress(CoreDLL,T("ReadMsgQueue"));
  583. *(FARPROC*)&FuncCreateMsgQueue = GetProcAddress(CoreDLL,T("CreateMsgQueue"));
  584. *(FARPROC*)&FuncCloseMsgQueue = GetProcAddress(CoreDLL,T("CloseMsgQueue"));
  585. *(FARPROC*)&FuncRequestPowerNotifications = GetProcAddress(CoreDLL,T("RequestPowerNotifications"));
  586. *(FARPROC*)&FuncStopPowerNotifications = GetProcAddress(CoreDLL,T("StopPowerNotifications"));
  587. }
  588. CEShellDLL = LoadLibrary(T("ceshell.dll"));
  589. if (CEShellDLL)
  590. *(FARPROC*)&FuncSHGetDocumentsFolder = GetProcAddress(CEShellDLL,MAKEINTRESOURCE(75));
  591. SystemPath[0] = 0;
  592. if (FuncSHGetSpecialFolderPath)
  593. FuncSHGetSpecialFolderPath(NULL,SystemPath,0x24/*CSIDL_WINDOWS*/,FALSE);
  594. DocumentPath[0] = 0;
  595. if (FuncSHGetDocumentsFolder)
  596. FuncSHGetDocumentsFolder(T("\"),DocumentPath);
  597. BacklightEvent = CreateEvent(NULL, FALSE, FALSE, T("TIMEOUTDISPLAYOFF"));
  598. Power_Init();
  599. #endif
  600. if (!Context()->CodePage)
  601. Context()->CodePage = CP_ACP; //CP_OEMCP;
  602. NodeRegisterClass(&Platform);
  603. Context()->Platform = NodeEnumObject(NULL,PLATFORM_ID);
  604. SleepTimeout(0,0); // restore backlight settings (if last time crashed)
  605. File_Init();
  606. DMO_Init();
  607. }
  608. void Platform_Done()
  609. {
  610. File_Done();
  611. DMO_Done();
  612. NodeUnRegisterClass(PLATFORM_ID);
  613. SetDisplayPower(1,0);
  614. SetKeyboardBacklight(1);
  615. #if defined(TARGET_WINCE)
  616. Power_Done();
  617. if (BacklightEvent) CloseHandle(BacklightEvent);
  618. if (AygShellDLL) FreeLibrary(AygShellDLL);
  619. if (CoreDLL) FreeLibrary(CoreDLL);
  620. if (CEShellDLL) FreeLibrary(CEShellDLL);
  621. #endif
  622. }
  623. void Log_Done()
  624. {
  625. if (Debug)
  626. {
  627. StreamClose(Debug);
  628. Debug = NULL;
  629. }
  630. }
  631. void WinUpdate()
  632. {
  633. HWND Wnd = Context()->Wnd;
  634. if (Wnd)
  635. UpdateWindow(Wnd);
  636. }
  637. void WinInvalidate(const rect* Rect, bool_t Local)
  638. {
  639. POINT o;
  640. RECT r;
  641. HWND Wnd = Context()->Wnd;
  642. if (Rect->Height>0 && Rect->Width>0)
  643. {
  644. DEBUG_MSG5(DEBUG_VIDEO,T("Invalidate %d,%d,%d,%d (%d)"),Rect->x,Rect->y,Rect->Width,Rect->Height,Local);
  645. if (Local && Wnd)
  646. {
  647. // only local invalidate
  648. o.x = 0;
  649. o.y = 0;
  650. ClientToScreen(Wnd,&o);
  651. DEBUG_MSG2(DEBUG_VIDEO,T("Invalidate local offset %d,%d"),o.x,o.y);
  652. r.left = Rect->x - o.x;
  653. r.top = Rect->y - o.y;
  654. r.right = r.left + Rect->Width;
  655. r.bottom = r.top + Rect->Height;
  656. InvalidateRect(Wnd,&r,0);
  657. }
  658. else
  659. GlobalInvalidate(Rect);
  660. }
  661. }
  662. void WinValidate(const rect* Rect)
  663. {
  664. POINT o;
  665. RECT r;
  666. HWND Wnd = Context()->Wnd;
  667. if (Rect->Height>0 && Rect->Width>0 && Wnd)
  668. {
  669. DEBUG_MSG4(DEBUG_VIDEO,T("Validate %d,%d,%d,%d"),Rect->x,Rect->y,Rect->Width,Rect->Height);
  670. o.x = 0;
  671. o.y = 0;
  672. ClientToScreen(Wnd,&o);
  673. DEBUG_MSG2(DEBUG_VIDEO,T("Validate offset %d,%d"),o.x,o.y);
  674. r.left = Rect->x - o.x;
  675. r.top = Rect->y - o.y;
  676. r.right = r.left+Rect->Width;
  677. r.bottom = r.top+Rect->Height;
  678. ValidateRect(Wnd,&r);
  679. }
  680. void AdjustOrientation(video* p, bool_t Combine)
  681. {
  682. int Width = GetSystemMetrics(SM_CXSCREEN);
  683. int Height = GetSystemMetrics(SM_CYSCREEN);
  684. int Orientation;
  685. rect Virt;
  686. if ((Width == p->Width*2 && Height == p->Height*2) || 
  687. (Width == p->Height*2 && Height == p->Width*2))
  688. p->Pixel.Flags |= PF_PIXELDOUBLE;
  689. Orientation = GetOrientation();
  690. if (Combine)
  691. p->Direction = CombineDir(0,p->Direction,Orientation);
  692. // still rotated? 
  693. PhyToVirt(NULL,&Virt,p);
  694. if (Width != Height && Virt.Width == Height && Virt.Height == Width)
  695. {
  696. if (Orientation & DIR_MIRRORLEFTRIGHT)
  697. p->Direction ^= DIR_SWAPXY | DIR_MIRRORLEFTRIGHT;
  698. else
  699. p->Direction ^= DIR_SWAPXY | DIR_MIRRORUPDOWN;
  700. }
  701. }
  702. bool_t IsOrientationChanged()
  703. {
  704. int Old = Orientation;
  705. Orientation = -1;
  706. return GetOrientation() != Old;
  707. }
  708. int SetOrientation(int Orientation)
  709. {
  710. return ERR_NOT_SUPPORTED;
  711. }
  712. bool_t GetHandedness()
  713. {
  714. return 0;
  715. }
  716. int GetOrientation()
  717. {
  718. #if defined(TARGET_WINCE)
  719. if (Orientation < 0)
  720. {
  721. HKEY Key;
  722. context* p;
  723. char Buffer[256];
  724. DEVMODE* Mode = (DEVMODE*)Buffer;
  725. Mode->dmSize = 192;
  726. Mode->dmFields = DM_DISPLAYQUERYORIENTATION;
  727. if (QueryPlatform(PLATFORM_VER) >= 421 && // we don't trust this method on pre wm2003se systems
  728. FuncChangeDisplaySettingsEx &&
  729. FuncChangeDisplaySettingsEx(NULL, Mode, NULL, CDS_TEST, NULL) == DISP_CHANGE_SUCCESSFUL)
  730. {
  731. Mode->dmFields = DM_DISPLAYORIENTATION;
  732. FuncChangeDisplaySettingsEx(NULL, Mode, NULL, CDS_TEST, NULL);
  733. switch ((&Mode->dmDisplayFrequency)[1]) //(Mode->dmDisplayOrientation)
  734. {
  735. case DMDO_0: Orientation = 0; break;
  736. case DMDO_90: Orientation = DIR_SWAPXY | DIR_MIRRORUPDOWN; break;
  737. case DMDO_270: Orientation = DIR_SWAPXY | DIR_MIRRORLEFTRIGHT; break;
  738. case DMDO_180: Orientation = DIR_MIRRORUPDOWN | DIR_MIRRORLEFTRIGHT; break;
  739. }
  740. }
  741. p = Context();
  742. if (Orientation < 0 && p->HwOrientation)
  743. Orientation = p->HwOrientation(p->HwOrientationContext);
  744. if (Orientation < 0 && RegOpenKeyEx(HKEY_LOCAL_MACHINE, T("System\GDI\ROTATION"), 0, KEY_READ, &Key) == ERROR_SUCCESS)
  745. {
  746. DWORD Value;
  747. DWORD RegSize = sizeof(Value);
  748. DWORD RegType;
  749. if (RegQueryValueEx(Key, T("Angle"), 0, &RegType, (LPBYTE) &Value, &RegSize) == ERROR_SUCCESS)
  750. switch (Value)
  751. {
  752. case 0: Orientation = 0; break;
  753. case 90: Orientation = DIR_SWAPXY | DIR_MIRRORUPDOWN; break;
  754. case 270: Orientation = DIR_SWAPXY | DIR_MIRRORLEFTRIGHT; break;
  755. case 180: Orientation = DIR_MIRRORUPDOWN | DIR_MIRRORLEFTRIGHT; break;
  756. }
  757. RegCloseKey(Key);
  758. }
  759. if (Orientation < 0)
  760. Orientation = 0;
  761. }
  762. #else
  763. Orientation = 0;
  764. #endif
  765. return Orientation;
  766. }
  767. void QueryDesktop(video* p)
  768. {
  769. HDC DC = GetDC(0);
  770. memset(p,0,sizeof(video));
  771. p->Width = GetDeviceCaps(DC,HORZRES);
  772. p->Height = GetDeviceCaps(DC,VERTRES);
  773. p->Aspect = ASPECT_ONE;
  774. p->Direction = 0;
  775. if (GetDeviceCaps(DC,BITSPIXEL)*GetDeviceCaps(DC,PLANES) <= 8)
  776. {
  777. p->Pixel.Flags = PF_PALETTE;
  778. p->Pixel.BitCount = GetDeviceCaps(DC,BITSPIXEL);
  779. if (p->Pixel.BitCount>4) //4,2,1 bits are grayscale (default palette required)
  780. {
  781. GetSystemPaletteEntries(DC,0,256,(PALETTEENTRY*)Palette);
  782. p->Pixel.Palette = Palette;
  783. }
  784. }
  785. else
  786. if (QueryPlatform(PLATFORM_CAPS) & CAPS_ONLY12BITRGB)
  787. DefaultRGB(&p->Pixel,GetDeviceCaps(DC,BITSPIXEL),4,4,4,1,2,1);
  788. else
  789. {
  790. int i;
  791. int RBits = 4;
  792. int GBits = 4;
  793. int BBits = 4;
  794. int BitCount = GetDeviceCaps(DC,BITSPIXEL);
  795. COLORREF Old = GetPixel(DC,0,0);
  796. for (i=3;i>=0;--i)
  797. {
  798. COLORREF c = SetPixel(DC,0,0,0x010101<<i);
  799. if (c == (COLORREF)-1)
  800. {
  801. if (BitCount > 16)
  802. RBits = GBits = BBits = 8;
  803. else
  804. {
  805. RBits = BBits = 5; GBits = 6;
  806. }
  807. break;
  808. }
  809. if (c & 0xFF)   RBits++;
  810. if (c & 0xFF00)   GBits++;
  811. if (c & 0xFF0000) BBits++;
  812. }
  813. SetPixel(DC,0,0,Old);
  814. DefaultRGB(&p->Pixel,BitCount,RBits,GBits,BBits,0,0,0);
  815. }
  816. ReleaseDC(0,DC);
  817. }
  818. #if defined(TARGET_WINCE)
  819. bool_t KernelMode(bool_t v)
  820. {
  821. if (FuncSetKMode)
  822. return FuncSetKMode(v);
  823. return 0;
  824. }
  825. #endif
  826. bool_t GetKeyboardBacklight()
  827. {
  828. #if defined(TARGET_WINCE)
  829. int DeviceState;
  830. // Treo700w
  831. if (FuncGetDevicePower && FuncGetDevicePower(T("kyl0:"),POWER_NAME,&DeviceState)==ERROR_SUCCESS)
  832. return DeviceState == POWER_D4 ? 0:1;
  833. #endif
  834. return 0;
  835. }
  836. int SetKeyboardBacklight(bool_t State)
  837. {
  838. #if defined(TARGET_WINCE)
  839. if (FuncSetDevicePower)
  840. {
  841. // Treo700w
  842. if (FuncSetDevicePower(T("kyl0:"),POWER_NAME,State?POWER_UNSPEC:POWER_D4)==ERROR_SUCCESS)
  843. return ERR_NONE;
  844. }
  845. #endif
  846. return ERR_NOT_SUPPORTED;
  847. }
  848. bool_t GetDisplayPower()
  849. {
  850. return DisplayPower;
  851. }
  852. int SetDisplayPower(bool_t State,bool_t Force)
  853. {
  854. VIDEO_POWER_MANAGEMENT VPM;
  855. HDC DC;
  856. if (DisplayPower != State || Force)
  857. {
  858. DisplayPower = State;
  859. DC = GetDC(NULL);
  860. VPM.Length = sizeof(VPM);
  861. VPM.DPMSVersion = 1;
  862. VPM.PowerState = State ? 1:4;
  863. ExtEscape(DC, SETPOWERMANAGEMENT, sizeof(VPM), (LPCSTR) &VPM, 0, NULL);
  864. ReleaseDC(NULL, DC);
  865. }
  866. return ERR_NONE;
  867. }
  868. static bool_t ChangeRegEntry(bool_t CurrentUser, const tchar_t* Reg, const tchar_t* Name, bool_t State, int NewValue, int BackupId) 
  869. {
  870. HKEY Key = 0;
  871. DWORD Size;
  872. DWORD Value;
  873. if (RegOpenKeyEx(CurrentUser ? HKEY_CURRENT_USER:HKEY_LOCAL_MACHINE,Reg, 0, KEY_READ|KEY_WRITE, &Key) == ERROR_SUCCESS) 
  874. {
  875. if (State)
  876. {
  877. // save old value 
  878. Size = sizeof(Value);
  879. if (RegQueryValueEx(Key, Name,NULL,NULL,(LPBYTE)&Value,&Size) == ERROR_SUCCESS)
  880. NodeRegSaveValue(0,BackupId,&Value,sizeof(Value),TYPE_INT);
  881. // set no screensaver
  882. Value = NewValue;
  883. Size = sizeof(Value);
  884. RegSetValueEx(Key, Name,0,REG_DWORD,(LPBYTE)&Value,Size);
  885. }
  886. else
  887. if (NodeRegLoadValue(0,BackupId,&Value,sizeof(Value),TYPE_INT))
  888. {
  889. // restore value (and delete old value)
  890. Size = sizeof(Value);
  891. RegSetValueEx(Key, Name,0,REG_DWORD,(LPBYTE)&Value,Size);
  892. NodeRegSaveValue(0,BackupId,NULL,0,0);
  893. }
  894. RegCloseKey(Key);
  895. }
  896. return Key != 0;
  897. }
  898. static BOOL ScreenSaveActive = -1;
  899. static BOOL PowerOffActive = -1;
  900. static BOOL LowPowerActive = -1;
  901. static bool_t BacklightTimeoutDisabled = -1;
  902. void SleepTimerReset()
  903. {
  904. #if defined(TARGET_WINCE)
  905. SystemIdleTimerReset();
  906. if (FuncSHIdleTimerReset)
  907. if (BacklightTimeoutDisabled || !QueryAdvanced(ADVANCED_HOMESCREEN))
  908. FuncSHIdleTimerReset();
  909. if (BacklightTimeoutDisabled)
  910. SetEvent(BacklightEvent);
  911. #endif
  912. }
  913. void SleepTimeout(bool_t KeepProcess,bool_t KeepDisplay)
  914. {
  915. if (!KeepProcess)
  916. KeepDisplay = 0;
  917. if (KeepDisplay && QueryAdvanced(ADVANCED_NOBACKLIGHT))
  918. KeepDisplay = 0;
  919. #if defined(TARGET_WIN32)
  920. if (KeepDisplay)
  921. {
  922. if (ScreenSaveActive == -1)
  923. {
  924. SystemParametersInfo(SPI_GETSCREENSAVEACTIVE,0,&ScreenSaveActive,0);
  925. SystemParametersInfo(SPI_SETSCREENSAVEACTIVE,FALSE,NULL,0);
  926. }
  927. if (PowerOffActive == -1)
  928. {
  929. SystemParametersInfo(SPI_GETPOWEROFFACTIVE,0,&PowerOffActive,0);
  930. SystemParametersInfo(SPI_SETPOWEROFFACTIVE,FALSE,NULL,0);
  931. }
  932. if (LowPowerActive == -1)
  933. {
  934. SystemParametersInfo(SPI_GETLOWPOWERACTIVE,0,&LowPowerActive,0);
  935. SystemParametersInfo(SPI_SETLOWPOWERACTIVE,FALSE,NULL,0);
  936. }
  937. }
  938. else
  939. {
  940. if (ScreenSaveActive != -1)
  941. {
  942. SystemParametersInfo(SPI_SETSCREENSAVEACTIVE,ScreenSaveActive,NULL,0);
  943. ScreenSaveActive = -1;
  944. }
  945. if (PowerOffActive != -1)
  946. {
  947. SystemParametersInfo(SPI_SETPOWEROFFACTIVE,PowerOffActive,NULL,0);
  948. PowerOffActive = -1;
  949. }
  950. if (LowPowerActive != -1)
  951. {
  952. SystemParametersInfo(SPI_SETLOWPOWERACTIVE,LowPowerActive,NULL,0);
  953. LowPowerActive = -1;
  954. }
  955. }
  956. #endif
  957. if (KeepDisplay != BacklightTimeoutDisabled)
  958. {
  959. HANDLE Handle;
  960. int Value;
  961. int Model = QueryPlatform(PLATFORM_MODEL);
  962. BacklightTimeoutDisabled = KeepDisplay;
  963. #ifdef MIPS
  964. if (Model == MODEL_CASIO_E125 ||
  965. Model == MODEL_CASIO_EM500 ||
  966. Model == MODEL_CASIO_E115 ||
  967. Model == MODEL_CASIO_BE300 ||
  968. Model == MODEL_CASIO_E105)
  969. {
  970. Value = 0;
  971. ChangeRegEntry(0,RegCASIOBacklight,RegTimeoutBattery,KeepDisplay,Value,REG_BATTERYTIMEOUT);
  972. ChangeRegEntry(0,RegCASIOBacklight,RegTimeoutExPower,KeepDisplay,Value,REG_ACTIMEOUT);
  973. }
  974. else
  975. #endif
  976. {
  977. Value = (QueryPlatform(PLATFORM_TYPENO) == TYPE_SMARTPHONE) ? 7199999 /*10*3600*1000*/ : 0x7FFFFFFF;
  978. if (Model == MODEL_AXIM_X5) 
  979. Value = 0;
  980. ChangeRegEntry(1,RegScreenSaver,RegMode,KeepDisplay,1,REG_SCREENSAVER);
  981. ChangeRegEntry(1,RegBacklight,RegBatteryTimeout,KeepDisplay,Value,REG_BATTERYTIMEOUT);
  982. ChangeRegEntry(1,RegBacklight,RegACTimeout,KeepDisplay,Value,REG_ACTIMEOUT);
  983. ChangeRegEntry(1,RegPower,RegDisplay,KeepDisplay,-1,REG_DISPPOWER);
  984. // just in case try HKEY_LOCAL_MACHINE as well 
  985. ChangeRegEntry(0,RegBacklight,RegBatteryTimeout,KeepDisplay,Value,REG_BATTERYTIMEOUT2);
  986. ChangeRegEntry(0,RegBacklight,RegACTimeout,KeepDisplay,Value,REG_ACTIMEOUT2);
  987. }
  988. Handle = CreateEvent(NULL, FALSE, FALSE, T("BackLightChangeEvent"));
  989. if (Handle) 
  990. {
  991. SetEvent(Handle);
  992. CloseHandle(Handle);
  993. }
  994. // support for sample Power Manager implementation 
  995. // maybe if they use the sample code, there might be bugs with SystemIdleTimerReset()...
  996. if (ChangeRegEntry(0,RegPowerTimouts,RegACUserIdle,KeepDisplay,0,REG_ACUSERIDLE))
  997. {
  998. ChangeRegEntry(0,RegPowerTimouts,RegBattUserIdle,KeepDisplay,0,REG_BATTUSERIDLE);
  999. ChangeRegEntry(0,RegPowerTimouts,RegACSystemIdle,KeepDisplay,0,REG_ACSYSTEMIDLE);
  1000. ChangeRegEntry(0,RegPowerTimouts,RegBattSystemIdle,KeepDisplay,0,REG_BATTSYSTEMIDLE);
  1001. ChangeRegEntry(0,RegPowerTimouts,RegACSuspend,KeepDisplay,0,REG_ACSUSPEND);
  1002. ChangeRegEntry(0,RegPowerTimouts,RegBattSuspend,KeepDisplay,0,REG_BATTSUSPEND);
  1003. Handle = CreateEvent(NULL, FALSE, FALSE, T("PowerManager/ReloadActivityTimeouts"));
  1004. if (Handle) 
  1005. {
  1006. SetEvent(Handle);
  1007. CloseHandle(Handle);
  1008. }
  1009. }
  1010. #if defined(TARGET_WINCE)
  1011. if (FuncSetPowerRequirement && FuncReleasePowerRequirement)
  1012. {
  1013. if (KeepDisplay && !PowerHandle)
  1014. {
  1015. PowerHandle = FuncSetPowerRequirement(T("BKL1:"),POWER_D0,POWER_NAME,NULL,0);
  1016. }
  1017. else if (!KeepDisplay && PowerHandle)
  1018. {
  1019. FuncReleasePowerRequirement(PowerHandle);
  1020. PowerHandle = NULL;
  1021. }
  1022. }
  1023. #endif
  1024. }
  1025. }
  1026. void _Assert(const char* Exp,const char* File,int Line)
  1027. {
  1028. TCHAR TExp[MAXPATH];
  1029. TCHAR TFile[MAXPATH];
  1030. AsciiToTcs(TExp,TSIZEOF(TExp),File);
  1031. stprintf_s(TFile,TSIZEOF(TFile),T("%s:%d"),TExp,Line);
  1032. AsciiToTcs(TExp,TSIZEOF(TExp),Exp);
  1033. #ifndef NDEBUG
  1034. DebugBreak();
  1035. #endif
  1036. MessageBox(NULL,TExp,TFile,MB_OK);
  1037. }
  1038. void* BrushCreate(rgbval_t Color) { return CreateSolidBrush(Color); }
  1039. void BrushDelete(void* Handle) { if (Handle) DeleteObject((HGDIOBJ)Handle); }
  1040. void WinFill(void* DC,rect* Rect,rect* Exclude,void* Brush)
  1041. {
  1042. RECT r;
  1043. if (Exclude)
  1044. ExcludeClipRect(DC,Exclude->x,Exclude->y,Exclude->x + Exclude->Width,Exclude->y + Exclude->Height);
  1045. r.left = Rect->x;
  1046. r.top = Rect->y;
  1047. r.right = Rect->x + Rect->Width;
  1048. r.bottom = Rect->y + Rect->Height;
  1049. FillRect(DC,&r,(HBRUSH)Brush);
  1050. }
  1051. void ShowMessage(const tchar_t* Title,const tchar_t* Msg,...)
  1052. {
  1053. bool_t Wait = WaitCursor;
  1054. tchar_t s[1024];
  1055. va_list Args;
  1056. va_start(Args,Msg);
  1057. vstprintf_s(s,TSIZEOF(s),Msg,Args);
  1058. va_end(Args);
  1059. if (Wait) WaitEnd();
  1060. MessageBox(NULL,s,Title,MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
  1061. if (Wait) WaitBegin();
  1062. }
  1063. void DebugMessage(const tchar_t* Msg,...)
  1064. {
  1065. va_list Args;
  1066. tchar_t s[1024];
  1067. #ifndef NDEBUG
  1068. if (!Debug)
  1069. Debug = StreamOpen(T("\debug.txt"),1);
  1070. #else
  1071. if (!Debug)
  1072. {
  1073. GetDebugPath(s,TSIZEOF(s),T("log.txt"));
  1074. Debug = StreamOpen(s,1);
  1075. }
  1076. #endif
  1077. s[0]=0;
  1078. #if 0
  1079. //#ifdef NDEBUG
  1080. {
  1081. //SYSTEMTIME t;
  1082. //GetSystemTime(&t);
  1083. //stprintf(s+tcslen(s), T("%02d:%02d:%02d "),t.wHour,t.wMinute,t.wSecond);
  1084. int min,sec;
  1085. int t = GetTickCount();
  1086. min = t / 60000;
  1087. t -= min*60000;
  1088. sec = t / 1000;
  1089. t -= sec*1000;
  1090. stcatprintf_s(s,TSIZEOF(s),T("%02d:%02d.%03d "),min,sec,t);
  1091. }
  1092. #endif
  1093. #ifndef NDEBUG
  1094. // stprintf_s(s,TSIZEOF(s),T("%04x "),(int)GetCurrentThreadId());
  1095. #endif
  1096. va_start(Args,Msg);
  1097. vstprintf_s(s+tcslen(s),TSIZEOF(s)-tcslen(s), Msg, Args);
  1098. va_end(Args);
  1099. tcscat_s(s,TSIZEOF(s),T("n"));
  1100. #ifndef NDEBUG
  1101. OutputDebugString(s);
  1102. #endif
  1103. StreamPrintf(Debug,T("%s"),s);
  1104. }
  1105. typedef struct contextreg
  1106. {
  1107. int Ofs;
  1108. const tchar_t* Name;
  1109. } contextreg;
  1110. #if defined(_M_IX86)
  1111. static contextreg Reg[] = 
  1112. {
  1113. OFS(CONTEXT,Eax), T("eax"),
  1114. OFS(CONTEXT,Ebx), T("ebx"),
  1115. OFS(CONTEXT,Ecx), T("ecx"),
  1116. OFS(CONTEXT,Edx), T("edx"),
  1117. OFS(CONTEXT,Esi), T("esi"),
  1118. OFS(CONTEXT,Edi), T("edi"),
  1119. OFS(CONTEXT,Ebp), T("ebp"),
  1120. OFS(CONTEXT,Esp), T("esp"),
  1121. OFS(CONTEXT,Eip), T("eip"),
  1122. OFS(CONTEXT,EFlags), T("flags"),
  1123. OFS(CONTEXT,Esp), NULL, 
  1124. };
  1125. #elif defined(MIPS)
  1126. static contextreg Reg[] = 
  1127. {
  1128. OFS(CONTEXT,IntZero), T("Zero"),
  1129. OFS(CONTEXT,IntAt), T("At"),
  1130. OFS(CONTEXT,IntV0), T("V0"),
  1131. OFS(CONTEXT,IntV1), T("V1"),
  1132. OFS(CONTEXT,IntA0), T("A0"),
  1133. OFS(CONTEXT,IntA1), T("A1"),
  1134. OFS(CONTEXT,IntA2), T("A2"),
  1135. OFS(CONTEXT,IntA3), T("A3"),
  1136. OFS(CONTEXT,IntT0), T("T0"),
  1137. OFS(CONTEXT,IntT1), T("T1"),
  1138. OFS(CONTEXT,IntT2), T("T2"),
  1139. OFS(CONTEXT,IntT3), T("T3"),
  1140. OFS(CONTEXT,IntT4), T("T4"),
  1141. OFS(CONTEXT,IntT5), T("T5"),
  1142. OFS(CONTEXT,IntT6), T("T6"),
  1143. OFS(CONTEXT,IntT7), T("T7"),
  1144. OFS(CONTEXT,IntS0), T("S0"),
  1145. OFS(CONTEXT,IntS1), T("S1"),
  1146. OFS(CONTEXT,IntS2), T("S2"),
  1147. OFS(CONTEXT,IntS3), T("S3"),
  1148. OFS(CONTEXT,IntS4), T("S4"),
  1149. OFS(CONTEXT,IntS5), T("S5"),
  1150. OFS(CONTEXT,IntS6), T("S6"),
  1151. OFS(CONTEXT,IntS7), T("S7"),
  1152. OFS(CONTEXT,IntT8), T("T8"),
  1153. OFS(CONTEXT,IntT9), T("T9"),
  1154. OFS(CONTEXT,IntK0), T("K0"),
  1155. OFS(CONTEXT,IntK1), T("K1"),
  1156. OFS(CONTEXT,IntGp), T("Gp"),
  1157. OFS(CONTEXT,IntSp), T("Sp"),
  1158. OFS(CONTEXT,IntS8), T("S8"),
  1159. OFS(CONTEXT,IntRa), T("Ra"),
  1160. OFS(CONTEXT,IntLo), T("Lo"),
  1161. OFS(CONTEXT,IntHi), T("Hi"),
  1162. OFS(CONTEXT,IntSp), NULL,
  1163. };
  1164. #elif defined(ARM)
  1165. static contextreg Reg[] = 
  1166. {
  1167. OFS(CONTEXT,R0), T("R0"),
  1168. OFS(CONTEXT,R1), T("R1"),
  1169. OFS(CONTEXT,R2), T("R2"),
  1170. OFS(CONTEXT,R3), T("R3"),
  1171. OFS(CONTEXT,R4), T("R4"),
  1172. OFS(CONTEXT,R5), T("R5"),
  1173. OFS(CONTEXT,R6), T("R6"),
  1174. OFS(CONTEXT,R7), T("R7"),
  1175. OFS(CONTEXT,R8), T("R8"),
  1176. OFS(CONTEXT,R9), T("R9"),
  1177. OFS(CONTEXT,R10),T("R10"),
  1178. OFS(CONTEXT,R11),T("R11"),
  1179. OFS(CONTEXT,R12),T("R12"),
  1180. OFS(CONTEXT,Sp), T("Sp"),
  1181. OFS(CONTEXT,Lr), T("Lr"),
  1182. OFS(CONTEXT,Pc), T("Pc"),
  1183. OFS(CONTEXT,Psr),T("Psr"),
  1184. OFS(CONTEXT,Sp), NULL,
  1185. };
  1186. #elif defined(SH3)
  1187. static contextreg Reg[] = 
  1188. {
  1189. OFS(CONTEXT,PR), T("PR"),
  1190. OFS(CONTEXT,MACH), T("MACH"),
  1191. OFS(CONTEXT,MACL), T("MACL"),
  1192. OFS(CONTEXT,GBR), T("GBR"),
  1193. OFS(CONTEXT,R0), T("R0"),
  1194. OFS(CONTEXT,R1), T("R1"),
  1195. OFS(CONTEXT,R2), T("R2"),
  1196. OFS(CONTEXT,R3), T("R3"),
  1197. OFS(CONTEXT,R4), T("R4"),
  1198. OFS(CONTEXT,R5), T("R5"),
  1199. OFS(CONTEXT,R6), T("R6"),
  1200. OFS(CONTEXT,R7), T("R7"),
  1201. OFS(CONTEXT,R8), T("R8"),
  1202. OFS(CONTEXT,R9), T("R9"),
  1203. OFS(CONTEXT,R10), T("R10"),
  1204. OFS(CONTEXT,R11), T("R11"),
  1205. OFS(CONTEXT,R12), T("R12"),
  1206. OFS(CONTEXT,R13), T("R13"),
  1207. OFS(CONTEXT,R14), T("R14"),
  1208. OFS(CONTEXT,R15), T("R15"),
  1209. OFS(CONTEXT,R15), NULL,
  1210. };
  1211. #else
  1212. static contextreg Reg[] = { -1, NULL };
  1213. #endif
  1214. void FindFiles(const tchar_t* Path, const tchar_t* Mask,void(*Process)(const tchar_t*,void*),void* Param)
  1215. {
  1216. WIN32_FIND_DATA FindData;
  1217. tchar_t FindPath[MAXPATH];
  1218. HANDLE Find;
  1219. tcscpy_s(FindPath,TSIZEOF(FindPath),Path);
  1220. tcscat_s(FindPath,TSIZEOF(FindPath),Mask);
  1221. Find = FindFirstFile(FindPath,&FindData);
  1222. if (Find != INVALID_HANDLE_VALUE)
  1223. {
  1224. do
  1225. {
  1226. tcscpy_s(FindPath,TSIZEOF(FindPath),Path);
  1227. tcscat_s(FindPath,TSIZEOF(FindPath),FindData.cFileName);
  1228. Process(FindPath,Param);
  1229. }
  1230. while (FindNextFile(Find,&FindData));
  1231. FindClose(Find);
  1232. }
  1233. }
  1234. void GetModulePath(tchar_t* Path,const tchar_t* Module)
  1235. {
  1236. tchar_t* s;
  1237. HANDLE Handle = NULL;
  1238. if (Module)
  1239. Handle = GetModuleHandle(Module);
  1240. GetModuleFileName(Handle,Path,MAXPATH);
  1241. s = tcsrchr(Path,'\');
  1242. if (s) s[1]=0;
  1243. }
  1244. void GetDebugPath(tchar_t* Path, int PathLen, const tchar_t* FileName)
  1245. {
  1246. stprintf_s(Path,PathLen,T("%s\%s"),DocumentPath,FileName);
  1247. }
  1248. void GetSystemPath(tchar_t* Path, int PathLen, const tchar_t* FileName)
  1249. {
  1250. stprintf_s(Path,PathLen,T("%s\%s"),SystemPath,FileName);
  1251. }
  1252. int64_t GetTimeDate()
  1253. {
  1254. SYSTEMTIME t;
  1255. GetSystemTime(&t);
  1256. return (((t.wHour*100)+t.wMinute)*100+t.wSecond)*1000 +
  1257. (int64_t)(((t.wYear*100)+t.wMonth)*100+t.wDay) * 1000000000;
  1258. }
  1259. bool_t SaveDocument(const tchar_t* Name, const tchar_t* Text,tchar_t* URL,int URLLen)
  1260. {
  1261. stream* f;
  1262. stprintf_s(URL,URLLen,T("%s\%s.txt"),DocumentPath,Name);
  1263. f = StreamOpen(URL,1);
  1264. if (!f)
  1265. return 0;
  1266. StreamText(f,Text,0);
  1267. StreamClose(f);
  1268. return 1;
  1269. }
  1270. int SafeException(void* p)
  1271. {
  1272. EXCEPTION_POINTERS* Data = (EXCEPTION_POINTERS*)p;
  1273. stream* File;
  1274. tchar_t Path[MAXPATH];
  1275. if (Context())
  1276. {
  1277. GetDebugPath(Path,TSIZEOF(Path),T("crash.txt"));
  1278. File = StreamOpen(Path,1);
  1279. if (File)
  1280. {
  1281. void** Stack;
  1282. contextreg* r;
  1283. int No;
  1284. const uint8_t* ContextRecord = (const uint8_t*) Data->ContextRecord;
  1285. EXCEPTION_RECORD* Record = Data->ExceptionRecord;
  1286. tchar_t* Name;
  1287. int DllBase;
  1288. tchar_t DllName[MAXPATH];
  1289. StreamPrintf(File,T("%s %s crash reportn----------------------------n"),
  1290. Context()->ProgramName,Context()->ProgramVersion);
  1291. switch (Record->ExceptionCode)
  1292. {
  1293. case STATUS_ACCESS_VIOLATION: Name = T("Access violation"); break;
  1294. case STATUS_BREAKPOINT: Name = T("Breakpoint"); break;
  1295. case STATUS_DATATYPE_MISALIGNMENT: Name = T("Datatype misalignment"); break;
  1296. case STATUS_ILLEGAL_INSTRUCTION: Name = T("Illegal instruction"); break;
  1297. case STATUS_INTEGER_DIVIDE_BY_ZERO: Name = T("Int divide by zero"); break;
  1298. case STATUS_INTEGER_OVERFLOW: Name = T("Int overflow"); break;
  1299. case STATUS_PRIVILEGED_INSTRUCTION: Name = T("Priv instruction"); break;
  1300. case STATUS_STACK_OVERFLOW: Name = T("Stack overflow"); break;
  1301. default: Name = T("Unknown"); break;
  1302. }
  1303. if (!NodeLocatePtr(Record->ExceptionAddress,DllName,TSIZEOF(DllName),&DllBase))
  1304. {
  1305. DllName[0] = 0;
  1306. DllBase = (int)Record->ExceptionAddress;
  1307. }
  1308. StreamPrintf(File,T("%s(%08x) at %08x (%s:%08x)"),Name,Record->ExceptionCode,Record->ExceptionAddress,DllName,DllBase);
  1309. if (Record->ExceptionCode == STATUS_ACCESS_VIOLATION)
  1310. {
  1311. if (Record->ExceptionInformation[0])
  1312. Name = T("Write to");
  1313. else
  1314. Name = T("Read from");
  1315. StreamPrintf(File,T("n%s %08x"),Name,Record->ExceptionInformation[1]);
  1316. if (NodeLocatePtr((void*)Record->ExceptionInformation[1],DllName,TSIZEOF(DllName),&DllBase))
  1317. StreamPrintf(File,T(" (%s:%08x)"),DllName,DllBase);
  1318. }
  1319. // context
  1320. StreamPrintf(File,T("nncpu dump:"));
  1321. for (r=Reg;r->Name;++r)
  1322. {
  1323. void* Ptr = *(void**)(ContextRecord+r->Ofs);
  1324. StreamPrintf(File,T("n%-5s = %08x"),r->Name,Ptr);
  1325. if (NodeLocatePtr(Ptr,DllName,TSIZEOF(DllName),&DllBase))
  1326. StreamPrintf(File,T(" (%s:%08x)"),DllName,DllBase);
  1327. }
  1328. if (r->Ofs >= 0)
  1329. {
  1330. StreamPrintf(File,T("nnstack dump:"));
  1331. Stack = *(void***)(ContextRecord+r->Ofs);
  1332. for (No=0;No<256;++No,++Stack)
  1333. {
  1334. if (!IsBadReadPtr(Stack,sizeof(void*)))
  1335. {
  1336. void* Ptr = *Stack;
  1337. StreamPrintf(File,T("n%08x %08x"),Stack,Ptr);
  1338. if (NodeLocatePtr(Ptr,DllName,TSIZEOF(DllName),&DllBase))
  1339. StreamPrintf(File,T(" (%s:%08x)"),DllName,DllBase);
  1340. }
  1341. else
  1342. StreamPrintf(File,T("n%08x ????????"),Stack);
  1343. }
  1344. }
  1345. StreamPrintf(File,T("nn"));
  1346. TRY_BEGIN 
  1347. {
  1348. NodeBroadcast(NODE_CRASH,NULL,0);
  1349. }
  1350. TRY_END
  1351. NodeDump(File);
  1352. StreamClose(File);
  1353. }
  1354. MessageBox(NULL,LangStr(PLATFORM_ID,PLATFORM_CRASH_MESSAGE),
  1355. LangStr(PLATFORM_ID,PLATFORM_CRASH_TITLE),MB_OK|MB_SETFOREGROUND|MB_TOPMOST|MB_ICONSTOP);
  1356. }
  1357. Mem_Done(); // use safevirtualfree (if done by OS, it could be buggy on O2 Atom)
  1358. TerminateProcess(GetCurrentProcess(),1);
  1359. return 1;
  1360. }
  1361. void TryInvalidate(HWND Wnd, RECT* r0)
  1362. {
  1363. RECT r;
  1364. if (IsWindowVisible(Wnd))
  1365. {
  1366. GetWindowRect(Wnd,&r);
  1367. if (r0->left < r.right && r0->right > r.left &&
  1368. r0->top < r.bottom && r0->bottom > r.top)
  1369. {
  1370. // window is visible and intersects with r0
  1371. HWND Child;
  1372. POINT o;
  1373. o.x = o.y = 0;
  1374. ClientToScreen(Wnd,&o);
  1375. r.left = r0->left - o.x;
  1376. r.right = r0->right - o.x;
  1377. r.top = r0->top - o.y;
  1378. r.bottom = r0->bottom - o.y;
  1379. InvalidateRect(Wnd,&r,0);
  1380. Child = GetWindow(Wnd,GW_CHILD);
  1381. while (Child && IsWindow(Child))
  1382. {
  1383. TryInvalidate(Child,r0);
  1384. Child = GetWindow(Child,GW_HWNDNEXT);
  1385. }
  1386. }
  1387. }
  1388. }
  1389. BOOL CALLBACK EnumInvalidate(HWND Wnd, LPARAM lParam)
  1390. {
  1391. TryInvalidate(Wnd,(RECT*)lParam);
  1392. return 1;
  1393. }
  1394. void GlobalInvalidate(const rect* Rect)
  1395. {
  1396. RECT r;
  1397. r.left = Rect->x;
  1398. r.top = Rect->y;
  1399. r.right = r.left + Rect->Width;
  1400. r.bottom = r.top + Rect->Height;
  1401. #if defined(TARGET_WINCE)
  1402. if (FuncRedrawWindow) // doesn't work for mio558???
  1403. FuncRedrawWindow(NULL,&r,NULL,0x0001|0x0080); //RDW_INVALIDATE|RDW_ALLCHILDREN
  1404. else
  1405. EnumWindows(EnumInvalidate,(LPARAM)&r);
  1406. #else
  1407. RedrawWindow(NULL,&r,NULL,RDW_INVALIDATE|RDW_ALLCHILDREN);
  1408. #endif
  1409. }
  1410. void HotKeyToString(tchar_t* Out, size_t OutLen, int HotKey)
  1411. {
  1412. int Id = 0;
  1413. Out[0] = 0;
  1414. if (HotKey)
  1415. {
  1416. bool_t Keep = (HotKey & HOTKEY_KEEP) != 0;
  1417. if ((HotKey & HOTKEY_MASK) < 0xC1 || (HotKey & HOTKEY_MASK) > 0xCF)
  1418. {
  1419. if (HotKey & HOTKEY_WIN) { tcscat_s(Out,OutLen,LangStr(PLATFORM_ID,PLATFORM_KEY_WIN)); tcscat_s(Out,OutLen,T("+")); }
  1420. if (HotKey & HOTKEY_SHIFT) { tcscat_s(Out,OutLen,LangStr(PLATFORM_ID,PLATFORM_KEY_SHIFT)); tcscat_s(Out,OutLen,T("+")); }
  1421. if (HotKey & HOTKEY_CTRL) { tcscat_s(Out,OutLen,LangStr(PLATFORM_ID,PLATFORM_KEY_CTRL)); tcscat_s(Out,OutLen,T("+")); }
  1422. if (HotKey & HOTKEY_ALT) { tcscat_s(Out,OutLen,LangStr(PLATFORM_ID,PLATFORM_KEY_ALT)); tcscat_s(Out,OutLen,T("+")); }
  1423. }
  1424. HotKey &= HOTKEY_MASK;
  1425. if ((HotKey >= '0' && HotKey <= '9') ||
  1426. (HotKey >= 'A' && HotKey <= 'Z'))
  1427. stcatprintf_s(Out,OutLen,T("%c"),HotKey);
  1428. else
  1429. if (HotKey >= 0x70 && HotKey < 0x80)
  1430. stcatprintf_s(Out,OutLen,T("F%d"),HotKey-0x70+1);
  1431. else
  1432. switch (HotKey)
  1433. {
  1434. case 0x86:
  1435. Id = PLATFORM_KEY_ACTION;
  1436. break;
  1437. case VK_RETURN:
  1438. Id = PLATFORM_KEY_ENTER;
  1439. break;
  1440. case VK_ESCAPE:
  1441. Id = PLATFORM_KEY_ESCAPE;
  1442. break;
  1443. case VK_LEFT:
  1444. Id = PLATFORM_KEY_LEFT;
  1445. break;
  1446. case VK_RIGHT:
  1447. Id = PLATFORM_KEY_RIGHT;
  1448. break;
  1449. case VK_UP:
  1450. Id = PLATFORM_KEY_UP;
  1451. break;
  1452. case VK_DOWN:
  1453. Id = PLATFORM_KEY_DOWN;
  1454. break;
  1455. case VK_SPACE:
  1456. Id = PLATFORM_KEY_SPACE;
  1457. break;
  1458. case 0xC1:
  1459. case 0xC2:
  1460. case 0xC3:
  1461. case 0xC4:
  1462. case 0xC5:
  1463. case 0xC6:
  1464. case 0xC7:
  1465. case 0xC8:
  1466. case 0xC9:
  1467. case 0xCA:
  1468. case 0xCB:
  1469. case 0xCC:
  1470. case 0xCD:
  1471. case 0xCE:
  1472. case 0xCF:
  1473. stcatprintf_s(Out,OutLen,LangStr(PLATFORM_ID,PLATFORM_KEY_APP),HotKey-0xC0);
  1474. break;
  1475. case 0xB0:
  1476. Id = PLATFORM_KEY_NEXT;
  1477. break;
  1478. case 0xB1:
  1479. Id = PLATFORM_KEY_PREV;
  1480. break;
  1481. case 0xB2:
  1482. Id = PLATFORM_KEY_STOP;
  1483. break;
  1484. case 0xB3:
  1485. Id = PLATFORM_KEY_PLAY;
  1486. break;
  1487. default:
  1488. stcatprintf_s(Out,OutLen,T("#%02X"),HotKey);
  1489. break;
  1490. }
  1491. if (Id)
  1492. tcscat_s(Out,OutLen,LangStr(PLATFORM_ID,Id));
  1493. if (Keep) { tcscat_s(Out,OutLen,T("*")); }
  1494. }
  1495. }
  1496. void WaitDisable(bool_t v)
  1497. {
  1498. WaitCursorDisable = v;
  1499. if (v && WaitCursor)
  1500. WaitEnd();
  1501. }
  1502. bool_t WaitBegin()
  1503. {
  1504. //DEBUG_MSG(DEBUG_SYS,T("WaitBegin"));
  1505. if (WaitCursorDisable)
  1506. return 0;
  1507. SetCursor(LoadCursor (NULL, IDC_WAIT));
  1508. WaitCursor = 1;
  1509. return 1;
  1510. }
  1511. void WaitEnd()
  1512. {
  1513. //DEBUG_MSG(DEBUG_SYS,T("WaitEnd"));
  1514. SetCursor(LoadCursor (NULL, IDC_ARROW));
  1515. WaitCursor = 0;
  1516. }
  1517. bool_t CheckModule(const tchar_t* Name)
  1518. {
  1519. DWORD RegType;
  1520. DWORD RegSize;
  1521. DWORD Disp;
  1522. void* Module;
  1523. tchar_t Path[MAXPATH];
  1524. HKEY Key = NULL;
  1525. if (!Name[0])
  1526. return 0;
  1527. RegSize = sizeof(Path);
  1528. stprintf_s(Path,TSIZEOF(Path),T("SOFTWARE\%s\DLLPath"),Context()->ProgramName);
  1529. if (RegCreateKeyEx(HKEY_ROOT, Path, 0, NULL, 0, KEY_READ|KEY_WRITE, NULL, &Key, &Disp) == ERROR_SUCCESS)
  1530. {
  1531. if (RegQueryValueEx(Key, Name, 0, &RegType, (PBYTE)Path, &RegSize) == ERROR_SUCCESS)
  1532. {
  1533. if (RegType==REG_SZ && FileExits(Path))
  1534. {
  1535. RegCloseKey(Key);
  1536. return 1;
  1537. }
  1538. RegDeleteValue(Key,Name);
  1539. }
  1540. }
  1541. Module = LoadLibrary(Name);
  1542. if (Module)
  1543. {
  1544. if (Key)
  1545. {
  1546. GetModuleFileName(Module,Path,MAXPATH);
  1547. RegSetValueEx(Key, Name, 0, REG_SZ, (PBYTE)Path, sizeof(tchar_t)*(tcslen(Path)+1));
  1548. RegCloseKey(Key);
  1549. }
  1550. FreeLibrary(Module);
  1551. return 1;
  1552. }
  1553. if (Key)
  1554. RegCloseKey(Key);
  1555. return 0;
  1556. }
  1557. bool_t HaveDPad()
  1558. {
  1559. return 1;
  1560. }
  1561. #endif