- , - . (DLL), . SCM.
, DLL . , - ( ) . DLL- (surrogate processes) . , , 6.
, , , , CLSID , . Windows NT 5.0 NT (NT Directory). , , - . NT - . , Class Store ( - ). Class Store CLSID ( ) - ( ). CLSID , . , Class Store , . , - , . , Class Store, .
, Class Store, , (Registry). , , CLSID ( ) ( ). Windows NT 5.0 . (keys), , . , , . Windows NT 4.0
HKEY_LOCAL_MACHINE\Software\Classes
HKEY_CLASSES_ROOT
Windows NT 5.0 HKEY_CLASSES_ROOT , CLSID . Windows NT 5.0
HKEY_CURRENT_USER\Software\Classes
HKEY_CLASSES_ROOT. HKLM, HKCR HKCU HKEY_LOCAL_MACHINE, HKEY_CLASSES_ROOT HKEY_CURRENT_USER, 1.
, CLSID ,
HKCR\CLSID
Windows NT 5.0
HKCU\Software\Classes\CLSID
CLSID, CLSID . , Gorilla, , 2:
[HKCR\CLSID\{571F1680-CC83-11d0-8C48-0080C73925BA}] @="Gorilla"
Gorilla CLSID Gorilla , , . DLL, :
[HKCR\CLSID\{571F1680-CC83-11d0-8C48-0080C73925BA}\InprocServer32] @="C:\ServerOfTheApes.dll"
, , :
[HKCR\CLSID\{571F1680-CC83-11d0-8C48-0080C73925BA}\LocalServer32] @=" :\ServerOfTheApes.exe"
, . ProgIDFromCLSID :
[HKCR\CLSID\{571F1680-CC83-11d0-8C48-0080C73925BA}\ProgID] @="Apes.Gorilla.1"
, CLSIDFromProgID :
[HKCR\Apes.Gorilla.1] @="Gorilla" [HKCR\Apes.Gorilla.1\CLSID] @="\{571F1680-CC83-11d0-8C48-0080C73925BA}
(ProgID) , , , CLSID, .
. , DLL
STDAPI DllRegisterServer(void); STDAPI DllUnregisterServer(void);
, STDAPI , , RESULT . , , . Class Store . Class Store ( , Microsoft Transaction Server, ActiveX Code Download, ) - . Win32 SDK REGSVR32.EXE, .
DllRegisterServer DllUnregisterServer , CLSID ProgID . , , , , , RegSetValueEx RegDeleteKey . , , Nx3, , :
const char *g_RegTable[][3] = { // format is { key, value name, value } { "CLSID\\{571F1680-CC83-11d0-8C48-0080C73925BA}", 0, "Gorilla" }, { "CLSID\\{571F1680-CC83-11d0-8C48-0080C73925BA}\\InprocServer32",0, (const char*)-1 // rogue value indicating file name // , }, { "CLSID\\{571F1680-CC83-11d0-8C48-0080C73925BA}\\ProgID", 0, " s.Gorilla.1" }, { "Apes.Gorill .1", 0, "Gorilla" }, { "Apes.Gorilla.1\\CLSID", 0, "{571F1680-CC83-11d0-8C48-0080C73925BA}" }, };
, DllRegisterServer:
STDAPI DllRegisterServer(void) { HRESULT hr = S_OK; // look up server's file name // char szFileName[MAX_PATH]; GetModuleFileNameA(g_hinstDll, szFileName, MAX_PATH); // register entries from table // int nEntries = sizeof(g_RegTable)/sizeof(*g_RegTable); for (int i = 0; SUCCEEDED(hr) && i < nEntries; i++) { const char *pszKeyName = g_RegTable[i][0]; const char *pszValueName = g_RegTable[i][1]; const char *pszvalue = g_RegTable[i][2]; // map rogue value to module file name // if (pszValue == (const char*)-1) pszValue = szFileName; HKEY hkey; // create the key // long err = RegCreateKeyA(HKEY_CLASSES_ROOT, pszKeyName, &hkey); if (err == ERROR_SUCCESS) { // set the value // err = RegSetValueExA(hkey, pszVvalueName, 0, REG_SZ, (const BYTE*) pszValue, (strlen(pszValue) + 1)); RegCloseKey(hkey); } if (err != ERROR_SUCCESS) { // if cannot add key or value, back out and fail // , DllUnregisterServer(); hr = SELFREG_E_CLASS; } } return hr; }
DllUnregisterServer :
STDAPI DllUnregisterServer(void) { HRESULT hr = S_OK; int nEntries = sizeof(g_RegTable)/sizeof(*g_RegTable); for (int i = nEntries - 1; i >= 0; i--) { const char *pszKeyName = g_RegTable[i][0]; long err = RegDeleteKeyA(HKEY_CLASSES_ROOT, pszKeyName); if (err != ERROR_SUCCESS) hr = S_FALSE; } return hr; }
, DllUnregisterServer , . RegDeleteKey, , , . DllUnregisterServer , .
CLSID , . , , API- CLSID. API- 6. , DLL, DLL , CoGetClassObject, . , :
HRESULT DllGetClassObject( [in] REFCLSID rclsid, // which class object? // ? [in] REFIID riid, // which interface? // ? [out, iid_is(riid)] void **ppv); // put it here! // !
. DllGetClassObject , . .
, : Gorilla, Chimp Orangutan. , , C++: , . , DllGetClassObject :
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv) { // define a singleton class object for each class // // static GorillaClass s_gorillaClass; static OrangutanClass s_orangutanClass; static ChimpClass s_chimpClass; // return interface pointers to known classes // if (rclsid == CLSID_Gorilla) return s_gorillaClass.QueryInterface(riid, ppv); else if (rclsid == CLSID_Orangutan) return s_orangutanClass.QueryInterface(riid, ppv); else if (rclsid == CLSID_Chimp) return s_chimpClass.QueryInterface(riid, ppv); // if we get to here, rclsid is a class we don't implement, // so fail with well-known error code // , rclsid - , // , *ppv = 0; return CLASS_E_CLASSNOTAVAILABLE; }
, , . QueryInterface .
, API- CoGetClassObject DllGetClassObject:
// pseudo-code from OLE32.DLL // OLE32.DLL HRESULT CoGetClassObject(REFCLSID rclsid, DWORD dwClsCtx, COSERVERINFO *pcsi , REFIID riid, void **ppv) { HRESULT hr = REGDB_E_CLASSNOTREG; *ppv = 0; if (dwClsCtx & CLSCTX_INPROC) { // try to perform inproc activation // HRESULT (*pfnGCO)(REFCLSID, REFIID, void**) = 0; // look in table of already loaded servers in this process // // pfnGCO = LookupInClassTable(rclsid, dwClsCtx); if (pfnGCO == 0) { // not loaded yet! // ! // ask class store or registry for DLL name // DLL- char szFileName[MAX_PATH]; hr = GetFileFromClassStoreOrRegistry(rclsid, dwClsCtx, szFileName); if (SUCCEEDED(hr)) { // try to load the DLL and scrape out DllGetClassObject // DLL DllGetClassObject HINSTANCE hInst = LoadLibrary(szFileName); if (hInst == 0) return CO_E_DLLNOTFOUND; pfnGCO = GetProcAddress(hInst, "DllGetClassObject"); if (pfnGCO == 0) return CO_E_ERRORINDLL; // cache DLL for later use // DLL InsertInClassTable(rclsid, dwClsCtx, hInst, pfnGCO); } } // call function to get pointer to class object // hr = (*pfnGCO)(rclsid, riid, ppv); } if ((dwClsCtx & (CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER)) && hr == REGDB_E_CLASSNOTREG) { // handle out-of-proc/remote request // / } return hr; }
, CoGetClassObject , DllGetClassObject. , , DllGetClassObject private :
// from APELIB.DEF // APELIB.DEF LIBRARY APELIB EXPORTS DllGetClassObject private
, .
1 . . .
2 REGEDIT4. , , . = (name = value) , . "@" .