2016年9月28日 星期三

win32 (Partition boot record) read/write by C++

Master boot record (FOR xp/2k)
以下是 win32 console program , 用來備份 boot sector (446 bytes) , 和寫入 boot sector.
測試環境是用 vs2005 , project property 用  /MT (靜態連結,省得 RUN-TIME-DLL 版本問題)
,用 MBCS 字集.

----------------
// bootsec.cpp : /dump to backup current harddisk boot sector to hex file, /fix to restore  from hex file
//

#include "stdafx.h"

HANDLE hDevice=NULL;
unsigned char * WriteSector(int drive, DWORD startinglogicalsector, int numberofsectors,unsigned char *buffer)
{
    SetFilePointer (hDevice, (startinglogicalsector*512), NULL, FILE_BEGIN);
    DWORD byteswrite=0;
    BOOL ret=WriteFile(hDevice,buffer,512*numberofsectors,&byteswrite,NULL);

    ret = FlushFileBuffers(hDevice);
    return buffer;
}
unsigned char * ReadSector(int drive, DWORD startinglogicalsector, int numberofsectors)
{
 // All msdos data structures must be packed on a 1 byte boundary
 #pragma pack (1)   
 struct
 {
    DWORD StartingSector ;
    WORD NumberOfSectors ;
    DWORD pBuffer;
 }ControlBlock;
 #pragma pack ()

 #pragma pack (1)
 typedef struct _DIOC_REGISTERS
 {
    DWORD reg_EBX;
    DWORD reg_EDX;
    DWORD reg_ECX;
    DWORD reg_EAX;
    DWORD reg_EDI;
    DWORD reg_ESI;
    DWORD reg_Flags;
 } DIOC_REGISTERS ;
 #pragma pack ()

 unsigned char* buffer = (unsigned char*)malloc (512*numberofsectors);
 DIOC_REGISTERS reg ;
 BOOL  fResult ;
 DWORD cb ;

 // Creating handle to vwin32.vxd (win 9x)
 hDevice = CreateFile ( "\\\\.\\vwin32",
         0,
         0,
         NULL,
         0,
         FILE_FLAG_DELETE_ON_CLOSE,
         NULL );

 if ( hDevice == INVALID_HANDLE_VALUE )
 {

    // win 2k code
    DWORD bytesread;
   
    // Creating a handle to drive a: using CreateFile () function ..
    char _devicename[] = "\\\\.\\A:";
    _devicename[4] += drive;
    hDevice = CreateFile(_devicename,
        // GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
        GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL, OPEN_EXISTING, 0, NULL);

    if (hDevice == INVALID_HANDLE_VALUE)
        return NULL;

    SetFilePointer (hDevice, (startinglogicalsector*512), NULL, FILE_BEGIN);
    if (!ReadFile (hDevice, buffer, 512*numberofsectors, &bytesread, NULL) )
        return NULL;   
 }
 else
 {
     // code for win 95/98
     ControlBlock.StartingSector = (DWORD)startinglogicalsector;
     ControlBlock.NumberOfSectors = (DWORD)numberofsectors ;
     ControlBlock.pBuffer =  (DWORD)buffer ;

    //-----------------------------------------------------------
    // SI contains read/write mode flags
    // SI=0h for read and SI=1h for write
    // CX must be equal to ffffh for
    // int 21h's 7305h extention
    // DS:BX -> base addr of the
    // control block structure
    // DL must contain the drive number
    // (01h=A:, 02h=B: etc)
    //-----------------------------------------------------------

     reg.reg_ESI = 0x00 ;
     reg.reg_ECX = -1 ;
     reg.reg_EBX = (DWORD)(&ControlBlock);
     reg.reg_EDX = drive+1;
     reg.reg_EAX = 0x7305 ;

     //  6 == VWIN32_DIOC_DOS_DRIVEINFO
     fResult = DeviceIoControl ( hDevice,
         6,
         &(reg),
         sizeof (reg),
          &(reg),
         sizeof (reg),
         &cb,
         0);

     if (!fResult || (reg.reg_Flags & 0x0001)) return NULL;        
 }

 // CloseHandle(hDevice);
 return buffer;
}


int _tmain(int argc, _TCHAR* argv[])
{
    const int mbr_drive = 'C' - 'A';
    const int mbr_sector_start = 0;
    const int mbr_sectors = 1;
    if(argc==1)
    {
        printf("\nmbr v002");
        printf("\nmbr /dump > mbr.hex");
        printf("\nmbr /fix < mbr.hex");
        printf("\n");
    }

    unsigned char * pmbr=NULL;
    pmbr=ReadSector(mbr_drive,mbr_sector_start,mbr_sectors);
    if(pmbr==NULL)
    {
        printf("Read error\n");
        return -1;
    }

    if(argc==1)
    {
        printf("Read ok\n");       
        for(int i=0;i<16;i++)
        {
            printf("%02x ",pmbr[i]);
        }
        printf("\n");   
    }

    const int MBR_BYTES = 446;
    if(argc==2)
    {
        if(0==memcmp(argv[1],"/dump",5))
        {
            for(int i=0; i<MBR_BYTES; i++)
            {
                if (i%16==0) printf("\n");
                printf("%02x ",pmbr[i]);
            }
        }
        else if(0==memcmp(argv[1],"/fix",4))
        {
            unsigned char mbr_new[512];
            int count = 0;        // 446 hex byte expected
            const int BUF_SIZE=2048;
            char hexbuf[BUF_SIZE];
            printf("\n/fix");
            while(count<MBR_BYTES)
            {
                memset(hexbuf,0,BUF_SIZE);
                gets(hexbuf);               
                char * phex=hexbuf;
                // printf("\n[%s]",hexbuf);

                printf("\n");
                for(int i=0;i<16;i++)
                {
                    unsigned int value;
                    int item=sscanf(phex,"%02x",&value);
                    if(item!=1)
                        break;
                    phex=phex+3;
                    printf("%02x ",value);
                    mbr_new[count]=value;
                    count++;
                    if(count >= MBR_BYTES)
                        break;
                }
            }

            int diff = 0;
            for(int i=0; i<MBR_BYTES; i++)
            {
                if(mbr_new[i]!=pmbr[i]) diff++;
            }

            if(diff!=0)
            {
                for(int i=0;i<MBR_BYTES; i++) pmbr[i]=mbr_new[i];
                printf("\nneed write new mbr 446 bytes record into harddisk\n");
                WriteSector(mbr_drive,mbr_sector_start,mbr_sectors,pmbr);
            }
        }
    }

    printf("\n");
    if(hDevice!=NULL)
        CloseHandle(hDevice);
    if(pmbr)
        free(pmbr);
    return 0;
}

2016年9月21日 星期三

用function call operator 來作getter 和 setter

我的結論是目前不推薦使用.

code 如----以下所示

網上有人大推這種 get/set 方法. 認為其不用 .getxxx() , .setxxx(...)
或許小程式有其優雅,

缺點是無法簡單的用 regular/expression 來搜尋其get/set 的引用.
但是一個 regular/expression 無法搜尋引用的寫法,表示人在閱讀,推敲其 code 時,
也要增加額外的負擔, 記住 (以下的code為例) class 產生出來的 instance 名子,才能追其code.

.要靠 compiler 級別的editor 才能找出其引用.
-------------------------------
class cInt {
    int v;
public:
    cInt() : v(0) {}

    int operator ()()                // cInt value get-function
    {
        return v;
    }

    void operator ()(int new_v)        // cInt value set-funciton
    {
        v = new_v;
    }

    void dump(){
        Output("cInt'v=%d\n",v);
    }
};

void test_paren_operator()
{
    cInt ci;
    ci.dump();
    // int v1=ci.v;    // not public
    int v2=ci();    // get

    ci(3);            // set
    ci.dump();
    // ci() = 4;    // not l-value
    ci.dump();
}
--------------

cInt'v=0
cInt'v=3
cInt'v=3

c++ set/get data member 用 set() template 區分出來

以下是將 class 的data member 基本上給外部用的,用 const
如果是 讀取,當然沒問題,
但是如果是設定新值, 就必需要用 set member function, 或 set template
如果 data member 繁多, 就用 set template 吧, 省得寫一大堆沒營養的 fuction.

這樣作的好處是 trace code 的時候, 可以很容易的找到 set value 的地方.
當然如果不這麼作,用眼看,也是分析的出來. 但是
讀取通常有數十個到數百個 reference, 設定通常是數個.
要在數百個中找到數個,也是很累人的.
------------------------------------
#include <iostream>
#include <wtypes.h>
using namespace std;

void Output(const char* szFormat, ...)
{
    char szBuff[1024];
    va_list arg;
    va_start(arg, szFormat);
    _vsnprintf(szBuff, sizeof(szBuff), szFormat, arg);
    va_end(arg);

    OutputDebugString(szBuff);
}


template <class T>
T & set(const T& vin) {
    return (T&) vin;
}

class cOne {
public:
    const int v;
    // int v;

    cOne() : v(0)
    {}

    void dump()
    {
        Output("cOne'v = %d\n",v);
    }
};


void func_modify(int & var)
{
    var++;
}

void set_test()
{
    cOne c1;
    c1.dump();

//    c1.v = 7;            // error
    int v1 = c1.v;       

//    int &v2 = c1.v;        // error
    int &v3 = set(c1.v);
    v3=4;
    c1.dump();

    set(c1.v) = 6;    c1.dump();
//    func_modify(c1.v);        // error
    func_modify(set(c1.v));    c1.dump();

    cOne *pc1 = new cOne;
//    pc1->v = 10;            // error
//    int& v4 = pc1->v;        // error
    int& v5 = set(pc1->v);
    v5=11;
    pc1->dump();

    set(pc1->v) = 12;    pc1->dump();
//    func_modify(pc1->v);    // error
    func_modify(set(pc1->v)); pc1->dump();
    delete pc1;
}

int main()
{
  cout << "Hi set_test" << endl;
  set_test();
  // getchar();
}
--------------------
----- Output -----
cOne'v = 0
cOne'v = 4
cOne'v = 6
cOne'v = 7
cOne'v = 11
cOne'v = 12
cOne'v = 13

2016年9月14日 星期三

use vs2005 commanline compile , don't install , but copy.

當你安裝好 vs2005 , 可以把安裝目錄備份(例如c:\VS8),
可以在(c:\vs8\vc\) vcvarsall.bat 頭一行加
SET VS80COMNTOOLS=C:\VS8\Common7\Tools\
然後再備份.

以後新裝 os,如果只想調用 commandline compile code, 可以不用安裝 .net2 vs.. long time
把之前的備份copy 回原位 (例如 c:\VS8)
如有需要請安裝 (vcredist_x86_vc2005sp1.exe)
如有(ml.exe from vs2008express) , 請安裝(vcredist_x86_vc2008sp1.exe)

 
進command prompt , cd到 c:\vs8\vc\
只要打 vcvarsall.bat 即有 commandline compile 的能力.

Using vs2005 +ml(2008express) build 7-zip 16.02

vm xpsp2
+我用 vs2005(安裝vc(.net2)(no mobile) 約 1G   
+vs2008sp1(ml.exe)  可以直接用 7-zip 打開壓縮(Ixpvc.exe)(vs_setup.cab)複製 
          FL_ml_exe_19621_x86_ln.3643236F_FC70_11D3_A536_0090278A1BB8
          vcredist_x86_vc2008sp1.exe (必需要安裝)
    用 2008ex 的 ml.exe 取代 2005 的 ml.exe
+7-zip 9.22 src  compile 方法同下
+7-zip 16.02 src 解開後  用 vs2005 command prompt  到 C:\c\7zsrc\CPP\7zip  打 nmake
    即可得 7z.exe 7-zip.dll 7z.dll 7zFM.exe 7zG(n).exe
    打 7zFM 和 7zG 時會出現要連(MSVCR80.DLL)
    用 vs2005 打開 CPP\7zip\UI\GUI\ 的 dsw (build releaseU)  --> 7zGn.exe
    CPP\7zip\UI\FileManager\ 的 dsw (build releaseU) --> 7zFM.exe
    即不會出現要求要連 msvcr80.dll 的問題
+7zip 16.02 src  到 c:\c\7zsrc\cpp\7zip 打 nmake MY_STATIC_LINK=1
    即不會出現要求要連 msvcr80.dll 的問題.

2016年9月10日 星期六

build TTSAPP(MS Speech SDK 5.1) with Unicode

predefine symbol:
remove:   _MBCS 
add:        _UNICODE,UNICODE
## must add both _UNICODE and UNICODE , just one don't work.
environment: VC6, SpeechSDK51.exe
PS:  universal string process  code snip
            // #include <stdio.h>
            // #include <TCHAR.H>
            {
                static int g_count = 0;
                HWND htWnd = GetDlgItem(m_hWnd, IDC_STATIC_RATE);
                if ( htWnd )
                {
                    TCHAR buf[256];
                    _stprintf(buf,_T("Rate %d "),g_count);

                    SetWindowText(htWnd, buf );
                    g_count ++;
                }
            }

    

2016年1月24日 星期日

enable user environment debug logging

enable user environment debug logging 

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon
Entry: UserEnvDebugLevel
Type: REG_DWORD 

NONE 0x00000000
NORMAL 0x00000001
VERBOSE 0x00000002
LOGFILE 0x00010000
DEBUGGER 0x00020000
The default value is NORMAL|LOGFILE (0x00010001).

Note To disable logging, select NONE (0x00000000).

You can combine these values. For example, you can combine VERBOSE 0x00000002 and LOGFILE 0x00010000 to get 0x00010002. Therefore, if UserEnvDebugLevel is given a value of 0x00010002, LOGFILE and VERBOSE are both turned on. Combining these values is the same as using an OR statement.
0x00010000 OR 0x00000002 = 0x00010002
Note If you set UserEnvDebugLevel to 0x00030002, the most verbose details are logged in the Userenv.log file.

%Systemroot%\Debug\UserMode\Userenv.log file. If the Userenv.log file is larger than 300 KB, the file is renamed Userenv.bak, and a new Userenv.log file is created.

you can set the read-only attribute on the Userenv.bak file, and the Userenv.log file will grow indefinitely.

2016年1月21日 星期四

啟用 Wiadebug.log 檔案的記錄

啟用 Wiadebug.log 檔案的記錄

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\StillImage\Debug\Module_name\DebugFlags
WIA 服務中,適當的二進位模組會是 Wiaservc.dll。

DebugFlags中的值會控制的記錄級別。下列清單說明這三個設定:
  • 0x00000001: 顯示錯誤
  • 0x00000002: 顯示警告 
  • 0x00000004: 顯示追蹤
DebugFlags的值是bit旗標值

重新啟動 
 net stop stisvc
 net start stisvc
 
 

2016年1月17日 星期日

firefox change cache directory folder position

firefox change cache directory folder position

1. old version  ,   about:config     
--->  add --> browser.cache.disk.parent_directory 
--->  value point to your new folder location  ---example--> "R:\\Firefox_cache\\"  

2. new version  edit prefs.js
---> add new entry
user_pref("browser.cache.disk.parent_directory", "R:\\Firefox_cache\\");


windows xp , stop wbem logging, and change WMI repository to ramdisk

windows xp , stop wbem logging, and change WMI repository to ramdisk

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WBEM\CIMOM
Key: Repository Directory
value: R:\xxx\Repository
where R: drive is your ramdisk drive, and xxx is your existing folder in ramdrive.


Key: Logging
value:  1  --> 0

您也可以為 WMI 設定錯誤記錄檔:
  • 所有的記錄檔的目的資料夾是設定此登錄子機碼:
    HKEY_LOCAL_MACHINE\Software\Microsoft\WBEM\CIMOM\LoggingDirectory
  • 最大檔案大小是設定下列登錄子機碼:
    HKEY_LOCAL_MACHINE\Software\Microsoft\WBEM\CIMOM\Log File Max Size
下列登錄子機碼會決定如何 Windows 驅動程式模型 (WDM) 提供者將會記錄錯誤:
HKEY_LOCAL_MACHINE\Software\Microsoft\WBEM\CIMOM\Logging

值:
0: 關閉記錄
1:   錯誤記錄
2: 詳細資訊記錄

windows XP assign Recent folder to ramdisk, or other drive

windows XP  assign Recent folder to ramdisk, or other drive

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
key: Recent
string: R:\Recent

purpose: decrease ssd, or system drive read/write activity

車 和 東 , 兩個 不喜歡的 簡體字 寫法

  车 是 草書 形變, 很難 和 小孩 解釋 為什麼 長這樣(反正你就背), 反而 車 就 很形象. 东 是 草書 形變, 很難 和 小孩 解釋 為什麼 長這樣( 反正你就背), (古人觀察到 日出東方, 東 是 木頭 加 日 , 那個方向 是 東.