Re: Unable to Get Credential Mgr Working on Windows 2000 Platform

From: diana (darroyo_at_texas.net)
Date: 12/01/03


Date: 1 Dec 2003 12:04:54 -0800

Hi David. Thanks so much for responding. I'm trying to write a
Credential Manager using the Network Provider setup.(ref:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/implementing_a_credential_manager.asp)
 According to the link provided it seems that Win2K is supported. Am
I reading this incorrectly?

"David Cross [MS]" <dcross@online.microsoft.com> wrote in message news:<uZ7O6#BtDHA.2060@TK2MSFTNGP10.phx.gbl>...
> The Credential Manager is only available on XP+.
>
> --
>
>
> David B. Cross [MS]
>
> --
> This posting is provided "AS IS" with no warranties, and confers no rights.
>
> http://support.microsoft.com
>
> "diana" <darroyo@texas.net> wrote in message
> news:e51ba5b0.0311251247.1903c896@posting.google.com...
> > Hello, I am having some difficulty getting the Credential Manager to
> > work on Windows 2K. I setup the credential manager to open a msg box
> > when I login but when I actually login, the dll does not seem to run.
> > I have a few questions followed by the registry settings and the code
> > I used to build the DLL for your reference since I am a newbie.
> >
> > My Questions are:
> > 1) How can I tell if the DLL gets loaded?
> > 2) What is the best way to debug this problem?
> > 3) Am I missing something in the code below or something in the
> > registry setup?
> >
> > I would appreciate any suggestion you may have. Thanks.
> >
> > Regards,
> > Diana
> >
> > =====================================================
> > registry settings
> > =====================================================
> >
> > HKEY_LOCAL_MACHINE\System\CurrentControlSet\control\NetworkProvider\Order
> > ProviderOrder = LanmanWorkstations,MYNP
> >
> > HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\MYNP\NetworkProvider
> > Name = My Credential Manager
> > Class = 0x0000002
> > ProviderPath = c:\dev\bin\mynp1.dll
> >
> > =====================================================
> > code
> > =====================================================
> >
> > -----------------------------------------------------
> > mywpnp_api.h
> >
> > #ifndef MYWPNP_API_H
> > #define MYWPNP_API_H
> >
> > #pragma warning( disable : 4251 4275 4786 )
> >
> > #if !defined( MYWPNP_API )
> > #if defined( WIN32 ) && !defined( MYWPNP_LIB )
> > #ifdef MYWPNP_EXPORTS
> > #define MYWPNP_API __declspec( dllexport )
> > #else
> > #define MYWPNP_API __declspec( dllimport )
> > #endif
> > #else
> > #define MYWPNP_API
> > #endif
> > #endif
> >
> > #if defined( WIN32 )
> > #define EXPORT_SYMBOL __declspec( dllexport )
> > #define IMPORT_SYMBOL __declspec( dllimport )
> > #else
> > #define EXPORT_SYMBOL
> > #define IMPORT_SYMBOL
> > #endif
> >
> > #endif // MYWPNP_API_H
> >
> > -----------------------------------------------------
> > mywpnpcaps.c
> >
> > #include < mywpnpcaps.h >
> >
> > DWORD MYWPNP_API NPGetCaps( DWORD ndex )
> > {
> >
> > DWORD result;
> >
> > switch (ndex) {
> >
> > case WNNC_START:
> > result = 1;
> > break;
> >
> > case WNNC_NET_TYPE:
> > result = WNNC_NET_MSNET;
> > break;
> >
> > default:
> > result = 0;
> > break;
> >
> > } /* switch */
> >
> > return(result);
> >
> > } /* NPGetCaps */
> >
> > -----------------------------------------------------
> > mywpnpcaps.h
> >
> > #include < wtypes.h >
> >
> > #include < NPAPI.H >
> >
> > #include < mywpnp_api.h >
> >
> >
> > -----------------------------------------------------
> > mywpnplog_api.c
> >
> > #include < mywpnplog.h>
> >
> > MYWPNP_API DWORD NPLogonNotify(
> > PLUID lpLogonId,
> > LPCWSTR lpAuthentInfoType,
> > LPVOID lpAuthentInfo,
> > LPCWSTR lpPreviousAuthentInfoType,
> > LPVOID lpPreviousAuthentInfo,
> > LPWSTR lpStationName,
> > LPVOID StationHandle,
> > LPWSTR *lpLogonScript
> > )
> > {
> >
> > MessageBox( NULL, "Hey", TEXT( "Cred Manager" ), MB_OK );
> >
> > return( WN_SUCCESS );
> >
> > } /* NPLogon */
> >
> > DWORD MYWPNP_API NPPasswordChangeNotify( LPCWSTR lpAuthentInfoType,
> > LPVOID lpAuthentInfo,
> > LPCWSTR lpPreviousAuthentInfoType,
> > LPVOID lpPreviousAuthentInfo,
> > LPWSTR lpStationName,
> > LPVOID StationHandle,
> > DWORD dwChangeInfo )
> > {
> > return WN_SUCCESS;
> > }
> >
> > -----------------------------------------------------
> > mywpnplog_api.h
> >
> >
> > #include < wtypes.h >
> >
> > #include < NPAPI.H >
> > #include < lmaccess.h >
> >
> > #include < windows.h >
> > #include < mywpnputil.h >
> >
> > typedef struct _UNICODE_STRING {
> > USHORT Length;
> > USHORT MaximumLength;
> > PWSTR Buffer;
> > } UNICODE_STRING;
> >
> > typedef struct _NONUNICODE_STRING {
> > USHORT Length;
> > USHORT MaximumLength;
> > LPTSTR Buffer;
> > } NONUNICODE_STRING;
> >
> > typedef struct _MSV1_0_INTERACTIVE_LOGON {
> > UCHAR MessageType;
> > UCHAR fill[3];
> > UNICODE_STRING LogonDomainName;
> > UNICODE_STRING UserName;
> > UNICODE_STRING Password;
> > } MSV1_0_INTERACTIVE_LOGON, *PMSV1_0_INTERACTIVE_LOGON;
> >
> >
> > -----------------------------------------------------
> > NPAPI.h
> >
> > /*++
> >
> > Copyright (c) 1991-1996 Microsoft Corporation
> >
> > Module Name:
> >
> > npapi.h
> >
> > Abstract:
> >
> > Network Provider API prototypes and manifests. A network provider
> > is a client of the Win32 Winnet driver. See the "NT/Win32 Network
> > Provider API Specification" document for further details.
> >
> > Environment:
> >
> > User Mode -Win32
> >
> > Notes:
> >
> > This file currently contains the function typedefs that will be
> > needed
> > by the winnet driver to support multiple providers using
> > LoadLibrary.
> >
> > --*/
> >
> > #include < mywpnp_api.h >
> >
> > #ifndef _NPAPI_INCLUDED
> > #define _NPAPI_INCLUDED
> >
> > #ifdef __cplusplus
> > extern "C" {
> > #endif
> >
> > //
> > // CONNECTIONS
> > //
> >
> > DWORD MYWPNP_API
> > NPAddConnection (
> > LPNETRESOURCEW lpNetResource,
> > LPWSTR lpPassword,
> > LPWSTR lpUserName
> > );
> >
> > typedef DWORD (*PF_NPAddConnection) (
> > LPNETRESOURCEW lpNetResource,
> > LPWSTR lpPassword,
> > LPWSTR lpUserName
> > );
> >
> >
> > DWORD MYWPNP_API
> > NPAddConnection3 (
> > HWND hwndOwner,
> > LPNETRESOURCEW lpNetResource,
> > LPWSTR lpPassword,
> > LPWSTR lpUserName,
> > DWORD dwFlags
> > );
> >
> > typedef DWORD (*PF_NPAddConnection3) (
> > HWND hwndOwner,
> > LPNETRESOURCEW lpNetResource,
> > LPWSTR lpPassword,
> > LPWSTR lpUserName,
> > DWORD dwFlags
> > );
> >
> >
> > DWORD MYWPNP_API
> > NPCancelConnection (
> > LPWSTR lpName,
> > BOOL fForce
> > );
> > typedef DWORD (*PF_NPCancelConnection) (
> > LPWSTR lpName,
> > BOOL fForce
> > );
> >
> >
> > DWORD MYWPNP_API
> > NPGetConnection (
> > LPWSTR lpLocalName,
> > LPWSTR lpRemoteName,
> > LPDWORD lpnBufferLen
> > );
> > typedef DWORD (*PF_NPGetConnection) (
> > LPWSTR lpLocalName,
> > LPWSTR lpRemoteName,
> > LPDWORD lpnBufferLen
> > );
> >
> >
> > #define WNGETCON_CONNECTED 0x00000000
> > #define WNGETCON_DISCONNECTED 0x00000001
> >
> > DWORD MYWPNP_API
> > NPGetConnection3 (
> > LPCWSTR lpLocalName,
> > DWORD dwLevel,
> > LPVOID lpBuffer,
> > LPDWORD lpBufferSize
> > );
> > typedef DWORD (*PF_NPGetConnection3) (
> > LPCWSTR lpLocalName,
> > DWORD dwLevel,
> > LPVOID lpBuffer,
> > LPDWORD lpBufferSize
> > );
> >
> >
> > DWORD MYWPNP_API
> > NPGetUniversalName (
> > LPCWSTR lpLocalPath,
> > DWORD dwInfoLevel,
> > LPVOID lpBuffer,
> > LPDWORD lpBufferSize
> > );
> > typedef DWORD (*PF_NPGetUniversalName) (
> > LPCWSTR lpLocalPath,
> > DWORD dwInfoLevel,
> > LPVOID lpBuffer,
> > LPDWORD lpnBufferSize
> > );
> >
> > DWORD MYWPNP_API
> > NPGetConnectionPerformance (
> > LPCWSTR lpRemoteName,
> > LPNETCONNECTINFOSTRUCT lpNetConnectInfo
> > );
> > typedef DWORD (*PF_NPGetConnectionPerformance) (
> > LPCWSTR lpRemoteName,
> > LPNETCONNECTINFOSTRUCT lpNetConnectInfo
> > );
> >
> >
> > DWORD MYWPNP_API
> > NPOpenEnum (
> > DWORD dwScope,
> > DWORD dwType,
> > DWORD dwUsage,
> > LPNETRESOURCEW lpNetResource,
> > LPHANDLE lphEnum
> > );
> > typedef DWORD (*PF_NPOpenEnum) (
> > DWORD dwScope,
> > DWORD dwType,
> > DWORD dwUsage,
> > LPNETRESOURCEW lpNetResource,
> > LPHANDLE lphEnum
> > );
> >
> > DWORD MYWPNP_API
> > NPEnumResource (
> > HANDLE hEnum,
> > LPDWORD lpcCount,
> > LPVOID lpBuffer,
> > LPDWORD lpBufferSize
> > );
> > typedef DWORD (*PF_NPEnumResource) (
> > HANDLE hEnum,
> > LPDWORD lpcCount,
> > LPVOID lpBuffer,
> > LPDWORD lpBufferSize
> > );
> >
> > DWORD MYWPNP_API
> > NPCloseEnum (
> > HANDLE hEnum
> > );
> > typedef DWORD (*PF_NPCloseEnum) (
> > HANDLE hEnum
> > );
> >
> >
> > //
> > // CAPABILITIES
> > //
> >
> > #define WNNC_SPEC_VERSION 0x00000001
> > #define WNNC_SPEC_VERSION51 0x00050001
> >
> > #define WNNC_NET_TYPE 0x00000002
> > #define WNNC_NET_NONE 0x00000000
> >
> > #define WNNC_DRIVER_VERSION 0x00000003
> >
> > #define WNNC_USER 0x00000004
> > #define WNNC_USR_GETUSER 0x00000001
> >
> > #define WNNC_CONNECTION 0x00000006
> > #define WNNC_CON_ADDCONNECTION 0x00000001
> > #define WNNC_CON_CANCELCONNECTION 0x00000002
> > #define WNNC_CON_GETCONNECTIONS 0x00000004
> > #define WNNC_CON_ADDCONNECTION3 0x00000008
> > #define WNNC_CON_GETPERFORMANCE 0x00000040
> > #define WNNC_CON_DEFER 0x00000080
> >
> > #define WNNC_DIALOG 0x00000008
> > #define WNNC_DLG_DEVICEMODE 0x00000001
> > #define WNNC_DLG_PROPERTYDIALOG 0x00000020
> > #define WNNC_DLG_SEARCHDIALOG 0x00000040
> > #define WNNC_DLG_FORMATNETWORKNAME 0x00000080
> > #define WNNC_DLG_PERMISSIONEDITOR 0x00000100
> > #define WNNC_DLG_GETRESOURCEPARENT 0x00000200
> > #define WNNC_DLG_GETRESOURCEINFORMATION 0x00000800
> >
> > #define WNNC_ADMIN 0x00000009
> > #define WNNC_ADM_GETDIRECTORYTYPE 0x00000001
> > #define WNNC_ADM_DIRECTORYNOTIFY 0x00000002
> >
> > #define WNNC_ENUMERATION 0x0000000B
> > #define WNNC_ENUM_GLOBAL 0x00000001
> > #define WNNC_ENUM_LOCAL 0x00000002
> > #define WNNC_ENUM_CONTEXT 0x00000004
> >
> > #define WNNC_START 0x0000000C
> > #define WNNC_WAIT_FOR_START 0x00000001
> >
> >
> >
> > DWORD MYWPNP_API
> > NPGetCaps (
> > DWORD ndex
> > );
> > typedef DWORD (*PF_NPGetCaps) (
> > DWORD ndex
> > );
> >
> > //
> > // OTHER
> > //
> >
> > DWORD MYWPNP_API
> > NPGetUser (
> > LPWSTR lpName,
> > LPWSTR lpUserName,
> > LPDWORD lpnBufferLen
> > );
> > typedef DWORD (*PF_NPGetUser) (
> > LPWSTR lpName,
> > LPWSTR lpUserName,
> > LPDWORD lpnBufferLen
> > );
> >
> > #define WNTYPE_DRIVE 1
> > #define WNTYPE_FILE 2
> > #define WNTYPE_PRINTER 3
> > #define WNTYPE_COMM 4
> >
> > #define WNPS_FILE 0
> > #define WNPS_DIR 1
> > #define WNPS_MULT 2
> >
> > DWORD MYWPNP_API
> > NPDeviceMode(
> > HWND hParent
> > );
> > typedef DWORD (*PF_NPDeviceMode) (
> > HWND hParent
> > );
> >
> > // flag for search dialog
> > #define WNSRCH_REFRESH_FIRST_LEVEL 0x00000001
> >
> > DWORD MYWPNP_API
> > NPSearchDialog(
> > HWND hwndParent,
> > LPNETRESOURCEW lpNetResource,
> > LPVOID lpBuffer,
> > DWORD cbBuffer,
> > LPDWORD lpnFlags
> > );
> > typedef DWORD (*PF_NPSearchDialog) (
> > HWND hwndParent,
> > LPNETRESOURCEW lpNetResource,
> > LPVOID lpBuffer,
> > DWORD cbBuffer,
> > LPDWORD lpnFlags
> > );
> >
> > DWORD MYWPNP_API
> > NPGetResourceParent(
> > LPNETRESOURCEW lpNetResource,
> > LPVOID lpBuffer,
> > LPDWORD lpBufferSize
> > );
> > typedef DWORD (*PF_NPGetResourceParent) (
> > LPNETRESOURCEW lpNetResource,
> > LPVOID lpBuffer,
> > LPDWORD lpBufferSize
> > );
> >
> > DWORD MYWPNP_API NPGetResourceInformation(
> > LPNETRESOURCEW lpNetResource,
> > LPVOID lpBuffer,
> > LPDWORD lpBufferSize,
> > LPWSTR *lplpSystem
> > );
> > typedef DWORD (*PF_NPGetResourceInformation) (
> > LPNETRESOURCEW lpNetResource,
> > LPVOID lpBuffer,
> > LPDWORD lpBufferSize,
> > LPWSTR *lplpSystem
> > );
> >
> > DWORD MYWPNP_API
> > NPFormatNetworkName(
> > LPWSTR lpRemoteName,
> > LPWSTR lpFormattedName,
> > LPDWORD lpnLength,
> > DWORD dwFlags,
> > DWORD dwAveCharPerLine
> > );
> > typedef DWORD (*PF_NPFormatNetworkName) (
> > LPWSTR lpRemoteName,
> > LPWSTR lpFormattedName,
> > LPDWORD lpnLength,
> > DWORD dwFlags,
> > DWORD dwAveCharPerLine
> > );
> >
> > DWORD MYWPNP_API
> > NPGetPropertyText(
> > DWORD iButton,
> > DWORD nPropSel,
> > LPWSTR lpName,
> > LPWSTR lpButtonName,
> > DWORD nButtonNameLen,
> > DWORD nType
> > );
> > typedef DWORD (*PF_NPGetPropertyText) (
> > DWORD iButton,
> > DWORD nPropSel,
> > LPWSTR lpName,
> > LPWSTR lpButtonName,
> > DWORD nButtonNameLen,
> > DWORD nType
> > );
> >
> > DWORD MYWPNP_API
> > NPPropertyDialog(
> > HWND hwndParent,
> > DWORD iButtonDlg,
> > DWORD nPropSel,
> > LPWSTR lpFileName,
> > DWORD nType
> > );
> > typedef DWORD (*PF_NPPropertyDialog) (
> > HWND hwndParent,
> > DWORD iButtonDlg,
> > DWORD nPropSel,
> > LPWSTR lpFileName,
> > DWORD nType
> > );
> >
> >
> > //
> > // ADMIN
> > //
> >
> > #define WNDT_NORMAL 0
> > #define WNDT_NETWORK 1
> >
> > #define WNDN_MKDIR 1
> > #define WNDN_RMDIR 2
> > #define WNDN_MVDIR 3
> >
> > DWORD MYWPNP_API
> > NPGetDirectoryType (
> > LPWSTR lpName,
> > LPINT lpType,
> > BOOL bFlushCache
> > );
> > typedef DWORD (*PF_NPGetDirectoryType) (
> > LPWSTR lpName,
> > LPINT lpType,
> > BOOL bFlushCache
> > );
> >
> > DWORD MYWPNP_API
> > NPDirectoryNotify (
> > HWND hwnd,
> > LPWSTR lpDir,
> > DWORD dwOper
> > );
> > typedef DWORD (*PF_NPDirectoryNotify) (
> > HWND hwnd,
> > LPWSTR lpDir,
> > DWORD dwOper
> > );
> >
> > VOID
> > WNetSetLastErrorA(
> > DWORD err,
> > LPSTR lpError,
> > LPSTR lpProviders
> > );
> >
> > VOID
> > WNetSetLastErrorW(
> > DWORD err,
> > LPWSTR lpError,
> > LPWSTR lpProviders
> > );
> >
> > #ifdef UNICODE
> > #define WNetSetLastError WNetSetLastErrorW
> > #else
> > #define WNetSetLastError WNetSetLastErrorA
> > #endif // UNICODE
> >
> > //
> > // CREDENTIAL MANAGEMENT and other classes of providers
> > //
> >
> >
> > // Define the Net/Authentication and othr Provider Classes
> > #define WN_NETWORK_CLASS 0x00000001
> > #define WN_CREDENTIAL_CLASS 0x00000002
> > #define WN_PRIMARY_AUTHENT_CLASS 0x00000004
> > #define WN_SERVICE_CLASS 0x00000008
> >
> > #define WN_VALID_LOGON_ACCOUNT 0x00000001
> > #define WN_NT_PASSWORD_CHANGED 0x00000002
> >
> > DWORD MYWPNP_API
> > NPLogonNotify (
> > PLUID lpLogonId,
> > LPCWSTR lpAuthentInfoType,
> > LPVOID lpAuthentInfo,
> > LPCWSTR lpPreviousAuthentInfoType,
> > LPVOID lpPreviousAuthentInfo,
> > LPWSTR lpStationName,
> > LPVOID StationHandle,
> > LPWSTR *lpLogonScript
> > );
> > typedef DWORD (*PF_NPLogonNotify) (
> > PLUID lpLogonId,
> > LPCWSTR lpAuthentInfoType,
> > LPVOID lpAuthentInfo,
> > LPCWSTR lpPreviousAuthentInfoType,
> > LPVOID lpPreviousAuthentInfo,
> > LPWSTR lpStationName,
> > LPVOID StationHandle,
> > LPWSTR *lpLogonScript
> > );
> >
> > DWORD MYWPNP_API
> > NPPasswordChangeNotify (
> > LPCWSTR lpAuthentInfoType,
> > LPVOID lpAuthentInfo,
> > LPCWSTR lpPreviousAuthentInfoType,
> > LPVOID lpPreviousAuthentInfo,
> > LPWSTR lpStationName,
> > LPVOID StationHandle,
> > DWORD dwChangeInfo
> > );
> >
> > typedef DWORD (*PF_NPPasswordChangeNotify) (
> > LPCWSTR lpAuthentInfoType,
> > LPVOID lpAuthentInfo,
> > LPCWSTR lpPreviousAuthentInfoType,
> > LPVOID lpPreviousAuthentInfo,
> > LPWSTR lpStationName,
> > LPVOID StationHandle,
> > DWORD dwChangeInfo
> > );
> >
> > //
> > // CONNECTION NOTIFICATION
> > //
> >
> > //
> > // NotifyStatus
> > //
> > #define NOTIFY_PRE 0x00000001
> > #define NOTIFY_POST 0x00000002
> >
> > typedef struct _NOTIFYINFO {
> > DWORD dwNotifyStatus;
> > DWORD dwOperationStatus;
> > LPVOID lpContext;
> > } NOTIFYINFO, *LPNOTIFYINFO;
> >
> > typedef struct _NOTIFYADD {
> > HWND hwndOwner;
> > NETRESOURCE NetResource;
> > DWORD dwAddFlags;
> > } NOTIFYADD, *LPNOTIFYADD;
> >
> > typedef struct _NOTIFYCANCEL {
> > LPWSTR lpName;
> > LPWSTR lpProvider;
> > DWORD dwFlags;
> > BOOL fForce;
> > } NOTIFYCANCEL, *LPNOTIFYCANCEL;
> >
> >
> > DWORD MYWPNP_API
> > AddConnectNotify (
> > LPNOTIFYINFO lpNotifyInfo,
> > LPNOTIFYADD lpAddInfo
> > );
> >
> > typedef DWORD (*PF_AddConnectNotify) (
> > LPNOTIFYINFO lpNotifyInfo,
> > LPNOTIFYADD lpAddInfo
> > );
> >
> > DWORD MYWPNP_API
> > CancelConnectNotify (
> > LPNOTIFYINFO lpNotifyInfo,
> > LPNOTIFYCANCEL lpCancelInfo
> > );
> >
> > typedef DWORD (*PF_CancelConnectNotify) (
> > LPNOTIFYINFO lpNotifyInfo,
> > LPNOTIFYCANCEL lpCancelInfo
> > );
> >
> > //
> > // Permission editor dialogs
> > //
> >
> > //
> > // Capabilities bits of permission editor dialogs
> > //
> > #define WNPERMC_PERM 0x00000001
> > #define WNPERMC_AUDIT 0x00000002
> > #define WNPERMC_OWNER 0x00000004
> >
> > DWORD MYWPNP_API
> > NPFMXGetPermCaps (
> > LPWSTR lpDriveName
> > );
> >
> > typedef DWORD (*PF_NPFMXGetPermCaps) (
> > LPWSTR lpDriveName
> > );
> >
> > //
> > // Type of security dialog
> > //
> > #define WNPERM_DLG_PERM 0
> > #define WNPERM_DLG_AUDIT 1
> > #define WNPERM_DLG_OWNER 2
> >
> > DWORD MYWPNP_API
> > NPFMXEditPerm (
> > LPWSTR lpDriveName,
> > HWND hwndFMX,
> > DWORD nDialogType
> > );
> >
> > typedef DWORD (*PF_NPFMXEditPerm) (
> > LPWSTR lpDriveName,
> > HWND hwndFMX,
> > DWORD nDialogType
> > );
> >
> > DWORD MYWPNP_API
> > NPFMXGetPermHelp (
> > LPWSTR lpDriveName,
> > DWORD nDialogType,
> > BOOL fDirectory,
> > LPVOID lpFileNameBuffer,
> > LPDWORD lpBufferSize,
> > LPDWORD lpnHelpContext
> > );
> >
> > typedef DWORD (*PF_NPFMXGetPermHelp) (
> > LPWSTR lpDriveName,
> > DWORD nDialogType,
> > BOOL fDirectory,
> > LPVOID lpFileNameBuffer,
> > LPDWORD lpBufferSize,
> > LPDWORD lpnHelpContext
> > );
> >
> > #ifdef __cplusplus
> > }
> > #endif
> >
> > #endif // _NPAPI_INCLUDED


Quantcast