2006-01-19 00:34:21 +01:00
/***********************************************************************
*
* Copyright ( C ) 2005 - 2006 Novell , Inc .
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; version 2.1
* of the License .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Library General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free
* Software Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*
* To contact Novell about this file by physical or electronic mail ,
* you may find current contact information at www . novell . com .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-10-11 21:51:00 +02:00
/***********************************************************************
* Following are registry entries , which must be created in order
* to run this credential manager ;
*
* [ HKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Control \ NetworkProvider \ Order
* " ProviderOrder " = LCredMgr , ( original string )
* [ HKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Services \ LCredMgr \ networkprovider
* " Class " = dword : 00000002
* " Name " = " LoginCapture Credential Provider "
* " ProviderPath " = "
*
* Following are registry entries , which must be created in order
* to run this notification dll ;
*
* [ HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ Winlogon \ Notify \ LCredMgr ]
* " Asynchronous " = dword : 00000001
* " DLLName " = " LCredMgr.dll "
* " Impersonate " = dword : 00000001
* " Logoff " = " NPLogoff "
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "lcredmgr.h"
# include <stdio.h>
//===[ External data ]=====================================================
//===[ Manifest constants ]================================================
//
// The authentication type is only used here in a Unicode context
//
# define MSV1_0_AUTH_TYPE L"MSV1_0:Interactive"
# define KERB_AUTH_TYPE L"Kerberos:Interactive"
# define WNNC_CRED_MANAGER 0xFFFF0000
# define WINDOWS_LOGON_ID 1
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
BOOL WriteLogFile ( LPTSTR String ) ;
DWORD
APIENTRY
NPGetCaps (
DWORD ndex
) ;
DWORD
APIENTRY
NPLogonNotify (
PLUID lpLogonId ,
LPCWSTR lpAuthentInfoType ,
LPVOID lpAuthentInfo ,
LPCWSTR lpPreviousAuthentInfoType ,
LPVOID lpPreviousAuthentInfo ,
LPWSTR lpStationName ,
LPVOID StationHandle ,
LPWSTR * lpLogonScript
) ;
DWORD
APIENTRY
NPPasswordChangeNotify (
LPCWSTR lpAuthentInfoType ,
LPVOID lpAuthentInfo ,
LPCWSTR lpPreviousAuthentInfoType ,
LPVOID lpPreviousAuthentInfo ,
LPWSTR lpStationName ,
LPVOID StationHandle ,
DWORD dwChangeInfo
) ;
//===[ Global variables ]==================================================
HMODULE g_hModule ;
HANDLE g_hModuleMutex = NULL ;
BOOLEAN g_bLibraryLoaded = FALSE ;
HINSTANCE g_hCASALibrary ;
PSETCREDENTIAL pCASASetCredential ;
POPENCACHE pCASAOpenCache ;
PCLOSECACHE pCASACloseCache ;
# ifdef _DEBUG
void
DebugPrint
(
char * format ,
. . .
)
{
va_list parameters ; /* Pointer to parameters on the stack */
char newString [ 600 ] = { " => LCredMgr: " } ;
/*
Get a pointer to the parameters
*/
va_start ( parameters , format ) ;
vsprintf ( & newString [ 13 ] , format , parameters ) ;
OutputDebugStringA ( newString ) ;
}
# endif
//++=======================================================================
BOOL
APIENTRY
DllMain (
HANDLE hInst ,
DWORD dwReason ,
LPVOID lpReserved
)
//=======================================================================--
{
# ifdef _DEBUG
DebugPrint ( " DllMain called. \n " ) ;
# endif
switch ( dwReason )
{
case DLL_PROCESS_ATTACH :
DisableThreadLibraryCalls ( ( HINSTANCE ) hInst ) ;
g_hModule = ( HMODULE ) hInst ;
g_hModuleMutex = CreateMutex ( NULL , FALSE , NULL ) ;
if ( g_hModuleMutex = = NULL )
{
return ( FALSE ) ;
}
InitLoginExtension ( ) ;
//
// Always succeed, this allows us to be configured with regsvr32.exe
//
break ;
case DLL_THREAD_ATTACH :
case DLL_THREAD_DETACH :
break ;
case DLL_PROCESS_DETACH :
CloseHandle ( g_hModuleMutex ) ;
break ;
}
return TRUE ;
}
//++=======================================================================
DWORD
WINAPI
NPGetCaps (
DWORD nIndex
)
//
// PURPOSE: This entry point is called to query the provider. The parameter
// is an index representing the query. For a credential manager
// only the following index values apply:
//
// WNNC_SPEC_VERSION - What version of the provider specification
// was used in developing this provider? The return value is
// the version number.
//
// WNNC_DRIVER_VERSION - The version of the provider.
//
// WNNC_START - Will the provider start? When? The return values
// are:
//
// - 0 : Only return this if the provider will *not* start.
// - Estimated Start time in milliseconds : This is how
// long the provider is expected to take to start.
// - 0xFFFFFFFF : Time to start is unknown.
// - 1 : Provider is already started.
//
// A return value of 0 in other cases indicates that the query
// is not supported.
//=======================================================================--
{
DWORD dwRes ;
# ifdef _DEBUG
DebugPrint ( " NPGetCaps called with nIndex %u. \n " , nIndex ) ;
# endif
switch ( nIndex )
{
case WNNC_NET_TYPE :
dwRes = WNNC_CRED_MANAGER ;
break ;
case WNNC_SPEC_VERSION :
dwRes = WNNC_SPEC_VERSION51 ; // We are using version 5.1 of the spec.
break ;
case WNNC_DRIVER_VERSION :
dwRes = 1 ; // This driver is version 1.
break ;
case WNNC_START :
dwRes = 1 ; // We are already "started"
break ;
default :
dwRes = 0 ; // We don't support anything else
break ;
}
# ifdef _DEBUG
DebugPrint ( " NPGetCaps returning dwRes %u. \n " , dwRes ) ;
# endif
return dwRes ;
}
//++=======================================================================
BOOLEAN
InitCASALibrary (
)
//
// PURPOSE: Loads the micasa dll entry points.
//=======================================================================--
{
BOOLEAN bLibraryLoaded = TRUE ;
if ( g_bLibraryLoaded = = FALSE )
{
WaitForSingleObjectEx ( g_hModuleMutex , INFINITE , FALSE ) ;
bLibraryLoaded = FALSE ;
if ( g_bLibraryLoaded = = FALSE )
{
g_hCASALibrary = LoadLibrary ( L " micasa.dll " ) ;
if ( g_hCASALibrary )
{
pCASASetCredential = ( PSETCREDENTIAL ) GetProcAddress ( g_hCASALibrary , " miCASASetCredential " ) ;
pCASAOpenCache = ( POPENCACHE ) GetProcAddress ( g_hCASALibrary , " miCASAOpenSecretStoreCache " ) ;
pCASACloseCache = ( PCLOSECACHE ) GetProcAddress ( g_hCASALibrary , " miCASACloseSecretStoreCache " ) ;
bLibraryLoaded = TRUE ;
g_bLibraryLoaded = TRUE ;
}
# ifdef _DEBUG
else
{
DebugPrint ( " LoadLibrary for micasa.dll failed. %d \n " , GetLastError ( ) ) ;
}
# endif
}
ReleaseMutex ( g_hModuleMutex ) ;
}
return bLibraryLoaded ;
}
//++=======================================================================
DWORD
WINAPI
NPLogonNotify (
PLUID lpLogonId ,
LPCWSTR lpAuthentInfoType ,
LPVOID lpAuthentInfo ,
LPCWSTR lpPreviousAuthentInfoType ,
LPVOID lpPreviousAuthentInfo ,
LPWSTR lpStationName ,
LPVOID StationHandle ,
LPWSTR * lpLogonScript
)
//
// PURPOSE: This entry point is called when a user logs on. If the user
// authentication fails here, the user will still be logged on
// to the local machine.
//=======================================================================--
{
int ccode ;
PMSV1_0_INTERACTIVE_LOGON pAuthInfo ;
SSCS_BASIC_CREDENTIAL basicCredential ;
SSCS_SECRET_ID_T desktopCredential ;
SSCS_SECRET_ID_T domainCredential ;
SSCS_EXT_T extension ;
BOOLEAN bLibraryLoaded ;
# ifdef _DEBUG
DebugPrint ( " NPLogonNotify called. \n " ) ;
# endif
SetLastError ( NO_ERROR ) ;
bLibraryLoaded = InitCASALibrary ( ) ;
if ( bLibraryLoaded = = FALSE )
{
SetLastError ( NO_ERROR ) ;
return NO_ERROR ;
}
//
// If the primary authenticator is not MSV1_0, return success.
// Why? Because this is the only auth info structure that we
// understand and we don't want to interact with other types.
//
if ( ! lstrcmpiW ( MSV1_0_AUTH_TYPE , lpAuthentInfoType ) )
{
# ifdef _DEBUG
DebugPrint ( " NPLogonNotify auth type is MSV1_0_AUTH_TYPE. \n " ) ;
# endif
}
else if ( ! lstrcmpiW ( KERB_AUTH_TYPE , lpAuthentInfoType ) )
{
# ifdef _DEBUG
DebugPrint ( " NPLogonNotify auth type is KERB_AUTH_TYPE. \n " ) ;
# endif
}
else
{
# ifdef _DEBUG
DebugPrint ( " NPLogonNotify auth type is UNSUPPORTED. \n " ) ;
# endif
SetLastError ( NO_ERROR ) ;
return NO_ERROR ;
}
if ( ( wcscmp ( L " SvcCtl " , lpStationName ) ) = = 0 )
{
# ifdef _DEBUG
DebugPrint ( " NPLogonNotify stationname indicates a service has logged on. \n " ) ;
# endif
return NO_ERROR ;
}
//
// Do something with the authentication information
//
pAuthInfo = ( PMSV1_0_INTERACTIVE_LOGON ) lpAuthentInfo ;
basicCredential . unLen = WideCharToMultiByte (
CP_UTF8 ,
0 ,
pAuthInfo - > UserName . Buffer ,
- 1 ,
( LPSTR ) & basicCredential . username ,
NSSCS_MAX_USERID_LEN ,
NULL ,
NULL ) ;
if ( basicCredential . unLen )
{
// basicCredential.unLen++;
basicCredential . pwordLen = WideCharToMultiByte (
CP_UTF8 ,
0 ,
pAuthInfo - > Password . Buffer ,
- 1 ,
( LPSTR ) & basicCredential . password ,
NSSCS_MAX_PWORD_LEN ,
NULL ,
NULL ) ;
if ( basicCredential . pwordLen )
{
// basicCredential.pwordLen++;
strcpy ( ( char * ) & desktopCredential . id , " Desktop " ) ;
desktopCredential . len = ( long ) strlen ( ( char * ) & desktopCredential . id ) + 1 ;
basicCredential . unFlags = USERNAME_TYPE_CN_F ;
extension . extID = WINDOWS_LOGON_ID ;
extension . version = 0x00010000 ; // 1.0.0
extension . ext = ( void * ) lpLogonId ;
ccode = ( * pCASASetCredential ) (
0 ,
& desktopCredential ,
NULL ,
SSCS_CRED_TYPE_BASIC_F ,
& basicCredential ,
& extension ) ;
# ifdef _DEBUG
if ( ! ccode )
{
DebugPrint ( " NSSCSSetCredential successful!. \n " ) ;
}
else
{
DebugPrint ( " NSSCSSetCredential failed 0x%X \n " , ccode ) ;
}
# endif
if ( pAuthInfo - > LogonDomainName . Length ! = 0 )
{
domainCredential . len = WideCharToMultiByte (
CP_UTF8 ,
0 ,
pAuthInfo - > LogonDomainName . Buffer ,
- 1 ,
( LPSTR ) & domainCredential . id ,
NSSCS_MAX_SECRET_ID_LEN ,
NULL ,
NULL ) ;
if ( domainCredential . len )
{
// domainCredential.len++;
# ifdef _DEBUG
DebugPrint ( " Domain exists - [%s], length %d \n " , domainCredential . id , domainCredential . len ) ;
# endif
ccode = ( * pCASASetCredential ) (
0 ,
& desktopCredential ,
& domainCredential ,
SSCS_CRED_TYPE_BASIC_F ,
& basicCredential ,
& extension ) ;
# ifdef _DEBUG
if ( ! ccode )
{
DebugPrint ( " NSSCSSetCredential successful!. \n " ) ;
}
else
{
DebugPrint ( " NSSCSSetCredential failed 0x%X \n " , ccode ) ;
}
# endif
}
}
}
# ifdef _DEBUG
else
{
DebugPrint ( " WideCharToMultiByte for password failed. \n " ) ;
}
# endif
}
# ifdef _DEBUG
else
{
DebugPrint ( " WideCharToMultiByte for user name failed. \n " ) ;
}
# endif
return NO_ERROR ;
}
//++=======================================================================
DWORD
WINAPI
NPPasswordChangeNotify (
LPCWSTR lpAuthentInfoType ,
LPVOID lpAuthentInfo ,
LPCWSTR lpPreviousAuthentInfoType ,
LPVOID lpPreviousAuthentInfo ,
LPWSTR lpStationName ,
LPVOID StationHandle ,
DWORD dwChangeInfo
)
//
// PURPOSE: This function is used to notify a credential manager provider
// of a password change (or, more accurately, an authentication
// information change) for an account.
//=======================================================================--
{
// return NO_ERROR;
# ifdef _DEBUG
DebugPrint ( " NPPasswordChangeNotify called. \n " ) ;
# endif
return WN_NOT_SUPPORTED ;
}
//++=======================================================================
VOID
WINAPI
NPLogoff (
PWLX_NOTIFICATION_INFO pInfo
)
//=======================================================================--
{
DWORD dwSize ;
TOKEN_STATISTICS tokenStats ;
SSCS_SECRETSTORE_T ssId ;
HANDLE context ;
BOOLEAN bLibraryLoaded ;
# ifdef _DEBUG
DebugPrint ( " NPLogoff called. \n " ) ;
# endif
dwSize = sizeof ( tokenStats ) ;
if ( GetTokenInformation (
pInfo - > hToken ,
TokenStatistics ,
& tokenStats ,
dwSize ,
& dwSize ) )
{
# ifdef _DEBUG
DebugPrint ( " GetTokenInformation for statistics returned LowPart 0x%X HighPart 0x%X \n " , tokenStats . AuthenticationId . LowPart , tokenStats . AuthenticationId . HighPart ) ;
# endif
}
# ifdef _DEBUG
else
{
DebugPrint ( " GetTokenInformation for TokenStatistics failed %u \n " , GetLastError ( ) ) ;
}
# endif
bLibraryLoaded = TRUE ;
WaitForSingleObjectEx ( g_hModuleMutex , INFINITE , FALSE ) ;
if ( g_bLibraryLoaded = = FALSE )
{
# ifdef _DEBUG
DebugPrint ( " Library not loaded in NPLogoff. \n " ) ;
# endif
bLibraryLoaded = FALSE ;
}
ReleaseMutex ( g_hModuleMutex ) ;
if ( bLibraryLoaded = = FALSE )
{
return ;
}
ssId . version = NSSCS_VERSION_NUMBER ;
strcpy ( ( char * ) ssId . ssName , ( char * ) SSCS_DEFAULT_SECRETSTORE_ID ) ;
context = ( * pCASAOpenCache ) (
& ssId ,
0 ,
NULL ) ;
if ( context )
{
//
// the SSFLAG_DESTROY_SESSION_F closes the session for this user
//
( * pCASACloseCache ) (
context ,
SSFLAG_DESTROY_SESSION_F ,
NULL ) ;
}
return ;
}
//++=======================================================================
DWORD
AddSubString (
HKEY hKey
)
//=======================================================================--
{
LONG rc ;
CHAR szValue [ 256 ] ,
szNewValue [ 256 ] ;
DWORD valueSize ;
valueSize = sizeof ( szValue ) ;
rc = RegQueryValueExA (
hKey ,
" ProviderOrder " ,
0 ,
NULL ,
( PUCHAR ) szValue ,
& valueSize ) ;
if ( rc = = S_OK )
{
strcpy ( szNewValue , " LCredMgr, " ) ;
strcat ( szNewValue , szValue ) ;
rc = RegSetValueExA (
hKey ,
" ProviderOrder " ,
0 ,
REG_SZ ,
( PUCHAR ) szNewValue ,
( DWORD ) strlen ( szNewValue ) ) ;
}
return rc ;
}
//++=======================================================================
DWORD
RemoveSubString (
HKEY hKey
)
//=======================================================================--
{
LONG rc ;
CHAR szValue [ 256 ] ,
szNewValue [ 256 ] ;
PCHAR subString , startString , endString ;
DWORD valueSize ;
valueSize = sizeof ( szValue ) ;
rc = RegQueryValueExA (
hKey ,
" ProviderOrder " ,
0 ,
NULL ,
( PUCHAR ) szValue ,
& valueSize ) ;
if ( rc = = S_OK )
{
//
// Remove any leading whitespace
//
subString = szValue ;
while ( * subString ! = NULL & & ( * subString = = ' , ' | | * subString = = ' ' ) )
{
subString + + ;
}
startString = subString ;
//
// Check to see if lcredmgr is in the string
//
if ( ( subString = strstr ( startString , " LCredMgr " ) ) ! = NULL )
{
if ( subString = = startString )
{
while ( * subString ! = ' , ' & & * subString ! = NULL )
{
subString + + ;
}
while ( ( * subString = = ' , ' | | * subString = = ' ' ) & & * subString ! = NULL )
{
subString + + ;
}
startString = subString ;
}
else
{
endString = subString + 8 ;
//
// Back up past any whitespace or comma's.
//
for ( subString - - ; ; subString - - )
{
if ( * subString ! = ' ' & & * subString ! = ' , ' )
{
* ( subString + 1 ) = ' \0 ' ;
break ;
}
}
//
// Get past any comma's
//
for ( ; ; endString + + )
{
if ( * endString = = NULL )
{
break ;
}
if ( ( * endString ! = ' , ' & & * endString ! = ' ' ) )
{
//
// concat the two strings without lcredmgr
//
strcpy ( szNewValue , startString ) ;
strcat ( szNewValue , endString ) ;
startString = szNewValue ;
break ;
}
}
}
rc = RegSetValueExA (
hKey ,
" ProviderOrder " ,
0 ,
REG_SZ ,
( PUCHAR ) startString ,
( DWORD ) strlen ( startString ) ) ;
}
}
return rc ;
}
//++=======================================================================
HRESULT
DllInstall (
BOOL bInstall ,
LPCWSTR pszCmdLine
)
//=======================================================================--
{
HKEY hKey ;
LONG rc ;
CHAR szModule [ 256 ] ;
DWORD value , valueSize ;
# ifdef _DEBUG
DebugPrint ( " DllInstall called \n " ) ;
OutputDebugStringW ( pszCmdLine ) ;
# endif
if ( bInstall = = TRUE )
{
rc = RegCreateKeyExA (
HKEY_LOCAL_MACHINE ,
" System \\ CurrentControlSet \\ Control \\ NetworkProvider \\ Order " ,
0 ,
NULL ,
REG_OPTION_NON_VOLATILE ,
KEY_ALL_ACCESS ,
NULL ,
& hKey ,
NULL ) ;
if ( rc = = S_OK )
{
rc = RemoveSubString ( hKey ) ;
if ( rc = = S_OK )
{
rc = AddSubString ( hKey ) ;
}
RegCloseKey ( hKey ) ;
}
//
// Set up our service key
//
if ( rc = = S_OK )
{
rc = RegCreateKeyExA (
HKEY_LOCAL_MACHINE ,
" System \\ CurrentControlSet \\ Services \\ LCredMgr \\ networkprovider " ,
0 ,
NULL ,
REG_OPTION_NON_VOLATILE ,
KEY_ALL_ACCESS ,
NULL ,
& hKey ,
NULL ) ;
if ( rc = = S_OK )
{
value = 2 ;
rc = RegSetValueExA (
hKey ,
" Class " ,
0 ,
REG_DWORD ,
( BYTE * ) & value ,
sizeof ( value ) ) ;
if ( rc ! = S_OK )
{
goto ErrorExit ;
}
rc = RegSetValueExA (
hKey ,
" Name " ,
0 ,
REG_SZ ,
( BYTE * ) " LoginCapture Credential Provider " ,
32 ) ;
if ( rc ! = S_OK )
{
goto ErrorExit ;
}
valueSize = GetModuleFileNameA ( ( HMODULE ) g_hModule , szModule , sizeof ( szModule ) ) ;
if ( valueSize )
{
rc = RegSetValueExA (
hKey ,
" ProviderPath " ,
0 ,
REG_SZ ,
( BYTE * ) szModule ,
valueSize + 1 ) ;
}
else
{
rc = GetLastError ( ) ;
}
RegCloseKey ( hKey ) ;
}
}
if ( rc = = S_OK )
{
rc = RegCreateKeyExA (
HKEY_LOCAL_MACHINE ,
" SOFTWARE \\ Microsoft \\ Windows NT \\ CurrentVersion \\ Winlogon \\ Notify \\ LCredMgr " ,
0 ,
NULL ,
REG_OPTION_NON_VOLATILE ,
KEY_ALL_ACCESS ,
NULL ,
& hKey ,
NULL ) ;
if ( rc = = S_OK )
{
value = 1 ;
rc = RegSetValueExA (
hKey ,
" Asynchronous " ,
0 ,
REG_DWORD ,
( BYTE * ) & value ,
sizeof ( value ) ) ;
if ( rc ! = S_OK )
{
goto ErrorExit ;
}
rc = RegSetValueExA (
hKey ,
" DLLName " ,
0 ,
REG_SZ ,
( BYTE * ) szModule ,
valueSize + 1 ) ;
if ( rc ! = S_OK )
{
goto ErrorExit ;
}
rc = RegSetValueExA (
hKey ,
" Impersonate " ,
0 ,
REG_DWORD ,
( BYTE * ) & value ,
sizeof ( value ) ) ;
if ( rc ! = S_OK )
{
goto ErrorExit ;
}
rc = RegSetValueExA (
hKey ,
" Logoff " ,
0 ,
REG_SZ ,
( BYTE * ) " NPLogoff " ,
9 ) ;
RegCloseKey ( hKey ) ;
}
}
if ( rc = = S_OK )
{
rc = RegCreateKeyExA (
HKEY_LOCAL_MACHINE ,
" SOFTWARE \\ Novell \\ Graphical Login \\ NWLGE \\ LCredMgr " ,
0 ,
NULL ,
REG_OPTION_NON_VOLATILE ,
KEY_ALL_ACCESS ,
NULL ,
& hKey ,
NULL ) ;
if ( rc = = S_OK )
{
rc = RegSetValueExA (
hKey ,
" LoginExtName " ,
0 ,
REG_SZ ,
( BYTE * ) szModule ,
valueSize + 1 ) ;
if ( rc ! = S_OK )
{
goto ErrorExit ;
}
rc = RegSetValueExA (
hKey ,
" LoginExtDesc " ,
0 ,
REG_SZ ,
( BYTE * ) " CASA Login Extension " ,
20 ) ;
if ( rc ! = S_OK )
{
goto ErrorExit ;
}
value = 0x00008002 ;
rc = RegSetValueExA (
hKey ,
" LoginExtType " ,
0 ,
REG_DWORD ,
( BYTE * ) & value ,
sizeof ( value ) ) ;
ErrorExit :
RegCloseKey ( hKey ) ;
}
}
}
else
{
rc = RegCreateKeyExA (
HKEY_LOCAL_MACHINE ,
" System \\ CurrentControlSet \\ Control \\ NetworkProvider \\ Order " ,
0 ,
NULL ,
REG_OPTION_NON_VOLATILE ,
KEY_ALL_ACCESS ,
NULL ,
& hKey ,
NULL ) ;
if ( rc = = S_OK )
{
RemoveSubString ( hKey ) ;
RegCloseKey ( hKey ) ;
}
//
// Delete our service key
//
RegDeleteKeyA (
HKEY_LOCAL_MACHINE ,
" System \\ CurrentControlSet \\ Services \\ LCredMgr \\ Enum " ) ;
RegDeleteKeyA (
HKEY_LOCAL_MACHINE ,
" System \\ CurrentControlSet \\ Services \\ LCredMgr \\ networkprovider " ) ;
RegDeleteKeyA (
HKEY_LOCAL_MACHINE ,
" System \\ CurrentControlSet \\ Services \\ LCredMgr " ) ;
RegDeleteKeyA (
HKEY_LOCAL_MACHINE ,
" SOFTWARE \\ Microsoft \\ Windows NT \\ CurrentVersion \\ Winlogon \\ Notify \\ LCredMgr " ) ;
RegDeleteKeyA (
HKEY_LOCAL_MACHINE ,
" SOFTWARE \\ Novell \\ Graphical Login \\ NWLGE \\ LCredMgr " ) ;
}
# ifdef _DEBUG
if ( rc = = S_OK )
{
DebugPrint ( " DllInstall successful. \n " ) ;
}
else
{
DebugPrint ( " DllInstall failed. \n " ) ;
}
# endif
return rc ;
}
//++=======================================================================
STDAPI
DllRegisterServer (
void
)
//=======================================================================--
{
# ifdef _DEBUG
DebugPrint ( " DllRegisterServer called \n " ) ;
# endif
return S_OK ;
}
//++=======================================================================
STDAPI
DllUnregisterServer (
void
)
//=======================================================================--
{
# ifdef _DEBUG
DebugPrint ( " DllUnregisterServer called \n " ) ;
# endif
return S_OK ;
}
//=========================================================================
//=========================================================================