Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencomcat.c
Go to the documentation of this file.
00001 /* 00002 * Comcat implementation 00003 * 00004 * Copyright (C) 2002 John K. Hohm 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #include <string.h> 00022 #include <stdarg.h> 00023 00024 #define COBJMACROS 00025 00026 #include "windef.h" 00027 #include "winbase.h" 00028 #include "winuser.h" 00029 #include "winreg.h" 00030 #include "winerror.h" 00031 00032 #include "ole2.h" 00033 #include "comcat.h" 00034 #include "wine/unicode.h" 00035 #include "wine/debug.h" 00036 00037 WINE_DEFAULT_DEBUG_CHANNEL(ole); 00038 00039 static const ICatRegisterVtbl COMCAT_ICatRegister_Vtbl; 00040 static const ICatInformationVtbl COMCAT_ICatInformation_Vtbl; 00041 00042 typedef struct 00043 { 00044 ICatRegister ICatRegister_iface; 00045 ICatInformation ICatInformation_iface; 00046 } ComCatMgrImpl; 00047 00048 /* static ComCatMgr instance */ 00049 static ComCatMgrImpl COMCAT_ComCatMgr = 00050 { 00051 { &COMCAT_ICatRegister_Vtbl }, 00052 { &COMCAT_ICatInformation_Vtbl } 00053 }; 00054 00055 struct class_categories { 00056 LPCWSTR impl_strings; 00057 LPCWSTR req_strings; 00058 }; 00059 00060 static IEnumCATEGORYINFO *COMCAT_IEnumCATEGORYINFO_Construct(LCID lcid); 00061 static LPENUMGUID COMCAT_CLSID_IEnumGUID_Construct(struct class_categories *class_categories); 00062 static LPENUMGUID COMCAT_CATID_IEnumGUID_Construct(REFCLSID rclsid, LPCWSTR impl_req); 00063 00064 /********************************************************************** 00065 * File-scope string constants 00066 */ 00067 static const WCHAR comcat_keyname[] = { 00068 'C','o','m','p','o','n','e','n','t',' ','C','a','t','e','g','o','r','i','e','s',0 }; 00069 static const WCHAR impl_keyname[] = { 00070 'I','m','p','l','e','m','e','n','t','e','d',' ','C','a','t','e','g','o','r','i','e','s',0 }; 00071 static const WCHAR req_keyname[] = { 00072 'R','e','q','u','i','r','e','d',' ','C','a','t','e','g','o','r','i','e','s',0 }; 00073 static const WCHAR clsid_keyname[] = { 'C','L','S','I','D',0 }; 00074 00075 00076 /********************************************************************** 00077 * COMCAT_RegisterClassCategories 00078 */ 00079 static HRESULT COMCAT_RegisterClassCategories( 00080 REFCLSID rclsid, 00081 LPCWSTR type, 00082 ULONG cCategories, 00083 const CATID *rgcatid) 00084 { 00085 WCHAR keyname[39]; 00086 HRESULT res; 00087 HKEY clsid_key, class_key, type_key; 00088 00089 if (cCategories && rgcatid == NULL) return E_POINTER; 00090 00091 /* Format the class key name. */ 00092 res = StringFromGUID2(rclsid, keyname, 39); 00093 if (FAILED(res)) return res; 00094 00095 /* Create (or open) the CLSID key. */ 00096 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0, 00097 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL); 00098 if (res != ERROR_SUCCESS) return E_FAIL; 00099 00100 /* Create (or open) the class key. */ 00101 res = RegCreateKeyExW(clsid_key, keyname, 0, NULL, 0, 00102 KEY_READ | KEY_WRITE, NULL, &class_key, NULL); 00103 if (res == ERROR_SUCCESS) { 00104 /* Create (or open) the category type key. */ 00105 res = RegCreateKeyExW(class_key, type, 0, NULL, 0, 00106 KEY_READ | KEY_WRITE, NULL, &type_key, NULL); 00107 if (res == ERROR_SUCCESS) { 00108 for (; cCategories; --cCategories, ++rgcatid) { 00109 HKEY key; 00110 00111 /* Format the category key name. */ 00112 res = StringFromGUID2(rgcatid, keyname, 39); 00113 if (FAILED(res)) continue; 00114 00115 /* Do the register. */ 00116 res = RegCreateKeyExW(type_key, keyname, 0, NULL, 0, 00117 KEY_READ | KEY_WRITE, NULL, &key, NULL); 00118 if (res == ERROR_SUCCESS) RegCloseKey(key); 00119 } 00120 res = S_OK; 00121 } else res = E_FAIL; 00122 RegCloseKey(class_key); 00123 } else res = E_FAIL; 00124 RegCloseKey(clsid_key); 00125 00126 return res; 00127 } 00128 00129 /********************************************************************** 00130 * COMCAT_UnRegisterClassCategories 00131 */ 00132 static HRESULT COMCAT_UnRegisterClassCategories( 00133 REFCLSID rclsid, 00134 LPCWSTR type, 00135 ULONG cCategories, 00136 const CATID *rgcatid) 00137 { 00138 WCHAR keyname[68] = { 'C', 'L', 'S', 'I', 'D', '\\' }; 00139 HRESULT res; 00140 HKEY type_key; 00141 00142 if (cCategories && rgcatid == NULL) return E_POINTER; 00143 00144 /* Format the class category type key name. */ 00145 res = StringFromGUID2(rclsid, keyname + 6, 39); 00146 if (FAILED(res)) return res; 00147 keyname[44] = '\\'; 00148 lstrcpyW(keyname + 45, type); 00149 00150 /* Open the class category type key. */ 00151 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, 00152 KEY_READ | KEY_WRITE, &type_key); 00153 if (res != ERROR_SUCCESS) return E_FAIL; 00154 00155 for (; cCategories; --cCategories, ++rgcatid) { 00156 /* Format the category key name. */ 00157 res = StringFromGUID2(rgcatid, keyname, 39); 00158 if (FAILED(res)) continue; 00159 00160 /* Do the unregister. */ 00161 RegDeleteKeyW(type_key, keyname); 00162 } 00163 RegCloseKey(type_key); 00164 00165 return S_OK; 00166 } 00167 00168 /********************************************************************** 00169 * COMCAT_GetCategoryDesc 00170 */ 00171 static HRESULT COMCAT_GetCategoryDesc(HKEY key, LCID lcid, PWCHAR pszDesc, 00172 ULONG buf_wchars) 00173 { 00174 static const WCHAR fmt[] = { '%', 'l', 'X', 0 }; 00175 WCHAR valname[5]; 00176 HRESULT res; 00177 DWORD type, size = (buf_wchars - 1) * sizeof(WCHAR); 00178 00179 if (pszDesc == NULL) return E_INVALIDARG; 00180 00181 /* FIXME: lcid comparisons are more complex than this! */ 00182 wsprintfW(valname, fmt, lcid); 00183 res = RegQueryValueExW(key, valname, 0, &type, (LPBYTE)pszDesc, &size); 00184 if (res != ERROR_SUCCESS || type != REG_SZ) { 00185 FIXME("Simplified lcid comparison\n"); 00186 return CAT_E_NODESCRIPTION; 00187 } 00188 pszDesc[size / sizeof(WCHAR)] = 0; 00189 00190 return S_OK; 00191 } 00192 00193 /********************************************************************** 00194 * COMCAT_PrepareClassCategories 00195 */ 00196 static struct class_categories *COMCAT_PrepareClassCategories( 00197 ULONG impl_count, const CATID *impl_catids, ULONG req_count, const CATID *req_catids) 00198 { 00199 struct class_categories *categories; 00200 WCHAR *strings; 00201 00202 categories = HeapAlloc( 00203 GetProcessHeap(), HEAP_ZERO_MEMORY, 00204 sizeof(struct class_categories) + 00205 ((impl_count + req_count) * 39 + 2) * sizeof(WCHAR)); 00206 if (categories == NULL) return categories; 00207 00208 strings = (WCHAR *)(categories + 1); 00209 categories->impl_strings = strings; 00210 while (impl_count--) { 00211 StringFromGUID2(impl_catids++, strings, 39); 00212 strings += 39; 00213 } 00214 *strings++ = 0; 00215 00216 categories->req_strings = strings; 00217 while (req_count--) { 00218 StringFromGUID2(req_catids++, strings, 39); 00219 strings += 39; 00220 } 00221 *strings++ = 0; 00222 00223 return categories; 00224 } 00225 00226 /********************************************************************** 00227 * COMCAT_IsClassOfCategories 00228 */ 00229 static HRESULT COMCAT_IsClassOfCategories( 00230 HKEY key, 00231 struct class_categories const* categories) 00232 { 00233 HKEY subkey; 00234 HRESULT res; 00235 DWORD index; 00236 LPCWSTR string; 00237 00238 /* Check that every given category is implemented by class. */ 00239 if (*categories->impl_strings) { 00240 res = RegOpenKeyExW(key, impl_keyname, 0, KEY_READ, &subkey); 00241 if (res != ERROR_SUCCESS) return S_FALSE; 00242 for (string = categories->impl_strings; *string; string += 39) { 00243 HKEY catkey; 00244 res = RegOpenKeyExW(subkey, string, 0, 0, &catkey); 00245 if (res != ERROR_SUCCESS) { 00246 RegCloseKey(subkey); 00247 return S_FALSE; 00248 } 00249 RegCloseKey(catkey); 00250 } 00251 RegCloseKey(subkey); 00252 } 00253 00254 /* Check that all categories required by class are given. */ 00255 res = RegOpenKeyExW(key, req_keyname, 0, KEY_READ, &subkey); 00256 if (res == ERROR_SUCCESS) { 00257 for (index = 0; ; ++index) { 00258 WCHAR keyname[39]; 00259 DWORD size = 39; 00260 00261 res = RegEnumKeyExW(subkey, index, keyname, &size, 00262 NULL, NULL, NULL, NULL); 00263 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break; 00264 if (size != 38) continue; /* bogus catid in registry */ 00265 for (string = categories->req_strings; *string; string += 39) 00266 if (!strcmpiW(string, keyname)) break; 00267 if (!*string) { 00268 RegCloseKey(subkey); 00269 return S_FALSE; 00270 } 00271 } 00272 RegCloseKey(subkey); 00273 } 00274 00275 return S_OK; 00276 } 00277 00278 /********************************************************************** 00279 * COMCAT_ICatRegister_QueryInterface 00280 */ 00281 static HRESULT WINAPI COMCAT_ICatRegister_QueryInterface( 00282 LPCATREGISTER iface, 00283 REFIID riid, 00284 LPVOID *ppvObj) 00285 { 00286 TRACE("%s\n",debugstr_guid(riid)); 00287 00288 if (ppvObj == NULL) return E_POINTER; 00289 00290 if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_ICatRegister)) { 00291 *ppvObj = iface; 00292 ICatRegister_AddRef(iface); 00293 return S_OK; 00294 } 00295 00296 if (IsEqualGUID(riid, &IID_ICatInformation)) { 00297 *ppvObj = &COMCAT_ComCatMgr.ICatInformation_iface; 00298 ICatRegister_AddRef(iface); 00299 return S_OK; 00300 } 00301 00302 return E_NOINTERFACE; 00303 } 00304 00305 /********************************************************************** 00306 * COMCAT_ICatRegister_AddRef 00307 */ 00308 static ULONG WINAPI COMCAT_ICatRegister_AddRef(LPCATREGISTER iface) 00309 { 00310 return 2; /* non-heap based object */ 00311 } 00312 00313 /********************************************************************** 00314 * COMCAT_ICatRegister_Release 00315 */ 00316 static ULONG WINAPI COMCAT_ICatRegister_Release(LPCATREGISTER iface) 00317 { 00318 return 1; /* non-heap based object */ 00319 } 00320 00321 /********************************************************************** 00322 * COMCAT_ICatRegister_RegisterCategories 00323 */ 00324 static HRESULT WINAPI COMCAT_ICatRegister_RegisterCategories( 00325 LPCATREGISTER iface, 00326 ULONG cCategories, 00327 CATEGORYINFO *rgci) 00328 { 00329 HKEY comcat_key; 00330 HRESULT res; 00331 00332 TRACE("\n"); 00333 00334 if (cCategories && rgci == NULL) 00335 return E_POINTER; 00336 00337 /* Create (or open) the component categories key. */ 00338 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, comcat_keyname, 0, NULL, 0, 00339 KEY_READ | KEY_WRITE, NULL, &comcat_key, NULL); 00340 if (res != ERROR_SUCCESS) return E_FAIL; 00341 00342 for (; cCategories; --cCategories, ++rgci) { 00343 static const WCHAR fmt[] = { '%', 'l', 'X', 0 }; 00344 WCHAR keyname[39]; 00345 WCHAR valname[9]; 00346 HKEY cat_key; 00347 00348 /* Create (or open) the key for this category. */ 00349 if (!StringFromGUID2(&rgci->catid, keyname, 39)) continue; 00350 res = RegCreateKeyExW(comcat_key, keyname, 0, NULL, 0, 00351 KEY_READ | KEY_WRITE, NULL, &cat_key, NULL); 00352 if (res != ERROR_SUCCESS) continue; 00353 00354 /* Set the value for this locale's description. */ 00355 wsprintfW(valname, fmt, rgci->lcid); 00356 RegSetValueExW(cat_key, valname, 0, REG_SZ, 00357 (CONST BYTE*)(rgci->szDescription), 00358 (lstrlenW(rgci->szDescription) + 1) * sizeof(WCHAR)); 00359 00360 RegCloseKey(cat_key); 00361 } 00362 00363 RegCloseKey(comcat_key); 00364 return S_OK; 00365 } 00366 00367 /********************************************************************** 00368 * COMCAT_ICatRegister_UnRegisterCategories 00369 */ 00370 static HRESULT WINAPI COMCAT_ICatRegister_UnRegisterCategories( 00371 LPCATREGISTER iface, 00372 ULONG cCategories, 00373 CATID *rgcatid) 00374 { 00375 HKEY comcat_key; 00376 HRESULT res; 00377 00378 TRACE("\n"); 00379 00380 if (cCategories && rgcatid == NULL) 00381 return E_POINTER; 00382 00383 /* Open the component categories key. */ 00384 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, comcat_keyname, 0, 00385 KEY_READ | KEY_WRITE, &comcat_key); 00386 if (res != ERROR_SUCCESS) return E_FAIL; 00387 00388 for (; cCategories; --cCategories, ++rgcatid) { 00389 WCHAR keyname[39]; 00390 00391 /* Delete the key for this category. */ 00392 if (!StringFromGUID2(rgcatid, keyname, 39)) continue; 00393 RegDeleteKeyW(comcat_key, keyname); 00394 } 00395 00396 RegCloseKey(comcat_key); 00397 return S_OK; 00398 } 00399 00400 /********************************************************************** 00401 * COMCAT_ICatRegister_RegisterClassImplCategories 00402 */ 00403 static HRESULT WINAPI COMCAT_ICatRegister_RegisterClassImplCategories( 00404 LPCATREGISTER iface, 00405 REFCLSID rclsid, 00406 ULONG cCategories, 00407 CATID *rgcatid) 00408 { 00409 TRACE("\n"); 00410 00411 return COMCAT_RegisterClassCategories( 00412 rclsid, impl_keyname, cCategories, rgcatid); 00413 } 00414 00415 /********************************************************************** 00416 * COMCAT_ICatRegister_UnRegisterClassImplCategories 00417 */ 00418 static HRESULT WINAPI COMCAT_ICatRegister_UnRegisterClassImplCategories( 00419 LPCATREGISTER iface, 00420 REFCLSID rclsid, 00421 ULONG cCategories, 00422 CATID *rgcatid) 00423 { 00424 TRACE("\n"); 00425 00426 return COMCAT_UnRegisterClassCategories( 00427 rclsid, impl_keyname, cCategories, rgcatid); 00428 } 00429 00430 /********************************************************************** 00431 * COMCAT_ICatRegister_RegisterClassReqCategories 00432 */ 00433 static HRESULT WINAPI COMCAT_ICatRegister_RegisterClassReqCategories( 00434 LPCATREGISTER iface, 00435 REFCLSID rclsid, 00436 ULONG cCategories, 00437 CATID *rgcatid) 00438 { 00439 TRACE("\n"); 00440 00441 return COMCAT_RegisterClassCategories( 00442 rclsid, req_keyname, cCategories, rgcatid); 00443 } 00444 00445 /********************************************************************** 00446 * COMCAT_ICatRegister_UnRegisterClassReqCategories 00447 */ 00448 static HRESULT WINAPI COMCAT_ICatRegister_UnRegisterClassReqCategories( 00449 LPCATREGISTER iface, 00450 REFCLSID rclsid, 00451 ULONG cCategories, 00452 CATID *rgcatid) 00453 { 00454 TRACE("\n"); 00455 00456 return COMCAT_UnRegisterClassCategories( 00457 rclsid, req_keyname, cCategories, rgcatid); 00458 } 00459 00460 /********************************************************************** 00461 * COMCAT_ICatInformation_QueryInterface 00462 */ 00463 static HRESULT WINAPI COMCAT_ICatInformation_QueryInterface( 00464 LPCATINFORMATION iface, 00465 REFIID riid, 00466 LPVOID *ppvObj) 00467 { 00468 return ICatRegister_QueryInterface(&COMCAT_ComCatMgr.ICatRegister_iface, riid, ppvObj); 00469 } 00470 00471 /********************************************************************** 00472 * COMCAT_ICatInformation_AddRef 00473 */ 00474 static ULONG WINAPI COMCAT_ICatInformation_AddRef(LPCATINFORMATION iface) 00475 { 00476 return ICatRegister_AddRef(&COMCAT_ComCatMgr.ICatRegister_iface); 00477 } 00478 00479 /********************************************************************** 00480 * COMCAT_ICatInformation_Release 00481 */ 00482 static ULONG WINAPI COMCAT_ICatInformation_Release(LPCATINFORMATION iface) 00483 { 00484 return ICatRegister_Release(&COMCAT_ComCatMgr.ICatRegister_iface); 00485 } 00486 00487 /********************************************************************** 00488 * COMCAT_ICatInformation_EnumCategories 00489 */ 00490 static HRESULT WINAPI COMCAT_ICatInformation_EnumCategories( 00491 LPCATINFORMATION iface, 00492 LCID lcid, 00493 IEnumCATEGORYINFO **ppenumCatInfo) 00494 { 00495 TRACE("\n"); 00496 00497 if (ppenumCatInfo == NULL) return E_POINTER; 00498 00499 *ppenumCatInfo = COMCAT_IEnumCATEGORYINFO_Construct(lcid); 00500 if (*ppenumCatInfo == NULL) return E_OUTOFMEMORY; 00501 IEnumCATEGORYINFO_AddRef(*ppenumCatInfo); 00502 return S_OK; 00503 } 00504 00505 /********************************************************************** 00506 * COMCAT_ICatInformation_GetCategoryDesc 00507 */ 00508 static HRESULT WINAPI COMCAT_ICatInformation_GetCategoryDesc( 00509 LPCATINFORMATION iface, 00510 REFCATID rcatid, 00511 LCID lcid, 00512 PWCHAR *ppszDesc) 00513 { 00514 WCHAR keyname[60] = { 'C', 'o', 'm', 'p', 'o', 'n', 'e', 'n', 00515 't', ' ', 'C', 'a', 't', 'e', 'g', 'o', 00516 'r', 'i', 'e', 's', '\\', 0 }; 00517 HKEY key; 00518 HRESULT res; 00519 00520 TRACE("CATID: %s LCID: %x\n",debugstr_guid(rcatid), lcid); 00521 00522 if (rcatid == NULL || ppszDesc == NULL) return E_INVALIDARG; 00523 00524 /* Open the key for this category. */ 00525 if (!StringFromGUID2(rcatid, keyname + 21, 39)) return E_FAIL; 00526 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &key); 00527 if (res != ERROR_SUCCESS) return CAT_E_CATIDNOEXIST; 00528 00529 /* Allocate a sensible amount of memory for the description. */ 00530 *ppszDesc = CoTaskMemAlloc(128 * sizeof(WCHAR)); 00531 if (*ppszDesc == NULL) { 00532 RegCloseKey(key); 00533 return E_OUTOFMEMORY; 00534 } 00535 00536 /* Get the description, and make sure it's null terminated. */ 00537 res = COMCAT_GetCategoryDesc(key, lcid, *ppszDesc, 128); 00538 RegCloseKey(key); 00539 if (FAILED(res)) { 00540 CoTaskMemFree(*ppszDesc); 00541 return res; 00542 } 00543 00544 return S_OK; 00545 } 00546 00547 /********************************************************************** 00548 * COMCAT_ICatInformation_EnumClassesOfCategories 00549 */ 00550 static HRESULT WINAPI COMCAT_ICatInformation_EnumClassesOfCategories( 00551 LPCATINFORMATION iface, 00552 ULONG cImplemented, 00553 CATID *rgcatidImpl, 00554 ULONG cRequired, 00555 CATID *rgcatidReq, 00556 LPENUMCLSID *ppenumCLSID) 00557 { 00558 struct class_categories *categories; 00559 00560 TRACE("\n"); 00561 00562 if (cImplemented == (ULONG)-1) 00563 cImplemented = 0; 00564 if (cRequired == (ULONG)-1) 00565 cRequired = 0; 00566 00567 if (ppenumCLSID == NULL || 00568 (cImplemented && rgcatidImpl == NULL) || 00569 (cRequired && rgcatidReq == NULL)) return E_POINTER; 00570 00571 categories = COMCAT_PrepareClassCategories(cImplemented, rgcatidImpl, 00572 cRequired, rgcatidReq); 00573 if (categories == NULL) return E_OUTOFMEMORY; 00574 *ppenumCLSID = COMCAT_CLSID_IEnumGUID_Construct(categories); 00575 if (*ppenumCLSID == NULL) { 00576 HeapFree(GetProcessHeap(), 0, categories); 00577 return E_OUTOFMEMORY; 00578 } 00579 IEnumGUID_AddRef(*ppenumCLSID); 00580 return S_OK; 00581 } 00582 00583 /********************************************************************** 00584 * COMCAT_ICatInformation_IsClassOfCategories 00585 */ 00586 static HRESULT WINAPI COMCAT_ICatInformation_IsClassOfCategories( 00587 LPCATINFORMATION iface, 00588 REFCLSID rclsid, 00589 ULONG cImplemented, 00590 CATID *rgcatidImpl, 00591 ULONG cRequired, 00592 CATID *rgcatidReq) 00593 { 00594 WCHAR keyname[45] = { 'C', 'L', 'S', 'I', 'D', '\\', 0 }; 00595 HRESULT res; 00596 struct class_categories *categories; 00597 HKEY key; 00598 00599 if (TRACE_ON(ole)) { 00600 ULONG count; 00601 TRACE("CLSID: %s Implemented %u\n",debugstr_guid(rclsid),cImplemented); 00602 for (count = 0; count < cImplemented; ++count) 00603 TRACE(" %s\n",debugstr_guid(&rgcatidImpl[count])); 00604 TRACE("Required %u\n",cRequired); 00605 for (count = 0; count < cRequired; ++count) 00606 TRACE(" %s\n",debugstr_guid(&rgcatidReq[count])); 00607 } 00608 00609 if ((cImplemented && rgcatidImpl == NULL) || 00610 (cRequired && rgcatidReq == NULL)) return E_POINTER; 00611 00612 res = StringFromGUID2(rclsid, keyname + 6, 39); 00613 if (FAILED(res)) return res; 00614 00615 categories = COMCAT_PrepareClassCategories(cImplemented, rgcatidImpl, 00616 cRequired, rgcatidReq); 00617 if (categories == NULL) return E_OUTOFMEMORY; 00618 00619 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &key); 00620 if (res == ERROR_SUCCESS) { 00621 res = COMCAT_IsClassOfCategories(key, categories); 00622 RegCloseKey(key); 00623 } else res = S_FALSE; 00624 00625 HeapFree(GetProcessHeap(), 0, categories); 00626 00627 return res; 00628 } 00629 00630 /********************************************************************** 00631 * COMCAT_ICatInformation_EnumImplCategoriesOfClass 00632 */ 00633 static HRESULT WINAPI COMCAT_ICatInformation_EnumImplCategoriesOfClass( 00634 LPCATINFORMATION iface, 00635 REFCLSID rclsid, 00636 LPENUMCATID *ppenumCATID) 00637 { 00638 static const WCHAR postfix[] = { '\\', 'I', 'm', 'p', 'l', 'e', 'm', 'e', 00639 'n', 't', 'e', 'd', ' ', 'C', 'a', 't', 00640 'e', 'g', 'o', 'r', 'i', 'e', 's', 0 }; 00641 00642 TRACE("%s\n",debugstr_guid(rclsid)); 00643 00644 if (rclsid == NULL || ppenumCATID == NULL) 00645 return E_POINTER; 00646 00647 *ppenumCATID = COMCAT_CATID_IEnumGUID_Construct(rclsid, postfix); 00648 if (*ppenumCATID == NULL) return E_OUTOFMEMORY; 00649 return S_OK; 00650 } 00651 00652 /********************************************************************** 00653 * COMCAT_ICatInformation_EnumReqCategoriesOfClass 00654 */ 00655 static HRESULT WINAPI COMCAT_ICatInformation_EnumReqCategoriesOfClass( 00656 LPCATINFORMATION iface, 00657 REFCLSID rclsid, 00658 LPENUMCATID *ppenumCATID) 00659 { 00660 static const WCHAR postfix[] = { '\\', 'R', 'e', 'q', 'u', 'i', 'r', 'e', 00661 'd', ' ', 'C', 'a', 't', 'e', 'g', 'o', 00662 'r', 'i', 'e', 's', 0 }; 00663 00664 TRACE("%s\n",debugstr_guid(rclsid)); 00665 00666 if (rclsid == NULL || ppenumCATID == NULL) 00667 return E_POINTER; 00668 00669 *ppenumCATID = COMCAT_CATID_IEnumGUID_Construct(rclsid, postfix); 00670 if (*ppenumCATID == NULL) return E_OUTOFMEMORY; 00671 return S_OK; 00672 } 00673 00674 /********************************************************************** 00675 * COMCAT_ICatRegister_Vtbl 00676 */ 00677 static const ICatRegisterVtbl COMCAT_ICatRegister_Vtbl = 00678 { 00679 COMCAT_ICatRegister_QueryInterface, 00680 COMCAT_ICatRegister_AddRef, 00681 COMCAT_ICatRegister_Release, 00682 COMCAT_ICatRegister_RegisterCategories, 00683 COMCAT_ICatRegister_UnRegisterCategories, 00684 COMCAT_ICatRegister_RegisterClassImplCategories, 00685 COMCAT_ICatRegister_UnRegisterClassImplCategories, 00686 COMCAT_ICatRegister_RegisterClassReqCategories, 00687 COMCAT_ICatRegister_UnRegisterClassReqCategories 00688 }; 00689 00690 00691 /********************************************************************** 00692 * COMCAT_ICatInformation_Vtbl 00693 */ 00694 static const ICatInformationVtbl COMCAT_ICatInformation_Vtbl = 00695 { 00696 COMCAT_ICatInformation_QueryInterface, 00697 COMCAT_ICatInformation_AddRef, 00698 COMCAT_ICatInformation_Release, 00699 COMCAT_ICatInformation_EnumCategories, 00700 COMCAT_ICatInformation_GetCategoryDesc, 00701 COMCAT_ICatInformation_EnumClassesOfCategories, 00702 COMCAT_ICatInformation_IsClassOfCategories, 00703 COMCAT_ICatInformation_EnumImplCategoriesOfClass, 00704 COMCAT_ICatInformation_EnumReqCategoriesOfClass 00705 }; 00706 00707 /********************************************************************** 00708 * COMCAT_IClassFactory_QueryInterface (also IUnknown) 00709 */ 00710 static HRESULT WINAPI COMCAT_IClassFactory_QueryInterface( 00711 LPCLASSFACTORY iface, 00712 REFIID riid, 00713 LPVOID *ppvObj) 00714 { 00715 TRACE("%s\n",debugstr_guid(riid)); 00716 00717 if (ppvObj == NULL) return E_POINTER; 00718 00719 if (IsEqualGUID(riid, &IID_IUnknown) || 00720 IsEqualGUID(riid, &IID_IClassFactory)) 00721 { 00722 *ppvObj = iface; 00723 IUnknown_AddRef(iface); 00724 return S_OK; 00725 } 00726 00727 return E_NOINTERFACE; 00728 } 00729 00730 /********************************************************************** 00731 * COMCAT_IClassFactory_AddRef (also IUnknown) 00732 */ 00733 static ULONG WINAPI COMCAT_IClassFactory_AddRef(LPCLASSFACTORY iface) 00734 { 00735 return 2; /* non-heap based object */ 00736 } 00737 00738 /********************************************************************** 00739 * COMCAT_IClassFactory_Release (also IUnknown) 00740 */ 00741 static ULONG WINAPI COMCAT_IClassFactory_Release(LPCLASSFACTORY iface) 00742 { 00743 return 1; /* non-heap based object */ 00744 } 00745 00746 /********************************************************************** 00747 * COMCAT_IClassFactory_CreateInstance 00748 */ 00749 static HRESULT WINAPI COMCAT_IClassFactory_CreateInstance( 00750 LPCLASSFACTORY iface, 00751 LPUNKNOWN pUnkOuter, 00752 REFIID riid, 00753 LPVOID *ppvObj) 00754 { 00755 HRESULT res; 00756 TRACE("%s\n",debugstr_guid(riid)); 00757 00758 if (ppvObj == NULL) return E_POINTER; 00759 00760 /* Don't support aggregation (Windows doesn't) */ 00761 if (pUnkOuter != NULL) return CLASS_E_NOAGGREGATION; 00762 00763 res = ICatRegister_QueryInterface(&COMCAT_ComCatMgr.ICatRegister_iface, riid, ppvObj); 00764 if (SUCCEEDED(res)) { 00765 return res; 00766 } 00767 00768 return CLASS_E_CLASSNOTAVAILABLE; 00769 } 00770 00771 /********************************************************************** 00772 * COMCAT_IClassFactory_LockServer 00773 */ 00774 static HRESULT WINAPI COMCAT_IClassFactory_LockServer( 00775 LPCLASSFACTORY iface, 00776 BOOL fLock) 00777 { 00778 FIXME("(%d), stub!\n",fLock); 00779 return S_OK; 00780 } 00781 00782 /********************************************************************** 00783 * static ClassFactory instance 00784 */ 00785 static const IClassFactoryVtbl ComCatCFVtbl = 00786 { 00787 COMCAT_IClassFactory_QueryInterface, 00788 COMCAT_IClassFactory_AddRef, 00789 COMCAT_IClassFactory_Release, 00790 COMCAT_IClassFactory_CreateInstance, 00791 COMCAT_IClassFactory_LockServer 00792 }; 00793 00794 static const IClassFactoryVtbl *ComCatCF = &ComCatCFVtbl; 00795 00796 HRESULT ComCatCF_Create(REFIID riid, LPVOID *ppv) 00797 { 00798 return IClassFactory_QueryInterface((IClassFactory *)&ComCatCF, riid, ppv); 00799 } 00800 00801 /********************************************************************** 00802 * IEnumCATEGORYINFO implementation 00803 * 00804 * This implementation is not thread-safe. The manager itself is, but 00805 * I can't imagine a valid use of an enumerator in several threads. 00806 */ 00807 typedef struct 00808 { 00809 IEnumCATEGORYINFO IEnumCATEGORYINFO_iface; 00810 LONG ref; 00811 LCID lcid; 00812 HKEY key; 00813 DWORD next_index; 00814 } IEnumCATEGORYINFOImpl; 00815 00816 static inline IEnumCATEGORYINFOImpl *impl_from_IEnumCATEGORYINFO(IEnumCATEGORYINFO *iface) 00817 { 00818 return CONTAINING_RECORD(iface, IEnumCATEGORYINFOImpl, IEnumCATEGORYINFO_iface); 00819 } 00820 00821 static ULONG WINAPI COMCAT_IEnumCATEGORYINFO_AddRef(IEnumCATEGORYINFO *iface) 00822 { 00823 IEnumCATEGORYINFOImpl *This = impl_from_IEnumCATEGORYINFO(iface); 00824 00825 TRACE("\n"); 00826 00827 return InterlockedIncrement(&This->ref); 00828 } 00829 00830 static HRESULT WINAPI COMCAT_IEnumCATEGORYINFO_QueryInterface( 00831 IEnumCATEGORYINFO *iface, 00832 REFIID riid, 00833 LPVOID *ppvObj) 00834 { 00835 TRACE("%s\n",debugstr_guid(riid)); 00836 00837 if (ppvObj == NULL) return E_POINTER; 00838 00839 if (IsEqualGUID(riid, &IID_IUnknown) || 00840 IsEqualGUID(riid, &IID_IEnumCATEGORYINFO)) 00841 { 00842 *ppvObj = iface; 00843 COMCAT_IEnumCATEGORYINFO_AddRef(iface); 00844 return S_OK; 00845 } 00846 00847 return E_NOINTERFACE; 00848 } 00849 00850 static ULONG WINAPI COMCAT_IEnumCATEGORYINFO_Release(IEnumCATEGORYINFO *iface) 00851 { 00852 IEnumCATEGORYINFOImpl *This = impl_from_IEnumCATEGORYINFO(iface); 00853 ULONG ref; 00854 00855 TRACE("\n"); 00856 00857 ref = InterlockedDecrement(&This->ref); 00858 if (ref == 0) { 00859 if (This->key) RegCloseKey(This->key); 00860 HeapFree(GetProcessHeap(), 0, This); 00861 return 0; 00862 } 00863 return ref; 00864 } 00865 00866 static HRESULT WINAPI COMCAT_IEnumCATEGORYINFO_Next( 00867 IEnumCATEGORYINFO *iface, 00868 ULONG celt, 00869 CATEGORYINFO *rgelt, 00870 ULONG *pceltFetched) 00871 { 00872 IEnumCATEGORYINFOImpl *This = impl_from_IEnumCATEGORYINFO(iface); 00873 ULONG fetched = 0; 00874 00875 TRACE("\n"); 00876 00877 if (rgelt == NULL) return E_POINTER; 00878 00879 if (This->key) while (fetched < celt) { 00880 LSTATUS res; 00881 HRESULT hr; 00882 WCHAR catid[39]; 00883 DWORD cName = 39; 00884 HKEY subkey; 00885 00886 res = RegEnumKeyExW(This->key, This->next_index, catid, &cName, 00887 NULL, NULL, NULL, NULL); 00888 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break; 00889 ++(This->next_index); 00890 00891 hr = CLSIDFromString(catid, &rgelt->catid); 00892 if (FAILED(hr)) continue; 00893 00894 res = RegOpenKeyExW(This->key, catid, 0, KEY_READ, &subkey); 00895 if (res != ERROR_SUCCESS) continue; 00896 00897 hr = COMCAT_GetCategoryDesc(subkey, This->lcid, 00898 rgelt->szDescription, 128); 00899 RegCloseKey(subkey); 00900 if (FAILED(hr)) continue; 00901 00902 rgelt->lcid = This->lcid; 00903 ++fetched; 00904 ++rgelt; 00905 } 00906 00907 if (pceltFetched) *pceltFetched = fetched; 00908 return fetched == celt ? S_OK : S_FALSE; 00909 } 00910 00911 static HRESULT WINAPI COMCAT_IEnumCATEGORYINFO_Skip( 00912 IEnumCATEGORYINFO *iface, 00913 ULONG celt) 00914 { 00915 IEnumCATEGORYINFOImpl *This = impl_from_IEnumCATEGORYINFO(iface); 00916 00917 TRACE("\n"); 00918 00919 This->next_index += celt; 00920 /* This should return S_FALSE when there aren't celt elems to skip. */ 00921 return S_OK; 00922 } 00923 00924 static HRESULT WINAPI COMCAT_IEnumCATEGORYINFO_Reset(IEnumCATEGORYINFO *iface) 00925 { 00926 IEnumCATEGORYINFOImpl *This = impl_from_IEnumCATEGORYINFO(iface); 00927 00928 TRACE("\n"); 00929 00930 This->next_index = 0; 00931 return S_OK; 00932 } 00933 00934 static HRESULT WINAPI COMCAT_IEnumCATEGORYINFO_Clone( 00935 IEnumCATEGORYINFO *iface, 00936 IEnumCATEGORYINFO **ppenum) 00937 { 00938 IEnumCATEGORYINFOImpl *This = impl_from_IEnumCATEGORYINFO(iface); 00939 static const WCHAR keyname[] = { 'C', 'o', 'm', 'p', 'o', 'n', 'e', 'n', 00940 't', ' ', 'C', 'a', 't', 'e', 'g', 'o', 00941 'r', 'i', 'e', 's', 0 }; 00942 IEnumCATEGORYINFOImpl *new_this; 00943 00944 TRACE("\n"); 00945 00946 if (ppenum == NULL) return E_POINTER; 00947 00948 new_this = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumCATEGORYINFOImpl)); 00949 if (new_this == NULL) return E_OUTOFMEMORY; 00950 00951 new_this->IEnumCATEGORYINFO_iface = This->IEnumCATEGORYINFO_iface; 00952 new_this->ref = 1; 00953 new_this->lcid = This->lcid; 00954 /* FIXME: could we more efficiently use DuplicateHandle? */ 00955 RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &new_this->key); 00956 new_this->next_index = This->next_index; 00957 00958 *ppenum = &new_this->IEnumCATEGORYINFO_iface; 00959 return S_OK; 00960 } 00961 00962 static const IEnumCATEGORYINFOVtbl COMCAT_IEnumCATEGORYINFO_Vtbl = 00963 { 00964 COMCAT_IEnumCATEGORYINFO_QueryInterface, 00965 COMCAT_IEnumCATEGORYINFO_AddRef, 00966 COMCAT_IEnumCATEGORYINFO_Release, 00967 COMCAT_IEnumCATEGORYINFO_Next, 00968 COMCAT_IEnumCATEGORYINFO_Skip, 00969 COMCAT_IEnumCATEGORYINFO_Reset, 00970 COMCAT_IEnumCATEGORYINFO_Clone 00971 }; 00972 00973 static IEnumCATEGORYINFO *COMCAT_IEnumCATEGORYINFO_Construct(LCID lcid) 00974 { 00975 IEnumCATEGORYINFOImpl *This; 00976 00977 This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumCATEGORYINFOImpl)); 00978 if (This) { 00979 static const WCHAR keyname[] = { 'C', 'o', 'm', 'p', 'o', 'n', 'e', 'n', 00980 't', ' ', 'C', 'a', 't', 'e', 'g', 'o', 00981 'r', 'i', 'e', 's', 0 }; 00982 00983 This->IEnumCATEGORYINFO_iface.lpVtbl = &COMCAT_IEnumCATEGORYINFO_Vtbl; 00984 This->lcid = lcid; 00985 RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &This->key); 00986 } 00987 return &This->IEnumCATEGORYINFO_iface; 00988 } 00989 00990 /********************************************************************** 00991 * ClassesOfCategories IEnumCLSID (IEnumGUID) implementation 00992 * 00993 * This implementation is not thread-safe. The manager itself is, but 00994 * I can't imagine a valid use of an enumerator in several threads. 00995 */ 00996 typedef struct 00997 { 00998 const IEnumGUIDVtbl *lpVtbl; 00999 LONG ref; 01000 struct class_categories *categories; 01001 HKEY key; 01002 DWORD next_index; 01003 } CLSID_IEnumGUIDImpl; 01004 01005 static ULONG WINAPI COMCAT_CLSID_IEnumGUID_AddRef(LPENUMGUID iface) 01006 { 01007 CLSID_IEnumGUIDImpl *This = (CLSID_IEnumGUIDImpl *)iface; 01008 TRACE("\n"); 01009 01010 return InterlockedIncrement(&This->ref); 01011 } 01012 01013 static HRESULT WINAPI COMCAT_CLSID_IEnumGUID_QueryInterface( 01014 LPENUMGUID iface, 01015 REFIID riid, 01016 LPVOID *ppvObj) 01017 { 01018 TRACE("%s\n",debugstr_guid(riid)); 01019 01020 if (ppvObj == NULL) return E_POINTER; 01021 01022 if (IsEqualGUID(riid, &IID_IUnknown) || 01023 IsEqualGUID(riid, &IID_IEnumGUID)) 01024 { 01025 *ppvObj = iface; 01026 COMCAT_CLSID_IEnumGUID_AddRef(iface); 01027 return S_OK; 01028 } 01029 01030 return E_NOINTERFACE; 01031 } 01032 01033 static ULONG WINAPI COMCAT_CLSID_IEnumGUID_Release(LPENUMGUID iface) 01034 { 01035 CLSID_IEnumGUIDImpl *This = (CLSID_IEnumGUIDImpl *)iface; 01036 ULONG ref; 01037 01038 TRACE("\n"); 01039 01040 ref = InterlockedDecrement(&This->ref); 01041 if (ref == 0) { 01042 if (This->key) RegCloseKey(This->key); 01043 HeapFree(GetProcessHeap(), 0, This->categories); 01044 HeapFree(GetProcessHeap(), 0, This); 01045 return 0; 01046 } 01047 return ref; 01048 } 01049 01050 static HRESULT WINAPI COMCAT_CLSID_IEnumGUID_Next( 01051 LPENUMGUID iface, 01052 ULONG celt, 01053 GUID *rgelt, 01054 ULONG *pceltFetched) 01055 { 01056 CLSID_IEnumGUIDImpl *This = (CLSID_IEnumGUIDImpl *)iface; 01057 ULONG fetched = 0; 01058 01059 TRACE("\n"); 01060 01061 if (rgelt == NULL) return E_POINTER; 01062 01063 if (This->key) while (fetched < celt) { 01064 LSTATUS res; 01065 HRESULT hr; 01066 WCHAR clsid[39]; 01067 DWORD cName = 39; 01068 HKEY subkey; 01069 01070 res = RegEnumKeyExW(This->key, This->next_index, clsid, &cName, 01071 NULL, NULL, NULL, NULL); 01072 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break; 01073 ++(This->next_index); 01074 01075 hr = CLSIDFromString(clsid, rgelt); 01076 if (FAILED(hr)) continue; 01077 01078 res = RegOpenKeyExW(This->key, clsid, 0, KEY_READ, &subkey); 01079 if (res != ERROR_SUCCESS) continue; 01080 01081 hr = COMCAT_IsClassOfCategories(subkey, This->categories); 01082 RegCloseKey(subkey); 01083 if (hr != S_OK) continue; 01084 01085 ++fetched; 01086 ++rgelt; 01087 } 01088 01089 if (pceltFetched) *pceltFetched = fetched; 01090 return fetched == celt ? S_OK : S_FALSE; 01091 } 01092 01093 static HRESULT WINAPI COMCAT_CLSID_IEnumGUID_Skip( 01094 LPENUMGUID iface, 01095 ULONG celt) 01096 { 01097 CLSID_IEnumGUIDImpl *This = (CLSID_IEnumGUIDImpl *)iface; 01098 01099 TRACE("\n"); 01100 01101 This->next_index += celt; 01102 FIXME("Never returns S_FALSE\n"); 01103 return S_OK; 01104 } 01105 01106 static HRESULT WINAPI COMCAT_CLSID_IEnumGUID_Reset(LPENUMGUID iface) 01107 { 01108 CLSID_IEnumGUIDImpl *This = (CLSID_IEnumGUIDImpl *)iface; 01109 01110 TRACE("\n"); 01111 01112 This->next_index = 0; 01113 return S_OK; 01114 } 01115 01116 static HRESULT WINAPI COMCAT_CLSID_IEnumGUID_Clone( 01117 LPENUMGUID iface, 01118 IEnumGUID **ppenum) 01119 { 01120 CLSID_IEnumGUIDImpl *This = (CLSID_IEnumGUIDImpl *)iface; 01121 static const WCHAR keyname[] = { 'C', 'L', 'S', 'I', 'D', 0 }; 01122 CLSID_IEnumGUIDImpl *new_this; 01123 DWORD size; 01124 01125 TRACE("\n"); 01126 01127 if (ppenum == NULL) return E_POINTER; 01128 01129 new_this = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLSID_IEnumGUIDImpl)); 01130 if (new_this == NULL) return E_OUTOFMEMORY; 01131 01132 new_this->lpVtbl = This->lpVtbl; 01133 new_this->ref = 1; 01134 size = HeapSize(GetProcessHeap(), 0, This->categories); 01135 new_this->categories = 01136 HeapAlloc(GetProcessHeap(), 0, size); 01137 if (new_this->categories == NULL) { 01138 HeapFree(GetProcessHeap(), 0, new_this); 01139 return E_OUTOFMEMORY; 01140 } 01141 memcpy(new_this->categories, This->categories, size); 01142 /* FIXME: could we more efficiently use DuplicateHandle? */ 01143 RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &new_this->key); 01144 new_this->next_index = This->next_index; 01145 01146 *ppenum = (LPENUMGUID)new_this; 01147 return S_OK; 01148 } 01149 01150 static const IEnumGUIDVtbl COMCAT_CLSID_IEnumGUID_Vtbl = 01151 { 01152 COMCAT_CLSID_IEnumGUID_QueryInterface, 01153 COMCAT_CLSID_IEnumGUID_AddRef, 01154 COMCAT_CLSID_IEnumGUID_Release, 01155 COMCAT_CLSID_IEnumGUID_Next, 01156 COMCAT_CLSID_IEnumGUID_Skip, 01157 COMCAT_CLSID_IEnumGUID_Reset, 01158 COMCAT_CLSID_IEnumGUID_Clone 01159 }; 01160 01161 static LPENUMGUID COMCAT_CLSID_IEnumGUID_Construct(struct class_categories *categories) 01162 { 01163 CLSID_IEnumGUIDImpl *This; 01164 01165 This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLSID_IEnumGUIDImpl)); 01166 if (This) { 01167 static const WCHAR keyname[] = { 'C', 'L', 'S', 'I', 'D', 0 }; 01168 01169 This->lpVtbl = &COMCAT_CLSID_IEnumGUID_Vtbl; 01170 This->categories = categories; 01171 RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &This->key); 01172 } 01173 return (LPENUMGUID)This; 01174 } 01175 01176 /********************************************************************** 01177 * CategoriesOfClass IEnumCATID (IEnumGUID) implementation 01178 * 01179 * This implementation is not thread-safe. The manager itself is, but 01180 * I can't imagine a valid use of an enumerator in several threads. 01181 */ 01182 typedef struct 01183 { 01184 const IEnumGUIDVtbl *lpVtbl; 01185 LONG ref; 01186 WCHAR keyname[68]; 01187 HKEY key; 01188 DWORD next_index; 01189 } CATID_IEnumGUIDImpl; 01190 01191 static ULONG WINAPI COMCAT_CATID_IEnumGUID_AddRef(LPENUMGUID iface) 01192 { 01193 CATID_IEnumGUIDImpl *This = (CATID_IEnumGUIDImpl *)iface; 01194 TRACE("\n"); 01195 01196 return InterlockedIncrement(&This->ref); 01197 } 01198 01199 static HRESULT WINAPI COMCAT_CATID_IEnumGUID_QueryInterface( 01200 LPENUMGUID iface, 01201 REFIID riid, 01202 LPVOID *ppvObj) 01203 { 01204 TRACE("%s\n",debugstr_guid(riid)); 01205 01206 if (ppvObj == NULL) return E_POINTER; 01207 01208 if (IsEqualGUID(riid, &IID_IUnknown) || 01209 IsEqualGUID(riid, &IID_IEnumGUID)) 01210 { 01211 *ppvObj = iface; 01212 COMCAT_CATID_IEnumGUID_AddRef(iface); 01213 return S_OK; 01214 } 01215 01216 return E_NOINTERFACE; 01217 } 01218 01219 static ULONG WINAPI COMCAT_CATID_IEnumGUID_Release(LPENUMGUID iface) 01220 { 01221 CATID_IEnumGUIDImpl *This = (CATID_IEnumGUIDImpl *)iface; 01222 ULONG ref; 01223 01224 TRACE("\n"); 01225 01226 ref = InterlockedDecrement(&This->ref); 01227 if (ref == 0) { 01228 if (This->key) RegCloseKey(This->key); 01229 HeapFree(GetProcessHeap(), 0, This); 01230 return 0; 01231 } 01232 return ref; 01233 } 01234 01235 static HRESULT WINAPI COMCAT_CATID_IEnumGUID_Next( 01236 LPENUMGUID iface, 01237 ULONG celt, 01238 GUID *rgelt, 01239 ULONG *pceltFetched) 01240 { 01241 CATID_IEnumGUIDImpl *This = (CATID_IEnumGUIDImpl *)iface; 01242 ULONG fetched = 0; 01243 01244 TRACE("\n"); 01245 01246 if (rgelt == NULL) return E_POINTER; 01247 01248 if (This->key) while (fetched < celt) { 01249 LSTATUS res; 01250 HRESULT hr; 01251 WCHAR catid[39]; 01252 DWORD cName = 39; 01253 01254 res = RegEnumKeyExW(This->key, This->next_index, catid, &cName, 01255 NULL, NULL, NULL, NULL); 01256 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break; 01257 ++(This->next_index); 01258 01259 hr = CLSIDFromString(catid, rgelt); 01260 if (FAILED(hr)) continue; 01261 01262 ++fetched; 01263 ++rgelt; 01264 } 01265 01266 if (pceltFetched) *pceltFetched = fetched; 01267 return fetched == celt ? S_OK : S_FALSE; 01268 } 01269 01270 static HRESULT WINAPI COMCAT_CATID_IEnumGUID_Skip( 01271 LPENUMGUID iface, 01272 ULONG celt) 01273 { 01274 CATID_IEnumGUIDImpl *This = (CATID_IEnumGUIDImpl *)iface; 01275 01276 TRACE("\n"); 01277 01278 This->next_index += celt; 01279 FIXME("Never returns S_FALSE\n"); 01280 return S_OK; 01281 } 01282 01283 static HRESULT WINAPI COMCAT_CATID_IEnumGUID_Reset(LPENUMGUID iface) 01284 { 01285 CATID_IEnumGUIDImpl *This = (CATID_IEnumGUIDImpl *)iface; 01286 01287 TRACE("\n"); 01288 01289 This->next_index = 0; 01290 return S_OK; 01291 } 01292 01293 static HRESULT WINAPI COMCAT_CATID_IEnumGUID_Clone( 01294 LPENUMGUID iface, 01295 IEnumGUID **ppenum) 01296 { 01297 CATID_IEnumGUIDImpl *This = (CATID_IEnumGUIDImpl *)iface; 01298 CATID_IEnumGUIDImpl *new_this; 01299 01300 TRACE("\n"); 01301 01302 if (ppenum == NULL) return E_POINTER; 01303 01304 new_this = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CATID_IEnumGUIDImpl)); 01305 if (new_this == NULL) return E_OUTOFMEMORY; 01306 01307 new_this->lpVtbl = This->lpVtbl; 01308 new_this->ref = 1; 01309 lstrcpyW(new_this->keyname, This->keyname); 01310 /* FIXME: could we more efficiently use DuplicateHandle? */ 01311 RegOpenKeyExW(HKEY_CLASSES_ROOT, new_this->keyname, 0, KEY_READ, &new_this->key); 01312 new_this->next_index = This->next_index; 01313 01314 *ppenum = (LPENUMGUID)new_this; 01315 return S_OK; 01316 } 01317 01318 static const IEnumGUIDVtbl COMCAT_CATID_IEnumGUID_Vtbl = 01319 { 01320 COMCAT_CATID_IEnumGUID_QueryInterface, 01321 COMCAT_CATID_IEnumGUID_AddRef, 01322 COMCAT_CATID_IEnumGUID_Release, 01323 COMCAT_CATID_IEnumGUID_Next, 01324 COMCAT_CATID_IEnumGUID_Skip, 01325 COMCAT_CATID_IEnumGUID_Reset, 01326 COMCAT_CATID_IEnumGUID_Clone 01327 }; 01328 01329 static LPENUMGUID COMCAT_CATID_IEnumGUID_Construct( 01330 REFCLSID rclsid, LPCWSTR postfix) 01331 { 01332 CATID_IEnumGUIDImpl *This; 01333 01334 This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CATID_IEnumGUIDImpl)); 01335 if (This) { 01336 WCHAR prefix[] = { 'C', 'L', 'S', 'I', 'D', '\\' }; 01337 01338 This->lpVtbl = &COMCAT_CATID_IEnumGUID_Vtbl; 01339 memcpy(This->keyname, prefix, sizeof(prefix)); 01340 StringFromGUID2(rclsid, This->keyname + 6, 39); 01341 lstrcpyW(This->keyname + 44, postfix); 01342 RegOpenKeyExW(HKEY_CLASSES_ROOT, This->keyname, 0, KEY_READ, &This->key); 01343 } 01344 return (LPENUMGUID)This; 01345 } Generated on Fri May 25 2012 04:23:42 for ReactOS by
1.7.6.1
|