Как сделать так, чтобы компонент Mac OS Component Manager был виден другим процессам? - PullRequest
0 голосов
/ 06 декабря 2009

Это немного эзотерично, но здесь должно быть несколько человек, которые знают, как работает Carbon Component Manager в OS X. Я сделал несколько небольших приложений, чтобы поиграть с созданием Компонентов (см. здесь для некоторого фона). На самом деле, одно из приложений представляет собой пример программы прямо от Apple под названием «Fiendishthngs». В нем перечислены все компоненты, которые диспетчер компонентов делает доступными. Моя программа - простая маленькая вещь, которая регистрирует Компонент, перечисляет все Компоненты, которые есть у Менеджера Компонентов, и затем ждет в течение неопределенного времени (чтобы избежать очистки Компонента, который он зарегистрировал).

В моей системе диспетчер компонентов отслеживает 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 не может видеть мой тестовый Компонент, который я регистрирую - он видит только 873 Компонента. Флаг 'registerComponentGlobal', передаваемый в RegisterComponent (), должен сделать Компонент доступным для других процессов, но кажется, что что-то идет не так.

Есть идеи?

1 Ответ

3 голосов
/ 27 декабря 2009

Ну, я оставил эту проблему позади, смирившись с тем фактом, что диспетчер компонентов OS X, вероятно, больше не поддерживает глобальную опцию.

Это действительно имело бы большой смысл. Чтобы сделать ваш компонент «глобальным» от вашего процесса к другим процессам, потребовалось бы маршалинг вызовов вне процесса, как в 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)   

Единственными 2 параметрами, которые беспокоит RegisterComponentFileRefEntries, являются spec (при ebp + 0x8) и toRegister (при ebp + 0x10). global (при ebp + 0xc) и registerCount (при ebp + 0x14) полностью игнорируются.

...