Self-Registration

After having looked at the details of creating and exposing a server's class factories, implementing self-registration is a snap. Three samples demonstrate this feature: SelfReg (CHAP05\SELFREG), DKoala2 (CHAP05\DKOALA2), and EKoala2 (CHAP05\EKOALA2). The two servers are simple enhancements to DKoala1 and EKoala1 to support self-registration. SelfReg is nothing more than a command-line tool (a Windows application nevertheless) with the following syntax:


selfreg [/e] [/u] <path to server>

The /e switch specifies that the path is to an EXE as opposed to a DLL, and /u instructs the server to unregister as opposed to register. The code in SELFREG.CPP parses the command line and generates the appropriate calls: when the code sees /e, it will attempt to call WinExec with the given path, passing /REGSERVER or /UNREGSERVER as the command line, depending on the presence of /u. If /e is not present, SelfReg calls CoLoadLibrary with the server specified on the path and then calls DllRegisterServer or DllUnregisterServer, depending again on /u. SelfReg displays a message box with the result of whatever sequence it executes (and calls CoFreeLibrary to unload the DLL).

Prior to calling CoLoadLibrary, SelfReg calls CoInitialize. It then calls CoUninitialize after calling CoFreeLibrary. SelfReg does this because in-process servers will expect that COM has been initialized by the application that owns the process. SelfReg falls into that category and so must perform the initialization.

How you actually choose to create the registry entries from within the server itself is up to you. You can use either the straight registry APIs (RegCreateKeyEx, RegSetValueEx, RegCloseKey, RegDeleteKey, and so on) as done in DKoala2 and EKoala2, or you can use another technique, such as launching REGEDIT.EXE with an appropriate registration file. What is most important in all of this is that the InprocServer32, InprocHandler32, and LocalServer32 entries have values equivalent to the full path of the loaded module. This is true also for any entries for your type libraries, which you should also register at this time. These paths are the only entries that depend on the directory in which the component resides, and that directory is the most important way OLE has of finding a component. This isn't hard to accomplish, mind you, as the Windows function GetModuleFilename gives you the full path to the loaded server, exactly what you want to store in the registry. If you perform registration using a REG file, be sure to update the keys with pathnames in them after that process is complete.

A final note to make here is that the function RegDeleteKey is picky: it will not delete a registry key if there are any subkeys below it. This means that just as you need to register entries one by one, you have to delete them one by one. You want to delete only the keys and subkeys that you registered from within your own server because other servers might have stored, for example, a TreatAs key under your CLSID. If you simply removed everything in the registry that pertained to your server, you'd obliterate this TreatAs key and potentially break clients that weren't using your server anyway. So delete only what you stored in the registry, and leave the rest alone.