C400

135. オブジェクトを読むには

IBM iのオブジェクトを直接読取るなんて考えたことは
あるだろうか?
一体そんなことができるのだろうか?
最近になってオブジェクトの読取りに成功したので
その方法を紹介する。
オブジェクトをダンプ・リストではなく直接読むことが
できるとかなり深い解析に役に立つ。

先に「ボインタでプログラムを呼び出す」でプログラム・オブジェクトの
システム・ポインタを取得する方法を紹介したので
今回はいよいよそのオブジェクトの読取りである。

[オブジェクトを読取るTESTMIOBJ ]

ソースはこちらから

0001.00 #include                                   
0002.00 #include                                  
0003.00 #include                                  
0004.00 #include  /* triml */                   
0005.00 #include                                   
0006.00 #include                                  
0007.00 #include                                
0008.00 #include                                
0009.00 #include                                  
0010.00 #include                                 
0011.00 #include                                
0012.00 #include                                
0013.00 #include                                
0014.00 #include                                  
0015.00                                                     
0016.00 #define TRUE         0                              
0017.00 #define FALSE       -1                              
0018.00 typedef struct {                                    
0019.00    int  BYTESPRO;                                   
0020.00    int  BYTESAVL;                                   
0021.00    char MSGID[7];                                   
0022.00    char RESRVD;                                     
0023.00    char EXCPDATA[100];                              
0024.00 } ERRSTRUCTURE;     /* Define the error return structure            */ 
0025.00 ERRSTRUCTURE  errcode;/* Error Code Structure for RCVMSG      */       
0026.00 typedef struct {                                                       
0027.00    char OBJ[10];                                                       
0028.00    char OBJLIB[10];                                                    
0029.00    char OBJTYPE[10];                                                   
0030.00 } OBJECT;                                                              
0031.00 OBJECT m_object;                                                       
0032.00 char   m_OBJTYP[2];                                                    
0033.00                                                                        
0034.00 void main(void){                                                       
0035.00    char OBJ[11], OBJLIB[11];                                           
0036.00    _SYSPTR    ptr_object;                                              
0037.00    _SPCPTR    objptr;                                                  
0038.00    _MPTR_Template_T  opt;                                              
0039.00    unsigned char* buff;                                                
0040.00    int i;                                                              
0041.00    _SPC_Template_T spc_template;                                       
0042.00                                                                        
0043.00    printf("*** TESTMIOBJ: OBJ 検索 MI テスト ***n");                  
0044.00    getchar();                                                          
0045.00    errcode.BYTESPRO = 160;                                             
0046.00    errcode.BYTESAVL = 0;                                               
0047.00    memcpy(m_object.OBJ, "QGSPDSPQ  ", 10);                             
0048.00    memcpy(m_object.OBJLIB, "QSYS      ", 10);                                             
0049.00    memcpy(m_object.OBJTYPE, "*PNLGRP   " , 10);                                           
0050.00    printf("[%d] OBJ=[%s]n",  __LINE__, m_object.OBJ);                                    
0051.00    getchar();                                                                             
0052.00    QLICVTTP("*SYMTOHEX ", "*PNLGRP   ", m_OBJTYP, &errcode);                              
0053.00    if(errcode.BYTESAVL != 0){/*APIERR*/                                                   
0054.00       printf("[%d] APIERR MSGID=[%s]n", __LINE__, errcode.MSGID);                        
0055.00       getchar();                                                                          
0056.00       exit(-1);                                                                           
0057.00    }/*APIERR*/                                                                            
0058.00    printf("[%d] m_OBJTYP = 0x%02x%02xn", __LINE__, m_OBJTYP[0], m_OBJTYP[1]);            
0059.00    getchar();                                                                             
0060.00                                                                                           
0061.00    memcpy(OBJ, m_object.OBJ, 10);                                                         
0062.00    OBJ[10] = 0x00;                                                                        
0063.00    memcpy(OBJLIB, m_object.OBJLIB, 10);                                                   
0064.00    OBJLIB[10] = 0x00;                                                                     
0065.00    ptr_object = rslvsp(WLI_PNLGRP,  OBJ, OBJLIB, _AUTH_RETRIEVE); /* オブジェクトの開始 */
0066.00    if(ptr_object == NULL){/* 失敗 */                                                      
0067.00      printf("[%d] failed in RSLVSP.n", __LINE__);                                        
0068.00      getchar();                                                                           
0069.00      exit(-1);                                                                            
0070.00    }/* 失敗 */                                                                            
0071.00    printf("[%d] 名前解決が成功した。 n", __LINE__);                                      
0072.00    getchar();                                                                       
0073.00                                                                                     
0074.00    spc_template.TmpSize = sizeof(spc_template);                                     
0075.00    mats(&spc_template, ptr_object); /* スペース属性 */                              
0076.00    objptr = setsppfp(ptr_object); /* スペース */                                    
0077.00    if(objptr == NULL){/* 失敗 */                                                    
0078.00       printf("[%d] setsppfp オブジェクト・ポインタ取得に失敗 n", __LINE__);        
0079.00       getchar();                                                                    
0080.00       exit(-1);                                                                     
0081.00    }/* 失敗 */                                                                      
0082.00    printf("[%d] objptr オブジェクト・ポインタの取得に成功しました。 n",__LINE__);  
0083.00    getchar();                                                                       
0084.00    printf("[%d] object size = %dn", __LINE__, spc_template.Size);                  
0085.00    getchar();                                                                       
0086.00    for(i = 0; i 0 && i % 16 == 15) printf("n");                                       
0090.00    }/*for-loop*/                                                                    
0091.00    printf("n");                                                                    
0092.00    getchar();                                                                       
0093.00 }    


                                                                                  

[コンパイル]

CRTBNDC OBJLIB/TESTMIOBJ SRCFILE(SRCLIB/QCSRC) AUT(*ALL)

[解説]

海外のサイトでもオブジェクトの読取りを試みている例が少しはあってプログラム(*PGM)の
読取りに成功している例もあるがここで紹介するのはパネル・グループ(*PNLGRP)のオブジェクトを
読取る例である。
しかも読者でテストできるように QSYS/QGSPDSPQ *PNLGRP というパネル・グルーブ・オブジェクトを
読取るようにした。
これは WRKOUTQコマンドのインターフェースを構成しているパネル・グループ(*PNLGRP)である。
簡単に説明すると

0065.00    ptr_object = rslvsp(WLI_PNLGRP,  OBJ, OBJLIB, _AUTH_RETRIEVE); /* オブジェクトの開始 */

 

によってオブジェクトのシステム・ポインタ ptr_object を取得している。
 次にこのオブジェクトの長さを調べるために

0074.00    spc_template.TmpSize = sizeof(spc_template);                                     
0075.00    mats(&spc_template, ptr_object); /* スペース属性 */

 

によって属性を取得して spc_template.Size というバイト数としての長さを取得している。
さらに

0076.00    objptr = setsppfp(ptr_object); /* スペース */

 

によってオブジェクトのポインタに変換して後は

0086.00    for(i = 0; i 0 && i % 16 == 15) printf("n");                                       
0090.00    }/*for-loop*/                               

 

によってオブジェクトそのものの内容を読み取って出力している。
 結果は

   *** TESTMIOBJ: OBJ 検索 MI テスト ***             
 >                                                   
   [50] OBJ=[QGSPDSPQ  QSYS      *PNLGRP   ]         
   [58] m_OBJTYP = 0x1915                            
   [71] 名前解決が成功した。                         
   [82] objptr オブジェクト・ポインタの取得に成功しました 
  [84] object size = 110592                       
>                                                 
  00 00 01 00 00 00 18 f0 00 01 2e 10 00 01 52 10 
  00 01 aa 30 00 00 00 00 00 00 00 00 ff ff ff fd 
  00 00 0a d0 00 00 00 0b 03 40 40 40 0e 47 cb 44 
  88 0f 4b 4b 4b 40 40 40 40 0e 49 f4 44 bc 44 ae 
  0f 0e 43 a2 43 af 43 d7 0f 40 40 40 40 40 40 40 
   :
   :

という感じである。

ところでオブジェクトの読取りには次の2つの注意がある。

(1) システム保護レベル(QSECURITY) が 40以上の場合は *SYSTEM オブジェクトは読取れない。

DSPOBJD OBJ(QSYS/QGSPDSPQ) OBJTYPE(*PNLGRP) を実行すると

                         オブジェクト記述の表示-明細                          
                                                            ライブラリー 1 の 1
 オブジェクト . . . . :   QGSPDSPQ        属性 . . . . . . . . :               
   ライブラリー . . . :     QSYS          所有者 . . . . . . . :   QSYS        
  ライブラリー ASP 装置  . :   *SYSBAS          ライブラリー ASP グループ  :   *SYSBAS     
 タイプ . . . . . . . :   *PNLGRP         1 次グループ . . . . :   *NONE       
                                                                               
 ユーザー定義の情報 :                                                          
   属性 . . . . . . . . . . . . . . . . :                                      
   テキスト . . . . . . . . . . . . . . :                                      
                                                                               
 作成情報 :                                                                    
   作成日/時刻 . . . . . . . . . . . . :   08/04/01  00:21:17                 
   作成ユーザー . . . . . . . . . . . . :   *IBM                               
   作成システム . . . . . . . . . . . . :   00000000                           
   オブジェクト定義域 . . . . . . . . . :   *SYSTEM                            
                                                                          
                                                                       続く ...
 続行するには,実行キーを押してください。                                      
                                                                               
 F3= 終了   F12= 取り消し                                                      

[解説]

注目して欲しいのはオブジェクト定義域が *SYSTEM と表示されていることである。
これは IBM が提供しているQSYSのオブジェクトであるからだけではない。

ユーザーがコンパイルした *PGM の場合は

オブジェクト定義域 : *USER

であるが
ユーザーが作成した *CMD や *PNLGRP はすべて

オブジェクト定義域 : *SYSTEM

となってしまう。(この理由は現在調査中である)

次に

システム保護レベル(QSECURITY) が 40以上の場合はオブジェクト定義域が *SYSTEM のオブジェクトは
保護違反となって読取ることができない。
従って例えばユーザーが作成したパネル・グループやコマンドのオブジェクトを読取ることが
できるのは QSECURITYが 30以下の場合だけである。

(2) 古いリリースで作成されたオブジェクトは読取れない。

弊社にあった V2R2M0のオブジェクトは読取りエラーになった。
かなり古いオブジェトクは読取れないようである。

 – 以上の2点を注意すればオブジェクトを読取ることができる。
オブジェクトの読取りはIBM iのオブジェクト解析を進化させうまく行けば劇的な改革が可能となる。
オブジェクト解析はまだ始まったばかりであるが大きな一歩となったと信じたい。