ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

asmenum.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.