0

これは少し難解ですが、OS X の Carbon Component Manager がどのように機能するかを知っている人が数人いるはずです。コンポーネントの作成をいじるためにいくつかの小さなアプリを作成しました (背景については、こちらを参照してください)。実際、アプリの 1 つは「Fiendishthngs」と呼ばれる Apple のサンプル プログラムです。Component Manager が使用可能にしているすべてのコンポーネントが一覧表示されます。私のプログラムは、コンポーネントを登録し、コンポーネント マネージャが持っているすべてのコンポーネントを一覧表示し、(登録したコンポーネントの削除を避けるために) 無期限に待機する単純な小さなものです。

私のシステムでは、Component Manager は 873 個のコンポーネント (ほとんどが別の種類のコーデック) を追跡しています。コンポーネントを登録する私のプログラムはそれを登録し、874 個のコンポーネントをカウントします。ソースは次のとおりです。

void RegisterBasicComponent()
{
    ComponentDescription desc;
    desc.componentType = kMyComponentType;
    desc.componentSubType = kMyComponentSubType;
    desc.componentManufacturer = kMyComponentManufacturer;
    desc.componentFlags = 0;
    desc.componentFlagsMask = cmpIsMissing;

    ComponentRoutineUPP MyComponentRoutineUPP 
        = NewComponentRoutineUPP( &MyComponentRoutineProc );

    //  Handle name_handle = NewHandle( sizeof( kMyComponentName ) );
    //strcpy( *(char**)name_handle, kMyComponentName );

    //RegisterComponent( &desc, MyComponentRoutineUPP, registerComponentGlobal, name_handle, NULL, NULL );
    Component component = RegisterComponent( &desc, MyComponentRoutineUPP, registerComponentGlobal, NULL, NULL, NULL );
    if ( NULL != component )
        printf("The registration seems to have worked!\n");
    else
        printf("Nope - didn't work for some reason.\n");

}


int main( void )
{
    RegisterBasicComponent();

    ComponentDescription looking;
//  OSType              componentType;          /* A unique 4-byte code indentifying the command set */
//  OSType              componentSubType;       /* Particular flavor of this instance */
//  OSType              componentManufacturer;  /* Vendor indentification */
//  UInt32              componentFlags;         /* 8 each for Component,Type,SubType,Manuf/revision */
//  UInt32              componentFlagsMask;     /* Mask for specifying which flags to consider in search, zero during registration */
    looking.componentType           = kAnyComponentType;          
    looking.componentSubType        = kAnyComponentSubType;
//  looking.componentSubType        = kComponentResourceType
    looking.componentManufacturer   = kAnyComponentManufacturer;
    looking.componentFlags          = 0;
    looking.componentFlagsMask      = cmpIsMissing;

    long numComponents = CountComponents ( &looking );

    printf("Found %ld components.\n", numComponents);

    Component component = 0;
    int i = 0;
    while (true) 
    {
        component = FindNextComponent(component, &looking);

        if ( 0 == component )
            break;

        ComponentDescription desc;
        Handle componentName = NewHandle(256);
        Handle componentInfo = NewHandle(1024);
        Handle componentIcon = 0;
        OSErr err = GetComponentInfo( component,
                                &desc,
                                componentName,
                                componentInfo,
                                componentIcon );

        if ( err != noErr )
        {
            printf("Couldn't find any info on component %d of %ld in list!\n", i
                   , numComponents);
            break;
        }


        printf( "%d of %ld: '%c%c%c%c', '%c%c%c%c', '%c%c%c%c', '%s'\n", 
            i, numComponents,
            SPLAT_WORD( desc.componentManufacturer ),
            SPLAT_WORD( desc.componentType ),
            SPLAT_WORD( desc.componentSubType ),
            *componentName );

        RecoverHandle( *componentName );
        RecoverHandle( *componentInfo );

        ++i;
    }

    while (true) 
    {
        printf("Waiting around for someone to use me...\n");
        sleep( 3 );
    }
}

とにかく、私がこれを実行すると、それを実行したままにし (コンポーネントはおそらくコンポーネント マネージャーに登録されたままになります)、Fiendishthngs を実行すると、Fiendishthngs は私が登録したテスト コンポーネントを認識できません。RegisterComponent() に渡された「registerComponentGlobal」フラグは、コンポーネントを他のプロセスで使用できるようにすることになっていますが、何かがうまくいかないようです。

何か案は?

4

1 に答える 1

3

さて、私はこの問題を残し、OSXのComponentManagerがおそらく「グローバル」オプションをサポートしなくなったという事実に自分自身を辞任しました。

これは本当に理にかなっています。コンポーネントをプロセスから他のプロセスに「グローバル」にするには、RPCやOS Xのように、アウトプロセスの呼び出しマーシャリングが必要になります。一方、OS 9以前では、すべてのことを考えると、それは完全に理にかなっています。プロセスは共通のアドレス空間に存在していました。OS 9の場合、コンポーネントをすべてのプロセスでグローバルに使用できるようにするのは簡単です。

とにかく、今日私は関連するコードが存在するように見えるRegisterComponentFileRefEntries()を逆アセンブルしていました、そして確かに、私はこれを関数の前文で見ました(コメントは私のものです):

0x9841a026  <+0018>  mov    eax, DWORD PTR [ebp+0x8]        // load param spec
0x9841a029  <+0021>  mov    DWORD PTR [ebp-0xdc],eax        // local spec = param spec
0x9841a02f  <+0027>  mov    edx,DWORD PTR [ebp+0x10]        // load param toRegister
0x9841a032  <+0030>  mov    DWORD PTR [ebp-0xe0],edx        // local toRegister = param toRegister

RegisterComponentFileRefEntriesの署名は次のとおりです。

extern OSErr 
RegisterComponentFileEntries(
  const FSSpec *                spec,
  short                         global,
  const ComponentDescription *  toRegister,          /* can be NULL */
  UInt32                        registerCount)   

RegisterComponentFileRefEntriesが煩わしい2つのパラメーターは、spec(ebp + 0x8)とtoRegister(ebp + 0x10)だけです。global(ebp + 0xc)およびregisterCount(ebp + 0x14)は完全に無視されます。

于 2009-12-27T00:45:43.547 に答える