如何使 Mac OS 组件管理器组件对其他进程可见?

发布于 2024-08-14 06:37:35 字数 3932 浏览 7 评论 0原文

这有点深奥,但这里肯定有几个人知道 OS X 的 Carbon 组件管理器是如何工作的。我制作了几个小应用程序来制作组件(请参阅 此处了解一些背景信息)。实际上,其中一个应用程序是直接来自 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 个组件。传递到 RegisterComponent() 的“registerComponentGlobal”标志应该使该组件可供其他进程使用,但似乎出现了问题。

有什么想法吗?

This is a bit esoteric, but there have to be a few people here who know how OS X's Carbon Component Manager works. I've made a couple of little apps to play around with making Components (see here for some background). Actually, one of the apps is a sample program straight from Apple called 'Fiendishthngs'. It lists all the Components that the Component Manager is making available. My program is a simple little thing that registers a Component, lists all the Components that the Component Manager has, and then waits around indefinately (to avoid purging the Component that it registered).

On my system, the Component Manager is tracking 873 Components (mostly codecs of one sort of another). My program that registers a Component registers it, and then counts 874 Components because it just registered one itself, of course). Here's the source:

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 );
    }
}

Anyways, when I run this, keep it running (so the Component would presumably stay registered with the Component Manager), and then run Fiendishthngs, Fiendishthngs can't see my test Component that I register - it only sees 873 Components. The 'registerComponentGlobal' flag passed into RegisterComponent() is supposed to make the Component available to other processes, but it seems like something is going awry.

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

戏舞 2024-08-21 06:37:35

好吧,我把这个问题抛在脑后,接受了 OS X 的组件管理器可能不再支持“全局”选项的事实。

这真的很有意义。使您的组件从您的进程到其他进程“全局”需要进程外调用编组,就像 OS X 中的 RPC 一样。另一方面,在 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)被完全忽略。

Well, I left this issue behind, resigning myself to the fact that OS X's Component Manager probably doesn't support the 'global' option anymore.

This would make a lot of sense, really. Making your component 'global' from your process to other processes would require out-of-process call marshalling, like with RPC, with OS X. On the other hand, in OS 9 and earlier, it would make perfect sense, given that all processes lived in a common address space. For OS 9 it would be trivial to make a component globally available to all processes.

Anyways, today I was disassembling RegisterComponentFileRefEntries() where the relevant code seems to reside, and sure enough, I saw this in the pre-amble to the function (the comments are mine):

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

The signature for RegisterComponentFileRefEntries is

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

The only 2 parameters that RegisterComponentFileRefEntries bothers with are spec (at ebp+0x8) and toRegister (at ebp+0x10). global (at ebp+0xc) and registerCount (at ebp+0x14) are completely ignored.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文