Opc.Ua.WindowsCertificateStore.EnumerateStores C# (CSharp) Method

EnumerateStores() public static method

Enumerates the available windows certificate store.
public static EnumerateStores ( WindowsStoreType storeType, string hostName, string serviceNameOrUserSid ) : IList
storeType WindowsStoreType
hostName string
serviceNameOrUserSid string
return IList
        public static IList<WindowsCertificateStore> EnumerateStores(
	        WindowsStoreType storeType, 
	        string           hostName, 
	        string           serviceNameOrUserSid)
        {
	        List<WindowsCertificateStore> stores = new List<WindowsCertificateStore>();

	        EnumResults results = new EnumResults();
            GCHandle hResults = GCHandle.Alloc(results, GCHandleType.Pinned);
	        IntPtr wszStoreBaseName = IntPtr.Zero;

	        try
	        {
		        uint dwFlags = 0;

		        // contruct base name for the store to enumerate.
		        string storeBaseName = null;

		        if (!String.IsNullOrEmpty(hostName) && hostName != ".")
		        {
			        storeBaseName = Utils.Format("{0}", hostName);
		        }

		        if (!String.IsNullOrEmpty(serviceNameOrUserSid))
		        {
			        if (!String.IsNullOrEmpty(storeBaseName))
			        {
				        storeBaseName = Utils.Format("{0}\\{1}", storeBaseName, serviceNameOrUserSid);
			        }
			        else
			        {
				        storeBaseName = serviceNameOrUserSid;
			        }
		        }

		        // allocate the store base name.
		        wszStoreBaseName = DuplicateString(storeBaseName);

		        // set the flags based on store type.
		        dwFlags |= GetFlags(storeType);

		        // get list of names.
		        results.Capacity = 10;
                results.Count = 0;
		        results.Names = Marshal.AllocHGlobal(results.Capacity*IntPtr.Size);

                IntPtr pResults = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(EnumResults)));
                Marshal.StructureToPtr(results, pResults, false);

                int bResult = NativeMethods.CertEnumSystemStore(
			        dwFlags,
			        wszStoreBaseName, 
			        pResults,
			        EnumStoreCallback);

                int dwError = Marshal.GetLastWin32Error();

                results = (EnumResults)Marshal.PtrToStructure(pResults, typeof(EnumResults));
                Marshal.DestroyStructure(pResults, typeof(EnumResults));
                Marshal.FreeHGlobal(pResults);
                
		        if (bResult == 0)
		        {
		            throw ServiceResultException.Create(
                        StatusCodes.BadUnexpectedError,
                        "Can't enumerate the contents of the certificate store.\r\nType={0}, HostName={1}, ServiceNameOrUserSid={2}, Error={3:X8}", 
				        storeType,
				        hostName,
				        serviceNameOrUserSid,
				        dwError);
		        }
        		
		        // copy names.
                IntPtr[] names = new IntPtr[results.Count];
                Marshal.Copy(results.Names, names, 0, results.Count);  

		        for (uint ii = 0; ii < results.Count; ii++)
		        {
			        IntPtr wszSymbolicName = names[ii];

                    IntPtr hStore = NativeMethods.CertOpenStore(
			           new IntPtr(CERT_STORE_PROV_SYSTEM),
			           0,
                       IntPtr.Zero,
                       GetFlags(storeType) | CERT_STORE_READONLY_FLAG | CERT_STORE_OPEN_EXISTING_FLAG, 
			           wszSymbolicName);

			        if (hStore == IntPtr.Zero)
			        {
				        continue;
			        }

                    int result = NativeMethods.CertCloseStore(hStore, 0);

                    if (result == 0)
                    {
                        Utils.Trace("Could not close certificate store. Error={0:X8}", Marshal.GetLastWin32Error());
                    }

			        WindowsCertificateStore store = new WindowsCertificateStore();

			        store.m_symbolicName = Marshal.PtrToStringUni(wszSymbolicName);
			        store.m_storeType = storeType;
			        store.m_displayName = store.m_symbolicName;

			        // extract the store name from the end of the symbolic name.
			        int index = store.m_symbolicName.LastIndexOf('\\');

			        if (index >= 0)
			        {
				        store.m_displayName = store.m_symbolicName.Substring(index+1);
				        store.m_serviceNameOrUserSid = store.m_symbolicName.Substring(0, index);
			        }

			        // check if the service name or user sid has a host name prefix.
			        if (!String.IsNullOrEmpty(store.m_serviceNameOrUserSid))
			        {
				        index = store.m_serviceNameOrUserSid.LastIndexOf('\\');

				        if (index >= 0)
				        {
					        store.m_hostName = store.m_serviceNameOrUserSid.Substring(0, index);
					        store.m_serviceNameOrUserSid = store.m_serviceNameOrUserSid.Substring(index+1);
				        }
			        }

			        // remove the leading '\\' from the host name.
			        if (!String.IsNullOrEmpty(store.m_hostName))
			        {
				        if (store.m_hostName.StartsWith("\\\\", StringComparison.Ordinal))
				        {
					        store.m_hostName = store.m_hostName.Substring(2);
				        }
			        }

			        store.m_displayName = GetStoreDisplayName(store.m_storeType, store.m_serviceNameOrUserSid, store.m_symbolicName);

			        // add the store to the list.
			        stores.Add(store);
		        }
	        }
	        finally
	        {
		        if (results.Names != IntPtr.Zero)
		        {
                    IntPtr[] names = new IntPtr[results.Count];
                    Marshal.Copy(results.Names, names, 0, results.Count);  

			        for (uint ii = 0; ii < names.Length; ii++)
			        {
				        Marshal.FreeHGlobal(names[ii]);
			        }

			        Marshal.FreeHGlobal(results.Names);
		        }

                if (hResults.IsAllocated)
                {
                    hResults.Free();
                }

		        if (wszStoreBaseName != IntPtr.Zero)
		        {
			        Marshal.FreeHGlobal(wszStoreBaseName);
		        }
	        }

	        return stores;
        }