2012年2月29日 星期三

Access Physical Disk Content ( partitiion, boot sector, FAT)

Physical Disks and Volumes

Direct access to the disk or to a volume is restricted. For more information, see "Changes to the file system and to the storage stack to restrict direct disk access and direct volume access in Windows Vista and in Windows Server 2008" in the Help and Support Knowledge Base athttp://support.microsoft.com/kb/942448.
Windows Server 2003 and Windows XP:  Direct access to the disk or to a volume is not restricted in this manner.
You can use the CreateFile function to open a physical disk drive or a volume, which returns a direct access storage device (DASD) handle that can be used with the DeviceIoControl function. This enables you to access the disk or volume directly, for example such disk metadata as the partition table. However, this type of access also exposes the disk drive or volume to potential data loss, because an incorrect write to a disk using this mechanism could make its contents inaccessible to the operating system. To ensure data integrity, be sure to become familiar withDeviceIoControl and how other APIs behave differently with a direct access handle as opposed to a file system handle.
The following requirements must be met for such a call to succeed:
  • The caller must have administrative privileges. For more information, see Running with Special Privileges.
  • The dwCreationDisposition parameter must have the OPEN_EXISTINGflag.
  • When opening a volume or floppy disk, the dwShareMode parameter must have the FILE_SHARE_WRITEflag.
Note  The dwDesiredAccess parameter can be zero, allowing the application to query device attributes without accessing a device. This is useful for an application to determine the size of a floppy disk drive and the formats it supports without requiring a floppy disk in a drive, for instance. It can also be used for reading statistics without requiring higher-level data read/write permission.
When opening a physical drive x:, the lpFileName string should be the following form: "\\.\PhysicalDriveX". Hard disk numbers start at zero. The following table shows some examples of physical drive strings.
StringMeaning
"\\.\PhysicalDrive0"Opens the first physical drive.
"\\.\PhysicalDrive2"Opens the third physical drive.

To obtain the physical drive identifier for a volume, open a handle to the volume and call the DeviceIoControl function withIOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS. This control code returns the disk number and offset for each of the volume's one or more extents; a volume can span multiple physical disks.
For an example of opening a physical drive, see Calling DeviceIoControl.
When opening a volume or removable media drive (for example, a floppy disk drive or flash memory thumb drive), the lpFileName string should be the following form: "\\.\X:". Do not use a trailing backslash (\), which indicates the root directory of a drive. The following table shows some examples of drive strings.
StringMeaning
"\\.\A:"Opens floppy disk drive A.
"\\.\C:"Opens the C: volume.
"\\.\C:\"Opens the file system of the C: volume.

You can also open a volume by referring to its volume name. For more information, see Naming a Volume.
A volume contains one or more mounted file systems. Volume handles can be opened as noncached at the discretion of the particular file system, even when the noncached option is not specified in CreateFile. You should assume that all Microsoft file systems open volume handles as noncached. The restrictions on noncached I/O for files also apply to volumes.
A file system may or may not require buffer alignment even though the data is noncached. However, if the noncached option is specified when opening a volume, buffer alignment is enforced regardless of the file system on the volume. It is recommended on all file systems that you open volume handles as noncached, and follow the noncached I/O restrictions.
Note  To read or write to the last few sectors of the volume, you must call DeviceIoControl and specifyFSCTL_ALLOW_EXTENDED_DASD_IO. This signals the file system driver not to perform any I/O boundary checks on partition read or write calls. Instead, boundary checks are performed by the device driver.

上面寫的是在Windows 環境
而在WINCE 中,要 Open 的 filename 應該是像 L"\\USB Disk\\Vol:" <-- 錯 要用 L"DSK1:" 注意有冒號
CreateFile 成功後,再用DeviceIoControl  IOCTL_DISK_READ
用 L"\\USB Disk\\Vol:" 會成功但是之後 DeviceIoControl  IOCTL_DISK_READ 會 hang

IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
http://a-jordan.blogspot.com/2008/05/usb-flash-physical-drive.html

2012年2月2日 星期四

USB flash problem, 沒有partition, superfloopy

最近有一個問題
就是用WINCE 5.0 format 的 USB Flash
沒辦法在USB200下讀取

仔細檢驗了一下不能讀取的USB Disk
發現竟然沒有partition table

查了一下 沒有 Partition 的 Disk
就叫 Super Floopy

http://msdn.microsoft.com/en-us/windows/hardware/gg463525


Q.What about removable media?
  
A.Removable media must be MBR or "superfloppy."
Q.What is a superfloppy?
  
A.
Removable media without either GPT or MBR formatting is considered a "superfloppy." The entire media is treated as a single partition.
The media manufacturer performs any MBR partitioning of removable media. If the media does have an MBR, only one partition is supported. There is little user-discernible difference between MBR-partitioned media and superfloppies.
Examples of removable media include floppy disk drives, JAZ disk cartridges, magneto-optical media, DVD-ROM, and CD-ROM. Hard disk drives on external buses such as SCSI or IEEE 1394 are not considered removable.

2012年1月17日 星期二

mem_fun_ref, for_each

在試著使用for_each 的時候, 發現了一些問題
也把for_each 的定義看過了一遍, 也更加了解其工作原理

for_each 的第三個參數
要怎麼寫才會漂亮呢

1. static function
2. member function
3. lambda function

看其定義


for (; _ChkFirst != _ChkLast; ++_ChkFirst)
_Func(*_ChkFirst);
return (_Func);

這個function 會以 *_ChkFirst 為參數
所以只能用 static function

void aa ( *_ChkFirst )
{ ... };

for_each(  ,  , aa );

用 member function 的話, 則會失敗, 因為member function 會隱含性地多加 this
參數

用 static member function 的話則ok
for_each(  ,   , &class::static_mem_function );

不想上面這種方法時就要用到 mem_fun_ref 或 mem_fun
此時這個 member function 不用有 ( *_CheckFirst ) 這個參數

2011年12月16日 星期五

Memory Mapped Files 初探

因為又要recording video 同時又要能 print 2Kx3K 的超高清圖片
記憶體根本不夠。所以得由我單方面來節省記憶體的使用量(另一面的Programmer, 老闆, 實在太忙了)

想了想沒有什麼節省的辦法,記憶體總共有三次配置,
一個是 alloc 2Kx3Kx3 = 23M 的buffer, 做為排版使用和最終 print 的buffer。
二是把圖片資料讀進來的buffer 約為1920x1080x3= 6M大小,這個也無法省。
三是把圖片rotate 或 resize 的buffer ,我不知道這個如何省。

最後只有最簡單 寫入檔案
也就是把Disk 當成記憶體來用
想到的就是 Memory Mapped File

在Windows 上,其流程就是
CreateFile --> CreateFileMapping --> MapViewOfFile --> 開始使用
結束則是
UnmapViewOfFile --> Close FileMapping --> Close File

在此列出實驗後的要點
1. 在WINCE 上,用CreateFile 之後的Handle 來傳入 CreateFileMapping 一直都會失敗,回傳 6 ( ERROR_INVALID_HANDLE ), 要用CreateFileForMapping 取代 CreateFile 開檔就ok。 在WINCE 上
CreateFileMapping 似乎不接受 CreateFile 所產生的 HANDLE。

2. CreateFileMapping 用PAGE_WRITECOPY 失敗用 PAGE_READWRITE 成功

2011年12月13日 星期二

CreateProcess 呼叫另一個程式

同事在用 CreateProcess 呼叫我寫的程式的時候
有出點問題

 把 CreateProcess 做個重點整理
( All Info is describe in Jeffery Ritcher's Windows Via C/C++, Chap 4 )

1. 同事用 loop 一直判斷 子Process 結束了沒,這是很不好的做法,浪費CPU時間。
 if ( GetExitCodeProcess() == STILL_ACTIVE )

而且,如果子程式笨笨的 不小心把 STILL_ACTIVE (259, 0x103) 做為傳回值之一會讓Parent Process 誤判,這會是個很不容易發現的錯誤。

2. CreateProcess 後, PROCESS_INFORMATION 會回傳 2 個handle, 一個Process Handle, 一個Thread Handle。記得沒用的話要使用CloseHandle關掉,
不然的話就得等到Parent Process 整個結束的時候才會free。
其概念就是 系統在創建 Kernel Object 時會把reference counter 加一,
reference counter 為0時 才會真正destroy object. 所以回傳的 PROCESS_INFORMATION  Process Handle, 在 child process 結束後並不會被free, (否則如何 call GetExitCodeProcess?) 必需自己手動CloseHandle。所以一個Process 的Handle 可能會活得比Process更久. This is a feature, not a bug.

3. 整個流程如下

PROCESS_INFORMATION pi;
DWORD dwExitCode;

// Spawn the child process.
BOOL fSuccess = CreateProcess(..., &pi);
if (fSuccess) {
// Close the thread handle as soon as it is no longer needed!
CloseHandle(pi.hThread);
// Suspend our execution until the child has terminated.
WaitForSingleObject(pi.hProcess, INFINITE);
// The child process terminated; get its exit code.
GetExitCodeProcess(pi.hProcess, &dwExitCode);
// Close the process handle as soon as it is no longer needed.
CloseHandle(pi.hProcess);
}

第一個CloseHandle(hThread) 並不會真正把 child process 的primary thread 停掉 (因為 usage counter 並不為0) , 所以這也是沒事就在第一行先把它 close掉的原因)

As already mentioned, creating a new process causes the system to create a process kernel object and a thread kernel object. At creation time, the system gives each object an initial usage count of 1. Then, just before CreateProcess returns, the function opens with full access to the process object and the thread object, and it places the process-relative handles for each in the hProcess and hThread members of the PROCESS_INFORMATION structure. When CreateProcess opens these objects internally, the usage count for each becomes 2.

2011年11月28日 星期一

boost Traverse directory

在看 Effective C++ 3rd 的時候,最後第55條寫 Familiarize yourself with boost.
其中簡述了 boost 的功能,我看到一項 Traverse file system 的功能。
這不正是我想要又常用的功能嗎?

於是搜尋了Google 找到以下網頁
http://stackoverflow.com/questions/2550309/traversing-a-directory

原始碼如下

#include 
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
#define foreach BOOST_FOREACHnamespace fs = boost::filesystem;

fs::recursive_directory_iterator it(top), eod;
foreach (fs::path const & p, std::make_pair(it, eod)) {
    if (is_directory(p)) {
        ...
    } else if (is_regular_file(p)) {
        ...
    } else if (is_symlink(p)) {
        ...
    }
}
第二種寫法                                                                       using namespace boost::filesystem;
using namespace std;                                                                    path Path = "e:\\";
 for(recursive_directory_iterator it(Path); it != recursive_directory_iterator(); ++it)
 {
  if ( is_directory(*it) )
   cout << *it << it.level() << endl;
 }
然後開啟Visual Studio ,試著去編譯這個 boost 範例
1. 要 add include directory \boost_1_46_1\
2. 之後會出現無法 link libboost_filesystem-vc90-mt-gd-1_46_1.lib
這是因為沒有build boost lib
3. 有些boost library 需要build,使用 cmd prompt, 在 \boost_1_46_1\ 下,執行bootstrap
4. boostrap 會build bjam, 但是此處失敗了 因為include 不到 windows.h (因為Windows SDK 7沒裝完整 )。失敗原因從 bootstrap.log 中可以看出。重新執行Windows SDK setup 把Windows header 裝上,然後執行Windows SDK 下的Configuration Tool 設定好預設的SDK。
5. 設好了 include 後,之後 cannot open input file 'kernel32.lib', 所以 LIB 也要設置正確
6. 最後編譯成功後,會提示你 include 要加入 E:\boost_1_46_1, lib 要加入 E:\boost_1_46_1\stage\lib
7. 編譯過程中會出現一些Warning, 跟 D_SCL_SECURE_NO_DEPRECATE  有關, 詳情請google
(Visual Studio 2005 SP1以後 use _SCL_SECURE_NO_WARNINGS ) Standard C++ Library
_SCL_SECURE_NO_WARNINGS
_CRT_SECURE_NO_WARNINGS
_AFX_SECURE_NO_WARNINGS
_ATL_SECURE_NO_WARNINGS
http://connect.microsoft.com/VisualStudio/feedback/details/101151/scl-secure-no-deprecate-is-not-found-by-search
Message: 'Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators''
正確解法要改用 Checked Iterators, and safe functions _s
http://msdn.microsoft.com/en-us/library/aa985872(v=VS.80).aspx