PC Review


Reply
Thread Tools Rating: Thread Rating: 1 votes, 1.00 average.

checking for / accessing custom attribute fails with 0x8000500c

 
 
Jabba
Guest
Posts: n/a
 
      29th Aug 2005
Hi guys,
I have created a custom attribute called tst-PwdDomainPolicy (unicode,
multivalued) on our win2000 AD server using a SchemaAdmin account and the
Schema editor snap-in. A dummy X500 identifier was used. It was replicated
on the other AD server correctly. I then asigned the attribute to the
OrganizationalUnit (OU) class.

I can see and edit this attribute for any given OU from a client machine
being logged in with a domain administrator account, using ADSIEdit. The
reason I insist on the security context in which the tools are ran will
become obvious later on.

I am now trying to get the values of the said custom attribute from a given
user name and OU that the user is part of in .NET app running under the
domain admin account. Rememeber, the attribute is part of the OU class.

I cannot get it.


Here 's the relevant code:

Code:
try {
DirectoryEntry de = null;
string userPath = string.Format("LDAP://cn={0},ou={1},{2}",
name.ToUpper(), ou.ToUpper(), permsLDAPSuffix);
de = new DirectoryEntry(userPath);
RefreshCache(de);
StringCollection scPwdPolicy =null;
DirectoryEntry deParent = de.Parent;//this is the OU I am after
RefreshCache(deParent);
scPwdPolicy=getDomainPwdPolicy(deParent);
return new User(de, this,scPwdPolicy);//whatever...
} catch (System.Runtime.InteropServices.COMException)
the getDomainPwdPolicy looks like this:

Code:
private StringCollection getDomainPwdPolicy(DirectoryEntry de)
{
try
{

//testcode
intConfig.Log.Log(Severity.Trace, "The following properties are
supported by the {0} organizational unit ", de.Name);
foreach(string key in de.Properties.PropertyNames)
{
intConfig.Log.Log(Severity.Trace, "{0}", key );
}

//end testcode


if(de.Properties.Contains("tst-PwdDomainPolicy"))
{

PropertyValueCollection pvc = de.Properties["tst-PwdDomainPolicy"];
if((pvc!=null)&&(pvc.Count!=0))
{
StringCollection sc = new
System.Collections.Specialized.StringCollection();
foreach (string p in pvc)
{
sc.Add(p);
}
return sc;
}
}
}
catch (System.Runtime.InteropServices.COMException e)
{
intConfig.Log.Log(Severity.Critical, "Caught COMException while trying
to retrieve the OU password policy : #{0:x}, {1}", e.ErrorCode, e.Message);
}
return null;
the output for this is :

TRACE-08/29/2005 09:35:58.326-[3144
(UserStoreImpl.exe)/UserStoreImpl/d5c]-The following properties are
supported by the ou=PLAYGROUND organizational unit
TRACE-08/29/2005 09:35:58.627-[3144
(UserStoreImpl.exe)/UserStoreImpl/d5c]-dSCorePropagationData
TRACE-08/29/2005 09:35:58.627-[3144
(UserStoreImpl.exe)/UserStoreImpl/d5c]-instanceType
TRACE-08/29/2005 09:35:58.877-[3144
(UserStoreImpl.exe)/UserStoreImpl/d5c]-nTSecurityDescriptor
TRACE-08/29/2005 09:35:58.877-[3144
(UserStoreImpl.exe)/UserStoreImpl/d5c]-distinguishedName
TRACE-08/29/2005 09:35:58.877-[3144
(UserStoreImpl.exe)/UserStoreImpl/d5c]-objectCategory
TRACE-08/29/2005 09:35:58.877-[3144
(UserStoreImpl.exe)/UserStoreImpl/d5c]-objectClass
TRACE-08/29/2005 09:35:58.877-[3144
(UserStoreImpl.exe)/UserStoreImpl/d5c]-objectGUID
TRACE-08/29/2005 09:35:58.877-[3144
(UserStoreImpl.exe)/UserStoreImpl/d5c]-ou
TRACE-08/29/2005 09:35:58.877-[3144
(UserStoreImpl.exe)/UserStoreImpl/d5c]-name
TRACE-08/29/2005 09:35:58.887-[3144
(UserStoreImpl.exe)/UserStoreImpl/d5c]-uSNChanged
TRACE-08/29/2005 09:35:58.887-[3144
(UserStoreImpl.exe)/UserStoreImpl/d5c]-uSNCreated
TRACE-08/29/2005 09:35:58.887-[3144
(UserStoreImpl.exe)/UserStoreImpl/d5c]-whenChanged
TRACE-08/29/2005 09:35:58.887-[3144
(UserStoreImpl.exe)/UserStoreImpl/d5c]-whenCreated
TRACE-08/29/2005 09:35:58.887-[3144
(UserStoreImpl.exe)/UserStoreImpl/d5c]-tst-PwdDomainPolicy

CRITICAL-08/29/2005 09:35:58.937-[3144
(UserStoreImpl.exe)/UserStoreImpl/d5c]-Caught COMException while trying to
retrieve the OU password policy : #8000500c, The directory datatype cannot
be converted to/from a native DS datatype

In case you wonder, the line that throws the exception is :

Code:
if(de.Properties.Contains("tst-PwdDomainPolicy"))
{
which is at least weird. Especially since the propertly is listed as
available by the enumeration just before the faulty code line.


Now some side notes: I am well aware of the schema cache refresh issue
described here:

http://support.microsoft.com/default...b;en-us;241981

That's why I use the RefreshCache(...) call:

public static void RefreshCache(DirectoryEntry entry)
{
try
{
if(entry != null)
{
if(entry.SchemaEntry != null)
entry.SchemaEntry.RefreshCache(); //force refresh of schema
entry.RefreshCache(); //force reload of cache info
}
}
catch (Exception e)
{
intConfig.Log.Log(Severity.Critical,"Exception in
DirectoryEntry:{0}{1}SchemaEntry:
{2}",entry.Path,entry.SchemaEntry.Path,e.Message);
}
}
This never throws, BTW. Which probably means the the domain admin guy
(who's running this) can access the schema.


Besides, both the server and the client machines have been restarted since
the schema change so the cache is probably in the right stage, as proven by
the TRACE messages above

Based on my research , I beleieve that there might be an issue with the
*attribute ownership* in that the attribute is owned by the schema admin guy
and the domain admin guy cannot access it (although this doesn't explain why
I can edit it with ADSI edit running under the domain admin guy's login). So
I am trying to change the ownership of the attribute . But AD GUI tools
don't list the ownership lists by default. It is hidden. To enable AD to use
List Object permission, one must modify cn=Directory Service,cn=Windows
NT,cn=Services,cn=Configuration,dc=subdomain,dc=domain,dc=com. The
dSHeuristics attribute should have a value "001" to enable this permission.
And here is where I had to stop. No matter how powerful a user I am using
(Administrators included ) the ADSI edit says I don't have enough rights to
change this attribute.

Please advise, either with the original issue, either with the secondary
one.



Thanks,

Jabba


 
Reply With Quote
 
 
 
 
Joe Kaplan \(MVP - ADSI\)
Guest
Posts: n/a
 
      29th Aug 2005
This is most likely a schema cache problem, but RefreshCache does not fix
them.

My guess is that you need to clear the cached schema on the file system in
the app to make sure you are getting a fresh copy of the local schema on the
machine. It is stored in the <windows dir>\SchCache folder. If those files
are dated earlier than your last applied schema mod, then that is likely the
problem.

ADSI is supposed to update those for you, but it might be the case that the
code that is running the ADSI code does not have the permissions to update
the files or registry keys associated with the cached schema.

Joe K.

"Jabba" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Hi guys,
> I have created a custom attribute called tst-PwdDomainPolicy (unicode,
> multivalued) on our win2000 AD server using a SchemaAdmin account and the
> Schema editor snap-in. A dummy X500 identifier was used. It was replicated
> on the other AD server correctly. I then asigned the attribute to the
> OrganizationalUnit (OU) class.
>
> I can see and edit this attribute for any given OU from a client machine
> being logged in with a domain administrator account, using ADSIEdit. The
> reason I insist on the security context in which the tools are ran will
> become obvious later on.
>
> I am now trying to get the values of the said custom attribute from a
> given user name and OU that the user is part of in .NET app running under
> the domain admin account. Rememeber, the attribute is part of the OU
> class.
>
> I cannot get it.
>
>
> Here 's the relevant code:
>
>
Code:
>  try {
>    DirectoryEntry de = null;
>    string userPath = string.Format("LDAP://cn={0},ou={1},{2}",
> name.ToUpper(), ou.ToUpper(), permsLDAPSuffix);
>    de = new DirectoryEntry(userPath);
>    RefreshCache(de);
>    StringCollection scPwdPolicy =null;
>    DirectoryEntry deParent = de.Parent;//this is the OU I am after
>    RefreshCache(deParent);
>    scPwdPolicy=getDomainPwdPolicy(deParent);
>    return new User(de, this,scPwdPolicy);//whatever...
>   } catch (System.Runtime.InteropServices.COMException)
>
>
> the getDomainPwdPolicy looks like this:
>
>
Code:
>  private StringCollection getDomainPwdPolicy(DirectoryEntry de)
>  {
>   try
>   {
>
>    //testcode
>    intConfig.Log.Log(Severity.Trace, "The following properties are
> supported by the {0} organizational unit ", de.Name);
>    foreach(string key in de.Properties.PropertyNames)
>    {
>     intConfig.Log.Log(Severity.Trace, "{0}", key );
>    }
>
>   //end testcode
>
>
>    if(de.Properties.Contains("tst-PwdDomainPolicy"))
>    {
>
>     PropertyValueCollection pvc = de.Properties["tst-PwdDomainPolicy"];
>     if((pvc!=null)&&(pvc.Count!=0))
>     {
>      StringCollection sc = new
> System.Collections.Specialized.StringCollection();
>      foreach (string p in pvc)
>      {
>       sc.Add(p);
>      }
>      return sc;
>     }
>    }
>   }
>   catch (System.Runtime.InteropServices.COMException e)
>   {
>    intConfig.Log.Log(Severity.Critical, "Caught COMException while trying
> to retrieve the OU password policy : #{0:x}, {1}", e.ErrorCode,
> e.Message);
>   }
>   return null;
>
>
>
> the output for this is :
>
> TRACE-08/29/2005 09:35:58.326-[3144
> (UserStoreImpl.exe)/UserStoreImpl/d5c]-The following properties are
> supported by the ou=PLAYGROUND organizational unit
> TRACE-08/29/2005 09:35:58.627-[3144
> (UserStoreImpl.exe)/UserStoreImpl/d5c]-dSCorePropagationData
> TRACE-08/29/2005 09:35:58.627-[3144
> (UserStoreImpl.exe)/UserStoreImpl/d5c]-instanceType
> TRACE-08/29/2005 09:35:58.877-[3144
> (UserStoreImpl.exe)/UserStoreImpl/d5c]-nTSecurityDescriptor
> TRACE-08/29/2005 09:35:58.877-[3144
> (UserStoreImpl.exe)/UserStoreImpl/d5c]-distinguishedName
> TRACE-08/29/2005 09:35:58.877-[3144
> (UserStoreImpl.exe)/UserStoreImpl/d5c]-objectCategory
> TRACE-08/29/2005 09:35:58.877-[3144
> (UserStoreImpl.exe)/UserStoreImpl/d5c]-objectClass
> TRACE-08/29/2005 09:35:58.877-[3144
> (UserStoreImpl.exe)/UserStoreImpl/d5c]-objectGUID
> TRACE-08/29/2005 09:35:58.877-[3144
> (UserStoreImpl.exe)/UserStoreImpl/d5c]-ou
> TRACE-08/29/2005 09:35:58.877-[3144
> (UserStoreImpl.exe)/UserStoreImpl/d5c]-name
> TRACE-08/29/2005 09:35:58.887-[3144
> (UserStoreImpl.exe)/UserStoreImpl/d5c]-uSNChanged
> TRACE-08/29/2005 09:35:58.887-[3144
> (UserStoreImpl.exe)/UserStoreImpl/d5c]-uSNCreated
> TRACE-08/29/2005 09:35:58.887-[3144
> (UserStoreImpl.exe)/UserStoreImpl/d5c]-whenChanged
> TRACE-08/29/2005 09:35:58.887-[3144
> (UserStoreImpl.exe)/UserStoreImpl/d5c]-whenCreated
> TRACE-08/29/2005 09:35:58.887-[3144
> (UserStoreImpl.exe)/UserStoreImpl/d5c]-tst-PwdDomainPolicy
>
> CRITICAL-08/29/2005 09:35:58.937-[3144
> (UserStoreImpl.exe)/UserStoreImpl/d5c]-Caught COMException while trying to
> retrieve the OU password policy : #8000500c, The directory datatype cannot
> be converted to/from a native DS datatype
>
> In case you wonder, the line that throws the exception is :
>
>
Code:
>   if(de.Properties.Contains("tst-PwdDomainPolicy"))
>    {
>
>
> which is at least weird. Especially since the propertly is listed as
> available by the enumeration just before the faulty code line.
>
>
> Now some side notes: I am well aware of the schema cache refresh issue
> described here:
>
> http://support.microsoft.com/default...b;en-us;241981
>
> That's why I use the RefreshCache(...) call:
>
> public static void RefreshCache(DirectoryEntry entry)
> {
> try
> {
> if(entry != null)
> {
> if(entry.SchemaEntry != null)
> entry.SchemaEntry.RefreshCache(); //force refresh of schema
> entry.RefreshCache(); //force reload of cache info
> }
> }
> catch (Exception e)
> {
> intConfig.Log.Log(Severity.Critical,"Exception in
> DirectoryEntry:{0}{1}SchemaEntry:
> {2}",entry.Path,entry.SchemaEntry.Path,e.Message);
> }
> }
> This never throws, BTW. Which probably means the the domain admin guy
> (who's running this) can access the schema.
>
>
> Besides, both the server and the client machines have been restarted
> since the schema change so the cache is probably in the right stage, as
> proven by the TRACE messages above
>
> Based on my research , I beleieve that there might be an issue with the
> *attribute ownership* in that the attribute is owned by the schema admin
> guy and the domain admin guy cannot access it (although this doesn't
> explain why I can edit it with ADSI edit running under the domain admin
> guy's login). So I am trying to change the ownership of the attribute .
> But AD GUI tools don't list the ownership lists by default. It is hidden.
> To enable AD to use List Object permission, one must modify cn=Directory
> Service,cn=Windows
> NT,cn=Services,cn=Configuration,dc=subdomain,dc=domain,dc=com. The
> dSHeuristics attribute should have a value "001" to enable this
> permission. And here is where I had to stop. No matter how powerful a user
> I am using (Administrators included ) the ADSI edit says I don't have
> enough rights to change this attribute.
>
> Please advise, either with the original issue, either with the secondary
> one.
>
>
>
> Thanks,
>
> Jabba
>
>



 
Reply With Quote
 
 
 
 
Jabba
Guest
Posts: n/a
 
      30th Aug 2005
Nice tip, tried it, still got the same behaviour...I am watching the schema
with notepad and it the custom attribute *is* present and it is asigned to
the OU class.
Thanks anyway.

Jabba



Joe Kaplan (MVP - ADSI)" <(E-Mail Removed)> wrote in
message news:%(E-Mail Removed)...
> This is most likely a schema cache problem, but RefreshCache does not fix
> them.
>
> My guess is that you need to clear the cached schema on the file system in
> the app to make sure you are getting a fresh copy of the local schema on
> the machine. It is stored in the <windows dir>\SchCache folder. If those
> files are dated earlier than your last applied schema mod, then that is
> likely the problem.
>
> ADSI is supposed to update those for you, but it might be the case that
> the code that is running the ADSI code does not have the permissions to
> update the files or registry keys associated with the cached schema.
>
> Joe K.
>
> "Jabba" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...

[snip...]


 
Reply With Quote
 
Joe Kaplan \(MVP - ADSI\)
Guest
Posts: n/a
 
      31st Aug 2005
Weird. I'm not sure if I know what the error is then. There isn't any
tracing available for the schema mapping stuff that ADSI does, so it can be
hard to decipher.

Have you tried playing with it using ldp.exe? It bypasses ADSI, so there is
no schema mapping. It is my favorite DS programming tool.

You might also try the trick of casting the NativeObject to an
IADsPropertyList and use the IADsPropertyValue stuff to get the value (check
the docs). However, that should not be needed.

Joe K.

"Jabba" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Nice tip, tried it, still got the same behaviour...I am watching the
> schema with notepad and it the custom attribute *is* present and it is
> asigned to the OU class.
> Thanks anyway.
>
> Jabba
>
>
>
> Joe Kaplan (MVP - ADSI)" <(E-Mail Removed)> wrote
> in message news:%(E-Mail Removed)...
>> This is most likely a schema cache problem, but RefreshCache does not fix
>> them.
>>
>> My guess is that you need to clear the cached schema on the file system
>> in the app to make sure you are getting a fresh copy of the local schema
>> on the machine. It is stored in the <windows dir>\SchCache folder. If
>> those files are dated earlier than your last applied schema mod, then
>> that is likely the problem.
>>
>> ADSI is supposed to update those for you, but it might be the case that
>> the code that is running the ADSI code does not have the permissions to
>> update the files or registry keys associated with the cached schema.
>>
>> Joe K.
>>
>> "Jabba" <(E-Mail Removed)> wrote in message
>> news:(E-Mail Removed)...

> [snip...]
>



 
Reply With Quote
 
Jabba
Guest
Posts: n/a
 
      1st Sep 2005
For the benefit of the others who might follow:
- it was not this :
http://support.microsoft.com/default...b;en-us;241981
- neither this :
http://support.microsoft.com/default...B;EN-US;888243

A MS guy figured out for me. Thanks, you know who you are :-))

If one wants to access a custom attribute from a machine that is not part of
the domain where the custom attribute resides (the credentials of the logged
in user don't matter) one needs to pass the fully qualified name of the
object is trying to access otherwise the schema cache on the client machine
is not properly refreshed, nevermind all the schema.refresh() calls you make
:

e.g in my case LDAP://companydev.com/OU= permissions, DC= companydev, DC=
com is needed to properly get the DirectoryServices.DirectoryEntry or the
ActiveDs.IADsOU for the object

instead of simply LDAP://OU= permissions, DC= companydev, DC= com



Note that you *don*t* have to pass the full controller name as in

LDAP://dev20.companydev.com/OU= permissions, DC= companydev, DC= com

Jabba

"Joe Kaplan (MVP - ADSI)" <(E-Mail Removed)> wrote
in message news:(E-Mail Removed)...
> Weird. I'm not sure if I know what the error is then. There isn't any
> tracing available for the schema mapping stuff that ADSI does, so it can
> be hard to decipher.
>
> Have you tried playing with it using ldp.exe? It bypasses ADSI, so there
> is no schema mapping. It is my favorite DS programming tool.
>
> You might also try the trick of casting the NativeObject to an
> IADsPropertyList and use the IADsPropertyValue stuff to get the value
> (check the docs). However, that should not be needed.
>
> Joe K.
>
> "Jabba" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
>> Nice tip, tried it, still got the same behaviour...I am watching the
>> schema with notepad and it the custom attribute *is* present and it is
>> asigned to the OU class.
>> Thanks anyway.
>>
>> Jabba
>>
>>
>>
>> Joe Kaplan (MVP - ADSI)" <(E-Mail Removed)> wrote
>> in message news:%(E-Mail Removed)...
>>> This is most likely a schema cache problem, but RefreshCache does not
>>> fix them.
>>>
>>> My guess is that you need to clear the cached schema on the file system
>>> in the app to make sure you are getting a fresh copy of the local schema
>>> on the machine. It is stored in the <windows dir>\SchCache folder. If
>>> those files are dated earlier than your last applied schema mod, then
>>> that is likely the problem.
>>>
>>> ADSI is supposed to update those for you, but it might be the case that
>>> the code that is running the ADSI code does not have the permissions to
>>> update the files or registry keys associated with the cached schema.
>>>
>>> Joe K.
>>>
>>> "Jabba" <(E-Mail Removed)> wrote in message
>>> news:(E-Mail Removed)...

>> [snip...]
>>

>
>



 
Reply With Quote
 
Joe Richards [MVP]
Guest
Posts: n/a
 
      1st Sep 2005
God I hate ADSI. You don't have any of those issues in the LDAP API.



--
Joe Richards Microsoft MVP Windows Server Directory Services
www.joeware.net


Jabba wrote:
> For the benefit of the others who might follow:
> - it was not this :
> http://support.microsoft.com/default...b;en-us;241981
> - neither this :
> http://support.microsoft.com/default...B;EN-US;888243
>
> A MS guy figured out for me. Thanks, you know who you are :-))
>
> If one wants to access a custom attribute from a machine that is not part of
> the domain where the custom attribute resides (the credentials of the logged
> in user don't matter) one needs to pass the fully qualified name of the
> object is trying to access otherwise the schema cache on the client machine
> is not properly refreshed, nevermind all the schema.refresh() calls you make
> :
>
> e.g in my case LDAP://companydev.com/OU= permissions, DC= companydev, DC=
> com is needed to properly get the DirectoryServices.DirectoryEntry or the
> ActiveDs.IADsOU for the object
>
> instead of simply LDAP://OU= permissions, DC= companydev, DC= com
>
>
>
> Note that you *don*t* have to pass the full controller name as in
>
> LDAP://dev20.companydev.com/OU= permissions, DC= companydev, DC= com
>
> Jabba
>
> "Joe Kaplan (MVP - ADSI)" <(E-Mail Removed)> wrote
> in message news:(E-Mail Removed)...
>
>>Weird. I'm not sure if I know what the error is then. There isn't any
>>tracing available for the schema mapping stuff that ADSI does, so it can
>>be hard to decipher.
>>
>>Have you tried playing with it using ldp.exe? It bypasses ADSI, so there
>>is no schema mapping. It is my favorite DS programming tool.
>>
>>You might also try the trick of casting the NativeObject to an
>>IADsPropertyList and use the IADsPropertyValue stuff to get the value
>>(check the docs). However, that should not be needed.
>>
>>Joe K.
>>
>>"Jabba" <(E-Mail Removed)> wrote in message
>>news:(E-Mail Removed)...
>>
>>>Nice tip, tried it, still got the same behaviour...I am watching the
>>>schema with notepad and it the custom attribute *is* present and it is
>>>asigned to the OU class.
>>> Thanks anyway.
>>>
>>>Jabba
>>>
>>>
>>>
>>>Joe Kaplan (MVP - ADSI)" <(E-Mail Removed)> wrote
>>>in message news:%(E-Mail Removed)...
>>>
>>>>This is most likely a schema cache problem, but RefreshCache does not
>>>>fix them.
>>>>
>>>>My guess is that you need to clear the cached schema on the file system
>>>>in the app to make sure you are getting a fresh copy of the local schema
>>>>on the machine. It is stored in the <windows dir>\SchCache folder. If
>>>>those files are dated earlier than your last applied schema mod, then
>>>>that is likely the problem.
>>>>
>>>>ADSI is supposed to update those for you, but it might be the case that
>>>>the code that is running the ADSI code does not have the permissions to
>>>>update the files or registry keys associated with the cached schema.
>>>>
>>>>Joe K.
>>>>
>>>>"Jabba" <(E-Mail Removed)> wrote in message
>>>>news:(E-Mail Removed)...
>>>
>>>[snip...]
>>>

>>
>>

>
>

 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Validation (XHTML 1.0 Transitional): Attribute 'leftmargin' is not a valid attribute of element 'body'. anonymous Microsoft ASP .NET 1 2nd Aug 2006 09:05 AM
SEARCH XML ATTRIBUTE BASED ON THE VALUE OF ANOTHER ATTRIBUTE ATLANTA PATNAIK via DotNetMonster.com Microsoft C# .NET 2 12th Apr 2005 06:10 PM
Attribute ID/Attribute Buffer DF Microsoft VB .NET 1 17th Sep 2004 03:47 PM
Calling an attribute method before calling a method with that attribute George Vodpik Microsoft Dot NET 0 9th Aug 2004 11:37 PM
Custom attribute applying another attribute Andrew Roberts Microsoft Dot NET Framework 1 4th Sep 2003 06:52 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 03:17 AM.