Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1215 lines
28 KiB

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
infostub.c
Abstract:
Client stubs of the Internet Info Server Admin APIs.
Author:
Madan Appiah (madana) 10-Oct-1993
Environment:
User Mode - Win32
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include "info_cli.h"
#include <ntsam.h>
#include <ntlsa.h>
#include <ftpd.h>
#include <w3svc.h>
#include <rpcutil.h>
#include <winsock2.h>
#include <rpcasync.h>
//
// Quick macro to initialize a unicode string
//
WCHAR g_wchUnicodeNull[] = L"";
#define _InitUnicodeString( pUnicode, pwch ) \
{ \
(pUnicode)->Buffer = pwch; \
(pUnicode)->Length = wcslen( pwch ) * sizeof(WCHAR); \
(pUnicode)->MaximumLength = (pUnicode)->Length + sizeof(WCHAR); \
}
# define InitUnicodeString( pUnicode, pwch) \
if (pwch == NULL) { _InitUnicodeString( pUnicode, g_wchUnicodeNull); } \
else { _InitUnicodeString( pUnicode, pwch); } \
//
// Returns a unicode empty string if the string is NULL
//
#define EMPTY_IF_NULL(str) (str ? str : L"")
struct SRV_SECRET_NAMES
{
DWORD dwID;
LPWSTR SecretName;
LPWSTR RootSecretName;
}
aSrvSecrets[] =
{
INET_FTP, FTPD_ANONYMOUS_SECRET_W, FTPD_ROOT_SECRET_W,
INET_HTTP, W3_ANONYMOUS_SECRET_W, W3_ROOT_SECRET_W,
INET_GOPHER, GOPHERD_ANONYMOUS_SECRET_W , GOPHERD_ROOT_SECRET_W,
//INET_CHAT, CHAT_ANONYMOUS_SECRET_W, CHAT_ROOT_SECRET_W,
//INET_NNTP, NNTP_ANONYMOUS_SECRET_W, NNTP_ROOT_SECRET_W,
//INET_SMTP, SMTP_ANONYMOUS_SECRET_W, SMTP_ROOT_SECRET_W,
//INET_POP3, POP3_ANONYMOUS_SECRET_W, POP3_ROOT_SECRET_W,
//INET_LDAP, LDAP_ANONYMOUS_SECRET_W, LDAP_ROOT_SECRET_W,
//INET_IMAP, IMAP_ANONYMOUS_SECRET_W, IMAP_ROOT_SECRET_W,
0, NULL, NULL
};
DWORD
GetSecret(
IN LPWSTR Server,
IN LPWSTR SecretName,
OUT LPWSTR * ppSecret
);
DWORD
SetSecret(
IN LPWSTR Server,
IN LPWSTR SecretName,
IN LPWSTR pSecret,
IN DWORD cbSecret
);
NET_API_STATUS
NET_API_FUNCTION
InetInfoGetVersion(
IN LPWSTR Server OPTIONAL,
IN DWORD dwReserved,
OUT DWORD * pdwVersion
)
{
NET_API_STATUS status;
RpcTryExcept
{
//
// Try RPC (local or remote) version of API.
//
status = R_InetInfoGetVersion(
Server,
dwReserved,
pdwVersion
);
}
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
{
status = RpcExceptionCode();
}
RpcEndExcept
return (status);
} // InetInfoGetVersion()
NET_API_STATUS
NET_API_FUNCTION
InetInfoGetServerCapabilities(
IN LPWSTR Server OPTIONAL,
IN DWORD dwReserved,
OUT LPINET_INFO_CAPABILITIES * ppCap
)
{
NET_API_STATUS status;
*ppCap = NULL;
RpcTryExcept
{
//
// Try RPC (local or remote) version of API.
//
status = R_InetInfoGetServerCapabilities(
Server,
dwReserved,
(LPINET_INFO_CAPABILITIES_STRUCT *)ppCap
);
}
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
{
status = RpcExceptionCode();
}
RpcEndExcept
return (status);
} // InetInfoServerCapabilities()
NET_API_STATUS
NET_API_FUNCTION
InetInfoQueryStatistics(
IN LPWSTR pszServer OPTIONAL,
IN DWORD Level,
IN DWORD dwServerMask,
OUT LPBYTE * Buffer
)
{
NET_API_STATUS status;
*Buffer = NULL;
RpcTryExcept
{
//
// Try RPC (local or remote) version of API.
//
status = R_InetInfoQueryStatistics(
pszServer,
Level,
dwServerMask,
(LPINET_INFO_STATISTICS_INFO) Buffer
);
}
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
{
status = RpcExceptionCode();
}
RpcEndExcept
return (status);
} // InetInfoQueryStatistics()
NET_API_STATUS
NET_API_FUNCTION
InetInfoClearStatistics(
IN LPWSTR pszServer OPTIONAL,
IN DWORD dwServerMask
)
{
NET_API_STATUS status;
RpcTryExcept
{
//
// Try RPC (local or remote) version of API.
//
status = R_InetInfoClearStatistics(
pszServer,
dwServerMask
);
}
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
{
status = RpcExceptionCode();
}
RpcEndExcept
return (status);
} // InetInfoClearStatistics()
NET_API_STATUS
NET_API_FUNCTION
InetInfoFlushMemoryCache(
IN LPWSTR pszServer OPTIONAL,
IN DWORD dwServerMask
)
{
NET_API_STATUS status;
RpcTryExcept
{
//
// Try RPC (local or remote) version of API.
//
status = R_InetInfoFlushMemoryCache(
pszServer,
dwServerMask
);
}
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
{
status = RpcExceptionCode();
}
RpcEndExcept
return (status);
} // InetInfoFlushMemoryCache()
NET_API_STATUS
NET_API_FUNCTION
InetInfoGetGlobalAdminInformation(
IN LPWSTR Server OPTIONAL,
IN DWORD dwReserved,
OUT LPINET_INFO_GLOBAL_CONFIG_INFO * ppConfig
)
{
NET_API_STATUS status;
RpcTryExcept
{
status = R_InetInfoGetGlobalAdminInformation(
Server,
dwReserved,
ppConfig
);
}
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
{
status = RpcExceptionCode();
}
RpcEndExcept
return status;
} // InetInfoGetGlobalAdminInformation()
NET_API_STATUS
NET_API_FUNCTION
InetInfoGetSites(
IN LPWSTR pszServer OPTIONAL,
IN DWORD dwServerMask,
OUT LPINET_INFO_SITE_LIST * ppSites
)
{
NET_API_STATUS status;
RpcTryExcept
{
status = R_InetInfoGetSites(
pszServer,
dwServerMask,
ppSites
);
}
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
{
status = RpcExceptionCode();
}
RpcEndExcept
return status;
} // InetInfoGetSites()
NET_API_STATUS
NET_API_FUNCTION
InetInfoSetGlobalAdminInformation(
IN LPWSTR Server OPTIONAL,
IN DWORD dwReserved,
IN INET_INFO_GLOBAL_CONFIG_INFO * pConfig
)
{
NET_API_STATUS status;
RpcTryExcept
{
status = R_InetInfoSetGlobalAdminInformation(
Server,
dwReserved,
pConfig
);
}
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
{
status = RpcExceptionCode();
}
RpcEndExcept
return status;
} // InetInfoSetGlobalAdminInformation()
NET_API_STATUS
NET_API_FUNCTION
InetInfoGetAdminInformation(
IN LPWSTR Server OPTIONAL,
IN DWORD dwServerMask,
OUT LPINET_INFO_CONFIG_INFO * ppConfig
)
{
NET_API_STATUS status;
BOOL fGetPassword = TRUE;
LPWSTR pSecret;
DWORD i = 0;
DWORD j;
LPWSTR pszCurrent;
INET_INFO_VIRTUAL_ROOT_ENTRY * pVirtRoot;
RpcTryExcept
{
status = R_InetInfoGetAdminInformation(
Server,
dwServerMask,
ppConfig
);
}
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
{
status = RpcExceptionCode();
}
RpcEndExcept
if ( status )
return status;
#ifndef CHICAGO
//
// Get the anonymous account password
//
while ( aSrvSecrets[i].dwID &&
!(aSrvSecrets[i].dwID & dwServerMask ) )
{
i++;
}
// Note: Only the service corresponding to first mask is chosen.
if ( !aSrvSecrets[i].dwID )
return ERROR_INVALID_PARAMETER;
status = GetSecret( Server,
aSrvSecrets[i].SecretName,
&pSecret );
if ( status )
return status;
memcpy( (*ppConfig)->szAnonPassword,
pSecret,
sizeof(WCHAR) * min( wcslen( pSecret ), PWLEN ));
(*ppConfig)->szAnonPassword[PWLEN] = L'\0';
LocalFree( pSecret );
//
// Zero terminate all of the passwords in case there is no associated
// secret
//
for ( j = 0; j < (*ppConfig)->VirtualRoots->cEntries; j++ )
{
*(*ppConfig)->VirtualRoots->aVirtRootEntry[j].AccountPassword = L'\0';
}
status = GetSecret( Server,
aSrvSecrets[i].RootSecretName,
&pSecret );
if ( status )
return status;
pszCurrent = pSecret;
while ( *pszCurrent )
{
LPWSTR pszRoot;
LPWSTR pszPassword;
LPWSTR pszAddress;
LPWSTR pszNextLine = pszCurrent + wcslen(pszCurrent) + 1;
//
// The list is in the form:
//
// <Root>,<Addresss>=<Password>\0
// <Root>,<Addresss>=<Password>\0
// \0
//
pszRoot = pszCurrent;
pszPassword = wcschr( pszCurrent, L'=' );
if ( !pszPassword )
{
//
// Bad list format, skip this one
//
goto NextLine;
}
*pszPassword = L'\0';
pszPassword++;
pszAddress = wcschr( pszRoot, L',');
if ( !pszAddress )
{
goto NextLine;
}
*pszAddress = L'\0';
pszAddress++;
//
// Now look for this root and address in the virtual root list
// so we can set the password
//
for ( i = 0; i < (*ppConfig)->VirtualRoots->cEntries; i++ )
{
pVirtRoot = &(*ppConfig)->VirtualRoots->aVirtRootEntry[i];
if ( !_wcsicmp( pszRoot, pVirtRoot->pszRoot ) &&
(!pszAddress || !_wcsicmp( pszAddress, pVirtRoot->pszAddress)))
{
//
// If the password length is invalid, we just ignore it.
// This shouldn't happen because we check before setting the
// password
//
if ( wcslen( pszPassword ) <= PWLEN )
{
wcscpy( pVirtRoot->AccountPassword,
pszPassword );
break;
}
}
}
NextLine:
pszCurrent = pszNextLine;
}
LocalFree( pSecret );
#else // CHICAGO
//
// Zero terminate all of the passwords in case there is no associated
// secret
//
for ( j = 0; j < (*ppConfig)->VirtualRoots->cEntries; j++ )
{
*(*ppConfig)->VirtualRoots->aVirtRootEntry[j].AccountPassword = L'\0';
}
#endif // CHICAGO
return status;
} // InetInfoGetAdminInformation()
NET_API_STATUS
NET_API_FUNCTION
InetInfoSetAdminInformation(
IN LPWSTR Server OPTIONAL,
IN DWORD dwServerMask,
IN INET_INFO_CONFIG_INFO * pConfig
)
{
NET_API_STATUS status;
WCHAR szAnonPassword[PWLEN+1];
LPWSTR pszRootPasswords = NULL;
LPWSTR pszPassword;
DWORD i, j;
#ifndef CHICAGO
//
// Enumerate the LSA secret names for the specified servers. We set the
// secrets first so the anonymous user name password can be refreshed
// in the server side InetInfoSetAdminInformation
//
i = 0;
while ( aSrvSecrets[i].dwID )
{
if ( !(aSrvSecrets[i].dwID & dwServerMask ))
{
i++;
continue;
}
if ( IsFieldSet( pConfig->FieldControl, FC_INET_INFO_ANON_PASSWORD ))
{
status = SetSecret( Server,
aSrvSecrets[i].SecretName,
pConfig->szAnonPassword,
(wcslen( pConfig->szAnonPassword ) + 1)
* sizeof(WCHAR));
if ( status )
return status;
}
if ( IsFieldSet( pConfig->FieldControl, FC_INET_INFO_VIRTUAL_ROOTS ))
{
DWORD cbNeeded = sizeof(WCHAR);
INET_INFO_VIRTUAL_ROOT_ENTRY * pVirtRoot;
LPWSTR psz;
LPWSTR pszSecret;
//
// Build a string that looks like:
//
// <Root>,<Addresss>=<Password>\0
// <Root>,<Addresss>=<Password>\0
// \0
//
//
// Do a first pass to figure the buffer size we need to build
//
for ( j = 0; j < pConfig->VirtualRoots->cEntries; j++ )
{
pVirtRoot = &pConfig->VirtualRoots->aVirtRootEntry[j];
cbNeeded += (wcslen( pVirtRoot->pszRoot ) +
wcslen( EMPTY_IF_NULL(pVirtRoot->pszAddress)) +
wcslen( pVirtRoot->AccountPassword ) +
(PWLEN + 3)) * sizeof(WCHAR);
}
//
// We always allocate at least enough room for a '\0'
//
pszSecret = LocalAlloc( LPTR, cbNeeded + sizeof(WCHAR) );
if ( !pszSecret )
return ERROR_NOT_ENOUGH_MEMORY;
psz = pszSecret;
//
// Now build the string
//
for ( j = 0; j < pConfig->VirtualRoots->cEntries; j++ )
{
pVirtRoot = &pConfig->VirtualRoots->aVirtRootEntry[j];
psz += wsprintfW( psz,
L"%ls,%ls=%ls",
pVirtRoot->pszRoot,
EMPTY_IF_NULL(pVirtRoot->pszAddress),
pVirtRoot->AccountPassword );
psz++;
}
//
// Add the list terminating NULL
//
*psz = L'\0';
status = SetSecret( Server,
aSrvSecrets[i].RootSecretName,
pszSecret,
cbNeeded );
LocalFree( pszSecret );
if ( status )
return status;
}
i++;
}
#endif // CHICAGO
//
// Set the passwords to NULL so it doesn't go out on the
// wire. We set them as a secrets above
//
if ( IsFieldSet( pConfig->FieldControl, FC_INET_INFO_VIRTUAL_ROOTS ))
{
pszRootPasswords = LocalAlloc( LPTR,
pConfig->VirtualRoots->cEntries *
(PWLEN + 1) * sizeof(WCHAR) );
if ( !pszRootPasswords )
return ERROR_NOT_ENOUGH_MEMORY;
for ( i = 0; i < pConfig->VirtualRoots->cEntries; i++ )
{
pszPassword = pConfig->VirtualRoots->aVirtRootEntry[i].AccountPassword;
if ( wcslen( pszPassword ) > PWLEN )
{
LocalFree( pszRootPasswords );
return ERROR_INVALID_PARAMETER;
}
wcscpy( pszRootPasswords + i * (PWLEN + 1),
pszPassword );
SecureZeroMemory( pszPassword,
sizeof( pConfig->VirtualRoots->aVirtRootEntry[i].AccountPassword ));
}
}
if ( IsFieldSet( pConfig->FieldControl, FC_INET_INFO_ANON_PASSWORD ))
{
memcpy( szAnonPassword,
pConfig->szAnonPassword,
sizeof(pConfig->szAnonPassword) );
SecureZeroMemory( pConfig->szAnonPassword,
sizeof(pConfig->szAnonPassword) );
}
RpcTryExcept
{
status = R_InetInfoSetAdminInformation(
Server,
dwServerMask,
pConfig
);
}
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
{
status = RpcExceptionCode();
}
RpcEndExcept
//
// Restore the structure we just mucked with
//
if ( IsFieldSet( pConfig->FieldControl, FC_INET_INFO_ANON_PASSWORD ))
{
memcpy( pConfig->szAnonPassword,
szAnonPassword,
sizeof(pConfig->szAnonPassword) );
SecureZeroMemory( szAnonPassword, sizeof( szAnonPassword ));
}
if ( IsFieldSet( pConfig->FieldControl, FC_INET_INFO_VIRTUAL_ROOTS ))
{
for ( i = 0; i < pConfig->VirtualRoots->cEntries; i++ )
{
pszPassword = pConfig->VirtualRoots->aVirtRootEntry[i].AccountPassword;
wcscpy( pszPassword,
pszRootPasswords + i * (PWLEN + 1) );
}
SecureZeroMemory( pszRootPasswords,
pConfig->VirtualRoots->cEntries * (PWLEN + 1) * sizeof(WCHAR));
LocalFree( pszRootPasswords );
pszRootPasswords = NULL;
}
return status;
} // InetInfoSetAdminInformation()
NET_API_STATUS
NET_API_FUNCTION
IISEnumerateUsers(
IN LPWSTR Server OPTIONAL,
IN DWORD dwLevel,
IN DWORD dwServiceId,
IN DWORD dwInstance,
OUT PDWORD nRead,
OUT LPBYTE *pBuffer
)
{
NET_API_STATUS status;
GENERIC_INFO_CONTAINER genInfo;
GENERIC_ENUM_STRUCT genStruct;
genInfo.Buffer = NULL;
genInfo.EntriesRead = 0;
genStruct.Container = &genInfo;
genStruct.Level = dwLevel;
RpcTryExcept
{
status = R_IISEnumerateUsers(
Server,
dwServiceId,
dwInstance,
(LPIIS_USER_ENUM_STRUCT)&genStruct
);
if ( genInfo.Buffer != NULL ) {
*pBuffer = (LPBYTE)genInfo.Buffer;
*nRead = genInfo.EntriesRead;
} else {
*pBuffer = NULL;
*nRead = 0;
}
}
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
{
status = RpcExceptionCode();
}
RpcEndExcept
return status;
} // IISEnumerateUsers
NET_API_STATUS
NET_API_FUNCTION
IISDisconnectUser(
IN LPWSTR Server OPTIONAL,
IN DWORD dwServiceId,
IN DWORD dwInstance,
IN DWORD dwIdUser
)
{
NET_API_STATUS status;
RpcTryExcept
{
status = R_IISDisconnectUser(
Server,
dwServiceId,
dwInstance,
dwIdUser
);
}
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
{
status = RpcExceptionCode();
}
RpcEndExcept
return status;
} // IISDisconnectUser
NET_API_STATUS
NET_API_FUNCTION
InitW3CounterStructure(
IN LPWSTR Server OPTIONAL,
OUT LPDWORD lpcbTotalRequired
)
{
NET_API_STATUS status;
RpcTryExcept
{
status = R_InitW3CounterStructure(Server, lpcbTotalRequired);
}
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
{
status = RpcExceptionCode();
}
RpcEndExcept
return status;
} //InitW3CounterStructure
NET_API_STATUS
NET_API_FUNCTION
CollectW3PerfData(
IN LPWSTR Server OPTIONAL,
IN LPWSTR lpValueName,
OUT LPBYTE lppData,
IN OUT LPDWORD lpcbTotalBytes,
OUT LPDWORD lpNumObjectTypes
)
{
NET_API_STATUS status;
RpcTryExcept
{
status = R_CollectW3PerfData(
Server,
lpValueName,
lppData,
lpcbTotalBytes,
lpNumObjectTypes
);
}
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
{
status = RpcExceptionCode();
}
RpcEndExcept
return status;
} //CollectW3PerfData
NET_API_STATUS
NET_API_FUNCTION
W3QueryStatistics2(
IN LPWSTR Server OPTIONAL,
IN DWORD dwLevel,
IN DWORD dwInstance,
IN DWORD dwReserved,
OUT LPBYTE * pBuffer
)
{
NET_API_STATUS status;
*pBuffer = NULL;
RpcTryExcept
{
status = R_W3QueryStatistics2(
Server,
dwLevel,
dwInstance,
dwReserved,
(LPW3_STATISTICS_STRUCT)pBuffer
);
}
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
{
status = RpcExceptionCode();
}
RpcEndExcept
return status;
} // W3QueryStatistics2
NET_API_STATUS
NET_API_FUNCTION
W3ClearStatistics2(
IN LPWSTR Server OPTIONAL,
IN DWORD dwInstance
)
{
NET_API_STATUS status;
RpcTryExcept
{
status = R_W3ClearStatistics2(
Server,
dwInstance
);
}
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
{
status = RpcExceptionCode();
}
RpcEndExcept
return status;
} // W3ClearStatistics2
NET_API_STATUS
NET_API_FUNCTION
FtpQueryStatistics2(
IN LPWSTR Server OPTIONAL,
IN DWORD dwLevel,
IN DWORD dwInstance,
IN DWORD dwReserved,
OUT LPBYTE * pBuffer
)
{
NET_API_STATUS status;
*pBuffer = NULL;
RpcTryExcept
{
status = R_FtpQueryStatistics2(
Server,
dwLevel,
dwInstance,
dwReserved,
(LPFTP_STATISTICS_STRUCT)pBuffer
);
}
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
{
status = RpcExceptionCode();
}
RpcEndExcept
return status;
} // FtpQueryStatistics2
NET_API_STATUS
NET_API_FUNCTION
FtpClearStatistics2(
IN LPWSTR Server OPTIONAL,
IN DWORD dwInstance
)
{
NET_API_STATUS status;
RpcTryExcept
{
status = R_FtpClearStatistics2(
Server,
dwInstance
);
}
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
{
status = RpcExceptionCode();
}
RpcEndExcept
return status;
} // FtpClearStatistics2
#ifndef CHICAGO
DWORD
GetSecret(
IN LPWSTR Server,
IN LPWSTR SecretName,
OUT LPWSTR * ppSecret
)
/*++
Description
Gets the specified LSA secret
Arguments:
Server - Server name (or NULL) secret lives on
SecretName - Name of the LSA secret
ppSecret - Receives an allocated block of memory containing the secret.
Must be freed with LocalFree.
Note:
--*/
{
LSA_HANDLE hPolicy;
UNICODE_STRING * punicodePassword;
UNICODE_STRING unicodeServer;
NTSTATUS ntStatus;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING unicodeSecret;
InitUnicodeString( &unicodeServer,
Server );
//
// Open a policy to the remote LSA
//
InitializeObjectAttributes( &ObjectAttributes,
NULL,
0L,
NULL,
NULL );
ntStatus = LsaOpenPolicy( &unicodeServer,
&ObjectAttributes,
POLICY_ALL_ACCESS,
&hPolicy );
if ( !NT_SUCCESS( ntStatus ) )
return LsaNtStatusToWinError( ntStatus );
InitUnicodeString( &unicodeSecret,
SecretName );
//
// Query the secret value
//
ntStatus = LsaRetrievePrivateData( hPolicy,
&unicodeSecret,
&punicodePassword );
LsaClose( hPolicy );
if ( !NT_SUCCESS( ntStatus ))
return LsaNtStatusToWinError( ntStatus );
*ppSecret = LocalAlloc( LPTR, punicodePassword->Length + sizeof(WCHAR) );
if ( !*ppSecret )
{
RtlZeroMemory( punicodePassword->Buffer,
punicodePassword->MaximumLength );
LsaFreeMemory( (PVOID) punicodePassword );
return ERROR_NOT_ENOUGH_MEMORY;
}
//
// Copy it into the buffer, Length is count of bytes
//
memcpy( *ppSecret,
punicodePassword->Buffer,
punicodePassword->Length );
(*ppSecret)[punicodePassword->Length/sizeof(WCHAR)] = L'\0';
RtlZeroMemory( punicodePassword->Buffer,
punicodePassword->MaximumLength );
LsaFreeMemory( (PVOID) punicodePassword );
return NO_ERROR;
} // GetSecret()
DWORD
SetSecret(
IN LPWSTR Server,
IN LPWSTR SecretName,
IN LPWSTR pSecret,
IN DWORD cbSecret
)
/*++
Description
Sets the specified LSA secret
Arguments:
Server - Server name (or NULL) secret lives on
SecretName - Name of the LSA secret
pSecret - Pointer to secret memory
cbSecret - Size of pSecret memory block
Note:
--*/
{
LSA_HANDLE hPolicy;
UNICODE_STRING unicodePassword;
UNICODE_STRING unicodeServer;
NTSTATUS ntStatus;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING unicodeSecret;
InitUnicodeString( &unicodeServer,
Server );
//
// Initialize the unicode string by hand so we can handle '\0' in the
// string
//
unicodePassword.Buffer = pSecret;
unicodePassword.Length = (USHORT) cbSecret;
unicodePassword.MaximumLength = (USHORT) cbSecret;
//
// Open a policy to the remote LSA
//
InitializeObjectAttributes( &ObjectAttributes,
NULL,
0L,
NULL,
NULL );
ntStatus = LsaOpenPolicy( &unicodeServer,
&ObjectAttributes,
POLICY_ALL_ACCESS,
&hPolicy );
if ( !NT_SUCCESS( ntStatus ) )
return LsaNtStatusToWinError( ntStatus );
//
// Create or open the LSA secret
//
InitUnicodeString( &unicodeSecret,
SecretName );
ntStatus = LsaStorePrivateData( hPolicy,
&unicodeSecret,
&unicodePassword );
LsaClose( hPolicy );
if ( !NT_SUCCESS( ntStatus ))
{
return LsaNtStatusToWinError( ntStatus );
}
return NO_ERROR;
} // SetSecret()
#else // CHICAGO
DWORD
GetSecret(
IN LPWSTR Server,
IN LPWSTR SecretName,
OUT LPWSTR * ppSecret
)
{
return(NO_ERROR);
}
DWORD
SetSecret(
IN LPWSTR Server,
IN LPWSTR SecretName,
IN LPWSTR pSecret,
IN DWORD cbSecret
)
{
return(NO_ERROR);
}
#endif // CHICAGO