【 W32api関数 】

1. 実験的なモジュール
2. バグ
3. UNLHA32.DLL によるファイルの圧縮

PHP 4.3.1 以降のインターフェイス
  • PHP 4.3.4 時点で、実験的なモジュールとマニュアルに明記されています

  • 実際問題、おそらくPHP 4.3.1 以降でインターフェイスが変更されています
    ので、マニュアルに書かれた関数は使用できません

  • 使用の際は、php.ini に extension=php_w32api.dll を記述( PHP セクション )
    した上で、以下のようなコードで実行します


  • $api = new win32;
    $api->registerfunction("long GetWindowsDirectory(string &a, long &b) From kernel32.dll");
     
    $len	= 255;
    $name	= str_repeat( "\0", $len );
     
    $api->GetWindowsDirectory($name, $len);
     
    print $name;
    


    引数の数の問題
  • 登録する win32api 関数の引数が3つを超えると動作しません

  • 実際に dll を作成して PHP からコールすると、3つ以上の場合
    は、全て右へ1つずれて1番目の引数には不明な数値がセットされます


  • #include "stdafx.h"
    extern "C" {  
    __declspec(dllexport) int Unlha(
    	const HWND _hwnd,
    	LPCSTR _szCmdLine,
    	LPSTR _szOutput,
    	const DWORD _dwSize
    );
    }
     
    BOOL APIENTRY DllMain( HANDLE hModule, 
                           DWORD  ul_reason_for_call, 
                           LPVOID lpReserved
    					 )
    {
        return TRUE;
    }
     
    int Unlha(const HWND _hwnd, LPCSTR _szCmdLine,LPSTR _szOutput, const DWORD _dwSize)
    {
    	return 10;
    }
    


  • return 10 のところでブレークポイントを設定し、以下のコードを書いた php スクリプトを用意します
  • <?
    $api = new win32;
    $api->registerfunction("int Unlha(long a,string &b,string &c,long d) From lha.dll");
     
    $a	= null;
    $b	= "TEST_STRING";
    $len	= 255;
    $buff 	= str_repeat("\0", $len);
     
    $api->Unlha($a,$b,$buff,$len);
    ?>
    
  • プロジェクトの設定でデバッグタブを選択し、デバッグセッションの実行可能ファイルに PHP.EXE をフルパス
    で指定し、プログラムの引数に上記コードのフルパスを指定します

  • デバッグを開始した結果の return 10 の位置での引数の内容は以下のようになります
  •   変数
    1
    _hwnd
    0x009f1330
    2
    _szCmdLine
    0x00000000 ""
    3
    _szOutput
    0x009fa308 "TEST_STRING"
    4
    _dwSize
    269701928


  • ですから、現在では殆どの場合自前で dll を作成する必要があります


  • #include "stdafx.h"
    extern "C" {  
    __declspec(dllexport) int MyUnlha(
    	LPCSTR _szCmdLine
    );
    }
     
    BOOL APIENTRY DllMain( HANDLE hModule, 
    	DWORD  ul_reason_for_call, 
    	LPVOID lpReserved
    )
    {
    	return TRUE;
    }
     
    typedef UINT (CALLBACK* LPFUNC)(
    	const HWND _hwnd,
    	LPCSTR _szCmdLine,
    	LPSTR _szOutput,
    	const DWORD _dwSize
    );
     
    int MyUnlha(LPCSTR _szCmdLine )
    {
    	HINSTANCE	lib;
    	LPFUNC		Lha;
     
    	lib = LoadLibrary( "UNLHA32.DLL" );
    	if ( lib == NULL ) {
    		return -1;
    	}
     
    	Lha = (LPFUNC)GetProcAddress( lib, "Unlha" );
    	if ( Lha == NULL ) {
    		FreeLibrary( lib );
    		return -2;
    	}
     
    	char *ret = new char[4096]; 
     
    	Lha(NULL, _szCmdLine, ret, 4096 );
    	FreeLibrary( lib );
     
    	delete [] ret;
     
    	return 0;
     
    }
    


    $api = new win32;
    $api->registerfunction("int MyUnlha(string &a) From lha.dll");
     
    $buff 	= "a d:\\temp\\archive.lzh -x1r2a2 d:\\ tmp";
     
    print $api->MyUnlha($buff);