Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenasmenum.c
Go to the documentation of this file.
00001 /* 00002 * IAssemblyEnum implementation 00003 * 00004 * Copyright 2008 James Hawkins 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 <stdarg.h> 00022 00023 #define COBJMACROS 00024 00025 #include "windef.h" 00026 #include "winbase.h" 00027 #include "winuser.h" 00028 #include "ole2.h" 00029 #include "guiddef.h" 00030 #include "fusion.h" 00031 #include "corerror.h" 00032 #include "fusionpriv.h" 00033 00034 #include "wine/debug.h" 00035 #include "wine/unicode.h" 00036 #include "wine/list.h" 00037 00038 WINE_DEFAULT_DEBUG_CHANNEL(fusion); 00039 00040 typedef struct _tagASMNAME 00041 { 00042 struct list entry; 00043 IAssemblyName *name; 00044 } ASMNAME; 00045 00046 typedef struct 00047 { 00048 IAssemblyEnum IAssemblyEnum_iface; 00049 00050 struct list assemblies; 00051 struct list *iter; 00052 LONG ref; 00053 } IAssemblyEnumImpl; 00054 00055 static inline IAssemblyEnumImpl *impl_from_IAssemblyEnum(IAssemblyEnum *iface) 00056 { 00057 return CONTAINING_RECORD(iface, IAssemblyEnumImpl, IAssemblyEnum_iface); 00058 } 00059 00060 static HRESULT WINAPI IAssemblyEnumImpl_QueryInterface(IAssemblyEnum *iface, 00061 REFIID riid, LPVOID *ppobj) 00062 { 00063 IAssemblyEnumImpl *This = impl_from_IAssemblyEnum(iface); 00064 00065 TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj); 00066 00067 *ppobj = NULL; 00068 00069 if (IsEqualIID(riid, &IID_IUnknown) || 00070 IsEqualIID(riid, &IID_IAssemblyEnum)) 00071 { 00072 IUnknown_AddRef(iface); 00073 *ppobj = This; 00074 return S_OK; 00075 } 00076 00077 WARN("(%p, %s, %p): not found\n", This, debugstr_guid(riid), ppobj); 00078 return E_NOINTERFACE; 00079 } 00080 00081 static ULONG WINAPI IAssemblyEnumImpl_AddRef(IAssemblyEnum *iface) 00082 { 00083 IAssemblyEnumImpl *This = impl_from_IAssemblyEnum(iface); 00084 ULONG refCount = InterlockedIncrement(&This->ref); 00085 00086 TRACE("(%p)->(ref before = %u)\n", This, refCount - 1); 00087 00088 return refCount; 00089 } 00090 00091 static ULONG WINAPI IAssemblyEnumImpl_Release(IAssemblyEnum *iface) 00092 { 00093 IAssemblyEnumImpl *This = impl_from_IAssemblyEnum(iface); 00094 ULONG refCount = InterlockedDecrement(&This->ref); 00095 struct list *item, *cursor; 00096 00097 TRACE("(%p)->(ref before = %u)\n", This, refCount + 1); 00098 00099 if (!refCount) 00100 { 00101 LIST_FOR_EACH_SAFE(item, cursor, &This->assemblies) 00102 { 00103 ASMNAME *asmname = LIST_ENTRY(item, ASMNAME, entry); 00104 00105 list_remove(&asmname->entry); 00106 IAssemblyName_Release(asmname->name); 00107 HeapFree(GetProcessHeap(), 0, asmname); 00108 } 00109 00110 HeapFree(GetProcessHeap(), 0, This); 00111 } 00112 00113 return refCount; 00114 } 00115 00116 static HRESULT WINAPI IAssemblyEnumImpl_GetNextAssembly(IAssemblyEnum *iface, 00117 LPVOID pvReserved, 00118 IAssemblyName **ppName, 00119 DWORD dwFlags) 00120 { 00121 IAssemblyEnumImpl *asmenum = impl_from_IAssemblyEnum(iface); 00122 ASMNAME *asmname; 00123 00124 TRACE("(%p, %p, %p, %d)\n", iface, pvReserved, ppName, dwFlags); 00125 00126 if (!ppName) 00127 return E_INVALIDARG; 00128 00129 asmname = LIST_ENTRY(asmenum->iter, ASMNAME, entry); 00130 if (!asmname) 00131 return S_FALSE; 00132 00133 *ppName = asmname->name; 00134 IAssemblyName_AddRef(*ppName); 00135 00136 asmenum->iter = list_next(&asmenum->assemblies, asmenum->iter); 00137 00138 return S_OK; 00139 } 00140 00141 static HRESULT WINAPI IAssemblyEnumImpl_Reset(IAssemblyEnum *iface) 00142 { 00143 IAssemblyEnumImpl *asmenum = impl_from_IAssemblyEnum(iface); 00144 00145 TRACE("(%p)\n", iface); 00146 00147 asmenum->iter = list_head(&asmenum->assemblies); 00148 return S_OK; 00149 } 00150 00151 static HRESULT WINAPI IAssemblyEnumImpl_Clone(IAssemblyEnum *iface, 00152 IAssemblyEnum **ppEnum) 00153 { 00154 FIXME("(%p, %p) stub!\n", iface, ppEnum); 00155 return E_NOTIMPL; 00156 } 00157 00158 static const IAssemblyEnumVtbl AssemblyEnumVtbl = { 00159 IAssemblyEnumImpl_QueryInterface, 00160 IAssemblyEnumImpl_AddRef, 00161 IAssemblyEnumImpl_Release, 00162 IAssemblyEnumImpl_GetNextAssembly, 00163 IAssemblyEnumImpl_Reset, 00164 IAssemblyEnumImpl_Clone 00165 }; 00166 00167 static void parse_name(IAssemblyName *name, int depth, LPWSTR path, LPWSTR buf) 00168 { 00169 WCHAR disp[MAX_PATH]; 00170 LPCWSTR verptr, pubkeyptr; 00171 HRESULT hr; 00172 DWORD size, major_size, minor_size, build_size, revision_size; 00173 WORD major, minor, build, revision; 00174 00175 static const WCHAR star[] = {'*',0}; 00176 static const WCHAR ss_fmt[] = {'%','s','\\','%','s',0}; 00177 static const WCHAR verpubkey[] = {'%','s','\\','%','s','_','_','%','s',0}; 00178 static const WCHAR ver_fmt[] = {'%','u','.','%','u','.','%','u','.','%','u',0}; 00179 00180 WCHAR version[24]; /* strlen("65535") * 4 + 3 + 1 */ 00181 WCHAR token_str[TOKEN_LENGTH + 1]; 00182 BYTE token[BYTES_PER_TOKEN]; 00183 00184 if (depth == 0) 00185 { 00186 size = MAX_PATH; 00187 *disp = '\0'; 00188 hr = IAssemblyName_GetName(name, &size, disp); 00189 if (SUCCEEDED(hr)) 00190 sprintfW(buf, ss_fmt, path, disp); 00191 else 00192 sprintfW(buf, ss_fmt, path, star); 00193 } 00194 else if (depth == 1) 00195 { 00196 major_size = sizeof(major); 00197 IAssemblyName_GetProperty(name, ASM_NAME_MAJOR_VERSION, &major, &major_size); 00198 00199 minor_size = sizeof(minor); 00200 IAssemblyName_GetProperty(name, ASM_NAME_MINOR_VERSION, &minor, &minor_size); 00201 00202 build_size = sizeof(build); 00203 IAssemblyName_GetProperty(name, ASM_NAME_BUILD_NUMBER, &build, &build_size); 00204 00205 revision_size = sizeof(revision); 00206 IAssemblyName_GetProperty(name, ASM_NAME_REVISION_NUMBER, &revision, &revision_size); 00207 00208 if (!major_size || !minor_size || !build_size || !revision_size) verptr = star; 00209 else 00210 { 00211 sprintfW(version, ver_fmt, major, minor, build, revision); 00212 verptr = version; 00213 } 00214 00215 size = sizeof(token); 00216 IAssemblyName_GetProperty(name, ASM_NAME_PUBLIC_KEY_TOKEN, token, &size); 00217 00218 if (!size) pubkeyptr = star; 00219 else 00220 { 00221 token_to_str(token, token_str); 00222 pubkeyptr = token_str; 00223 } 00224 00225 sprintfW(buf, verpubkey, path, verptr, pubkeyptr); 00226 } 00227 } 00228 00229 static int compare_assembly_names(ASMNAME *asmname1, ASMNAME *asmname2) 00230 { 00231 int ret; 00232 WORD version1, version2; 00233 WCHAR name1[MAX_PATH], name2[MAX_PATH]; 00234 WCHAR token_str1[TOKEN_LENGTH + 1], token_str2[TOKEN_LENGTH + 1]; 00235 BYTE token1[BYTES_PER_TOKEN], token2[BYTES_PER_TOKEN]; 00236 DWORD size, i; 00237 00238 size = sizeof(name1); 00239 IAssemblyName_GetProperty(asmname1->name, ASM_NAME_NAME, name1, &size); 00240 size = sizeof(name2); 00241 IAssemblyName_GetProperty(asmname2->name, ASM_NAME_NAME, name2, &size); 00242 00243 if ((ret = strcmpiW(name1, name2))) return ret; 00244 00245 for (i = ASM_NAME_MAJOR_VERSION; i < ASM_NAME_CULTURE; i++) 00246 { 00247 size = sizeof(version1); 00248 IAssemblyName_GetProperty(asmname1->name, i, &version1, &size); 00249 size = sizeof(version2); 00250 IAssemblyName_GetProperty(asmname2->name, i, &version2, &size); 00251 00252 if (version1 < version2) return -1; 00253 if (version1 > version2) return 1; 00254 } 00255 00256 /* FIXME: compare cultures */ 00257 00258 size = sizeof(token1); 00259 IAssemblyName_GetProperty(asmname1->name, ASM_NAME_PUBLIC_KEY_TOKEN, token1, &size); 00260 size = sizeof(token2); 00261 IAssemblyName_GetProperty(asmname2->name, ASM_NAME_PUBLIC_KEY_TOKEN, token2, &size); 00262 00263 token_to_str(token1, token_str1); 00264 token_to_str(token2, token_str2); 00265 00266 if ((ret = strcmpiW(token_str1, token_str2))) return ret; 00267 00268 return 0; 00269 } 00270 00271 /* insert assembly in list preserving sort order */ 00272 static void insert_assembly(struct list *assemblies, ASMNAME *to_insert) 00273 { 00274 struct list *item; 00275 00276 LIST_FOR_EACH(item, assemblies) 00277 { 00278 ASMNAME *name = LIST_ENTRY(item, ASMNAME, entry); 00279 00280 if (compare_assembly_names(name, to_insert) > 0) 00281 { 00282 list_add_before(&name->entry, &to_insert->entry); 00283 return; 00284 } 00285 } 00286 list_add_tail(assemblies, &to_insert->entry); 00287 } 00288 00289 static HRESULT enum_gac_assemblies(struct list *assemblies, IAssemblyName *name, 00290 int depth, LPWSTR path) 00291 { 00292 WIN32_FIND_DATAW ffd; 00293 WCHAR buf[MAX_PATH]; 00294 WCHAR disp[MAX_PATH]; 00295 WCHAR asmpath[MAX_PATH]; 00296 ASMNAME *asmname; 00297 HANDLE hfind; 00298 LPWSTR ptr; 00299 HRESULT hr = S_OK; 00300 00301 static WCHAR parent[MAX_PATH]; 00302 00303 static const WCHAR dot[] = {'.',0}; 00304 static const WCHAR dotdot[] = {'.','.',0}; 00305 static const WCHAR search_fmt[] = {'%','s','\\','*',0}; 00306 static const WCHAR dblunder[] = {'_','_',0}; 00307 static const WCHAR path_fmt[] = {'%','s','\\','%','s','\\','%','s','.','d','l','l',0}; 00308 static const WCHAR fmt[] = {'%','s',',',' ','V','e','r','s','i','o','n','=','%','s',',',' ', 00309 'C','u','l','t','u','r','e','=','n','e','u','t','r','a','l',',',' ', 00310 'P','u','b','l','i','c','K','e','y','T','o','k','e','n','=','%','s',0}; 00311 static const WCHAR ss_fmt[] = {'%','s','\\','%','s',0}; 00312 00313 if (name) 00314 parse_name(name, depth, path, buf); 00315 else 00316 sprintfW(buf, search_fmt, path); 00317 00318 hfind = FindFirstFileW(buf, &ffd); 00319 if (hfind == INVALID_HANDLE_VALUE) 00320 return S_OK; 00321 00322 do 00323 { 00324 if (!lstrcmpW(ffd.cFileName, dot) || !lstrcmpW(ffd.cFileName, dotdot)) 00325 continue; 00326 00327 if (depth == 0) 00328 { 00329 if (name) 00330 ptr = strrchrW(buf, '\\') + 1; 00331 else 00332 ptr = ffd.cFileName; 00333 00334 lstrcpyW(parent, ptr); 00335 } 00336 else if (depth == 1) 00337 { 00338 sprintfW(asmpath, path_fmt, path, ffd.cFileName, parent); 00339 00340 ptr = strstrW(ffd.cFileName, dblunder); 00341 *ptr = '\0'; 00342 ptr += 2; 00343 00344 sprintfW(disp, fmt, parent, ffd.cFileName, ptr); 00345 00346 asmname = HeapAlloc(GetProcessHeap(), 0, sizeof(ASMNAME)); 00347 if (!asmname) 00348 { 00349 hr = E_OUTOFMEMORY; 00350 break; 00351 } 00352 00353 hr = CreateAssemblyNameObject(&asmname->name, disp, 00354 CANOF_PARSE_DISPLAY_NAME, NULL); 00355 if (FAILED(hr)) 00356 { 00357 HeapFree(GetProcessHeap(), 0, asmname); 00358 break; 00359 } 00360 00361 hr = IAssemblyName_SetPath(asmname->name, asmpath); 00362 if (FAILED(hr)) 00363 { 00364 IAssemblyName_Release(asmname->name); 00365 HeapFree(GetProcessHeap(), 0, asmname); 00366 break; 00367 } 00368 00369 insert_assembly(assemblies, asmname); 00370 continue; 00371 } 00372 00373 sprintfW(buf, ss_fmt, path, ffd.cFileName); 00374 hr = enum_gac_assemblies(assemblies, name, depth + 1, buf); 00375 if (FAILED(hr)) 00376 break; 00377 } while (FindNextFileW(hfind, &ffd) != 0); 00378 00379 FindClose(hfind); 00380 return hr; 00381 } 00382 00383 static HRESULT enumerate_gac(IAssemblyEnumImpl *asmenum, IAssemblyName *pName) 00384 { 00385 WCHAR path[MAX_PATH]; 00386 WCHAR buf[MAX_PATH]; 00387 HRESULT hr; 00388 DWORD size; 00389 00390 static WCHAR under32[] = {'_','3','2',0}; 00391 static WCHAR msil[] = {'_','M','S','I','L',0}; 00392 00393 size = MAX_PATH; 00394 hr = GetCachePath(ASM_CACHE_GAC, buf, &size); 00395 if (FAILED(hr)) 00396 return hr; 00397 00398 lstrcpyW(path, buf); 00399 lstrcatW(path, under32); 00400 hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, path); 00401 if (FAILED(hr)) 00402 return hr; 00403 00404 lstrcpyW(path, buf); 00405 lstrcatW(path, msil); 00406 hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, path); 00407 if (FAILED(hr)) 00408 return hr; 00409 00410 hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, buf); 00411 if (FAILED(hr)) 00412 return hr; 00413 00414 return S_OK; 00415 } 00416 00417 /****************************************************************** 00418 * CreateAssemblyEnum (FUSION.@) 00419 */ 00420 HRESULT WINAPI CreateAssemblyEnum(IAssemblyEnum **pEnum, IUnknown *pUnkReserved, 00421 IAssemblyName *pName, DWORD dwFlags, LPVOID pvReserved) 00422 { 00423 IAssemblyEnumImpl *asmenum; 00424 HRESULT hr; 00425 00426 TRACE("(%p, %p, %p, %08x, %p)\n", pEnum, pUnkReserved, 00427 pName, dwFlags, pvReserved); 00428 00429 if (!pEnum) 00430 return E_INVALIDARG; 00431 00432 if (dwFlags == 0 || dwFlags == ASM_CACHE_ROOT) 00433 return E_INVALIDARG; 00434 00435 asmenum = HeapAlloc(GetProcessHeap(), 0, sizeof(IAssemblyEnumImpl)); 00436 if (!asmenum) 00437 return E_OUTOFMEMORY; 00438 00439 asmenum->IAssemblyEnum_iface.lpVtbl = &AssemblyEnumVtbl; 00440 asmenum->ref = 1; 00441 list_init(&asmenum->assemblies); 00442 00443 if (dwFlags & ASM_CACHE_GAC) 00444 { 00445 hr = enumerate_gac(asmenum, pName); 00446 if (FAILED(hr)) 00447 { 00448 HeapFree(GetProcessHeap(), 0, asmenum); 00449 return hr; 00450 } 00451 } 00452 00453 asmenum->iter = list_head(&asmenum->assemblies); 00454 *pEnum = &asmenum->IAssemblyEnum_iface; 00455 00456 return S_OK; 00457 } Generated on Sun May 27 2012 04:23:33 for ReactOS by
1.7.6.1
|