2012年4月25日 星期三

Apple Lossless Codec (ALAC)

Apple Lossless 已經open source 了, 是一個很好的選擇
試著build , Windows 的版本 很簡單 沒啥問題 只是如果用VS2010 以前的
要自己下載 stdint.h
stdint.h 是 C99 標準 可以在 http://code.google.com/p/msinttypes/ 下載

然後build MIPS 版本
會出現 error C2733: second C linkage of overloaded function 'wmemchr' not allowed

那是因為 stdint.h include wchar.h
而且加上 extern "C"


#ifdef __cplusplus
extern "C" {
#endif
#  include
#ifdef __cplusplus
}

因為 C 不能 第二次 link 到 overloaded function
所以會出現C2733 錯誤
而且Apple  Lossless Solution 把一些 .c 檔都當成 c++ (/TP) 來 compile

如果把那些  .c 檔用 c 的方式來compile 就不會出現 C2733
不過會出現奇怪錯誤 error C2054: expected '(' to follow 'inline'
那是因為 C 沒有 inline keyword 要用 __inline

2種改法都行

應該是 sdk 中的 wchar.h 有問題 跟 win32 的 wchar.h 不一樣
sdk 中的 wchar.h 好像有明顯錯誤

在win32 中 wchar.h

wmemchr, wcschr, wcspbrk, wcsrchr, wcsstr
都是用 extern "C++" 括起來
但是 standard sdk 中卻沒有(應該是錯誤)
如果修改,移出 extern "C" 然後把 wmemchr, wcschr, wcspbrk, wcsrchr, wcsstr
用 extern "C++" 括起來, 就可以過關

第三種改法
改 stdint.h , extern "C" 改成 extern "C++"

#ifdef __cplusplus
extern "C++" {
#endif
#  include
#ifdef __cplusplus
}




然後繼續編譯, Link 出現一些問題
0. Link subsystem specify WindowsCE
1. unresolved external symbol __security_check_cookie 使用 /GS- 即可 ( Buffer Security Check OFF )
2. memset... function 沒有
要Link coredll.lib 或 corelibc.lib
在此不能用 coredll.lib 因為沒有 startup function like mainACRTStartup 
也沒有 exit()

http://msdn.microsoft.com/en-us/library/ms859584.aspx

最後 編譯完的EXE 到 MIPS上跑
結果不能run 顯示 cannot find one of its component
不知道少了什麼
只好用 dependency walker
http://www.dependencywalker.com/
發現少了 msvcr90d.dll
解決方法之一 是把 compiler option /MDd 改成 /MTd
就ok了 ^^

http://msdn.microsoft.com/en-us/library/abx4dbyh(v=vs.80).aspx
http://blog.monkeypotion.net/gameprog/beginner/love-and-hate-between-msvc-and-crt


Exception
事情總是沒那麼簡單,alacConvert 實際上在MIPS run 時,出現了Exception
code 是 0x80000002  address 000124A8
怎麼看 exception code 呢
之前都沒仔細研究
後來查到有關的 2個 API  GetExceptionCode 跟 RaiseException


追到 Exception Code 的定義在 winbase.h 然後又定義在 winnt.h(WIN32) 或 ntstatus.h (ARM)



#define EXCEPTION_ACCESS_VIOLATION          STATUS_ACCESS_VIOLATION
#define EXCEPTION_DATATYPE_MISALIGNMENT     STATUS_DATATYPE_MISALIGNMENT
#define EXCEPTION_BREAKPOINT                STATUS_BREAKPOINT





最常見的是 
EXCEPTION_ACCESS_VIOLATION          0xC0000005
EXCEPTION_DATATYPE_MISALIGNMENT     0x80000002
這兩個


再來 alignment fault 可以用 __unaligned 來解決或者自己copy (byte by byte)

Address 的話, 產生 .map 檔跟 listing files來觀察即可

note: __unaligned 是Microsoft specific
在Linux 中, 用 get_unaligned() 和 put_unaligned() macro


The easiest way to avoid unaligned access is to use the get_unaligned() and
put_unaligned() macros provided by the  header file.


http://lwn.net/Articles/260456/

2012年4月15日 星期日

Unknown IOCTL, IOCTL_PSL_NOTIFY

在使用 XXX_IOControl  的時候 發現會有不名的 IOCTL 自動進來
其code 為 0x10303FF (16974847)
經查結果如下
IOCTL_PSL_NOTIFY 是屬於 OAL IOCTL 之一
它在什麼時候被呼叫呢?
也就是當AP Process Main Thread 結束的時候
它呼叫Driver 的 thread 尚未結束(或被block住)
這時系統就會call IOCTL_PSL_NOTIFY 去通知Device Driver unblock, release 這個thread.


The OS uses this I/O control when all of the following conditions are true:
  • The main application thread exits.
  • The application has other threads still running.
  • The application has open file handles that refer to the device.




http://www.itlisting.org/4-windows-ce-embedded/81ac8dc06a35379f.aspx
hey... 
Why does my XXX_IOControl receive a unknown IOCTL code when closing my
application ?? 
The IOCTL code is received before the XXX_Close is called. 
The received code is: 16974847 (0x10303FF) 
What is causing this ???
What is this used for ??? 


This is IOCTL_PSL_NOTIFY (see common\oak\inc\pkfuncs.h).  It's issued when a 
process is exiting. 
Basically what happens is this: when a process exits (i.e. the main thread
is terminating), all threads in that process will be terminated.  Some of
these threads may be blocked inside drivers.  This IOCTL is issued to all
drivers so that they can unblock these threads if they so desire (most
drivers ignore this, but check out the serial driver
(common\oak\drivers\serial\com_mdd2\mdd.c) for an example of how this might
be done. 

2012年4月12日 星期四

ActivateDevice

在WINCE 7 下,用RegisterDevice 會失敗 回傳1060 (ERROR_SERVICE_DOES_NOT_EXIST) 不知道為什麼。

只好改用 ActivateDevice
ActivateDevice 的第一個參數是 Registry Path 不包含HKEY_LOCAL_MACHINE
如 HKEY_LOCAL_MACHINE\Drivers\BuiltIn\Netbios 就變成 "Drivers\BuiltIn\Netbios"

過程如下
當Registry 都沒設時 回傳 1060
當有設好一些 Registry 時 會回傳 1610  (ERROR_BAD_CONFIGURATION)
當都設好時 但是 .DLL 沒放到 \Windows 下 會回傳 2 (ERROR_FILE_NOT_FOUND)
當全部都好後 一直回傳 1 (ERROR_INVALID_FUNCTION)
最後才知道是 XXX_Init 沒有定義 export ( 用到舊的定義 一個參數)


VirtualCopy MmMapIoSpace in WINCE 6

http://discovertheexperience.blogspot.com/2009/04/windows-embedded-ce-60-memory-mapping.html

In Windows Embedded CE 6.0 there are some APIs which can only be called from Kernel Mode due to trust issues. The memory mapping APIs like VirtualCopyMmMapIoSpace (which is a wrapper for VirtualAlloc and VirtualCopy), … now belong to those Kernel Mode only APIs. Consequently you might ask: “So there is no way to call MmMapIoSpace directly from User Mode?” Well not quite, there is but one exception and that is a User Mode driver. The reflector service of a particular User Mode driver which runs in Kernel Mode can call MmMapIoSpace on behalf of that User Mode driver. However, it will not do so unless it knows that the User Mode driver is allowed to access the addresses in question. But how does the reflector service get this information you might ask? Well It gets it from the User Mode driver’s registry: more specific from the IoBase and IoLen keys. You can also use multi-strings here to specify multiple base addresses and lengths. And since this part of the registry is only accessible by privileged applications we have a protection against unauthorized altering of those keys.

But what if you need to call a memory mapping API such asMmMapIoSpace from a User Mode application? How now brown cow? Well you got several options how to deal with this problem:
  • You can make the code that calls the memory mapping functions a driver. Remember to specify the IoBase and IoLenregistry keys if you make it a User Mode driver.

  • You can make the code that calls the memory mapping functions into a DLL that you then have to load into the Kernel via LoadKernelLibrary.

  • You can create a dummy Kernel Mode driver that implementsIOCTL_DO_VIRTUAL_COPY to call VirtualCopy.

There is another important restriction on VirtualCopy and therefore also on MmMapIoSpace in Windows Embedded CE 6.0: Calls to either of these two memory mapping functions will fail if it crosses a 32 MB section boundary. To avoid this you may have to call these APIs multiple times.




http://blog.csdn.net/Jack__h/article/details/4939911
http://www.cppblog.com/milkyway/archive/2007/03/27/20738.html


VirtualCopy 的WINCE 5, 6, 7 的解釋各有不同,值得一看
WINCE 5 -- 傳統的, MEM_PHYSICAL 解釋不同, return 的address 2MB 不同
http://msdn.microsoft.com/en-us/library/aa450977.aspx
WINCE 6  -- 講了如何call API 的替代方法
http://msdn.microsoft.com/en-us/library/ee483154(v=winembedded.60).aspx
WINCE 7
http://msdn.microsoft.com/en-us/library/ee483154.aspx