Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1524 lines
32 KiB

/*++
Copyright (c) 1991-1992 Microsoft Corporation
Module Name:
SsInit.c
Abstract:
This module contains initialization routines for the NT server
service.
Author:
David Treadwell (davidtr) 6-Mar-1991
Revision History:
ChuckC 20-May-93 Load share remarks from messagefile so it
can be internationalized.
--*/
#include "srvsvcp.h"
#if DBG
#include "srvconfg.h"
#endif
#include "ssdata.h"
#include "ssreg.h"
#include <netevent.h>
#include <lmapibuf.h> // NetApiBufferFree().
#include <netlib.h>
#include <apperr2.h>
#include <debugfmt.h>
#include <tstr.h>
#ifdef _CAIRO_
#include <windows.h>
#include <ole2.h>
#include <tdi.h>
#include <gluon.h>
#include <dsapi.h>
#include <dfsapi.h>
#endif // _CAIRO_
#define SERVICE_REGISTRY_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
#define SERVER_DRIVER_NAME L"Srv"
//
// Internationalizable share remarks.
//
#define NETMSG_DLL TEXT("NETMSG.DLL")
LPWSTR SsDefaultRemark = TEXT("") ; // if all else fails
LPWSTR SsAdminShareRemark = NULL ;
LPWSTR SsIPCShareRemark = NULL ;
LPWSTR SsDiskAdminShareRemark = NULL ;
//
// Forward declarations.
//
NET_API_STATUS
CreateDefaultShares (
VOID
);
VOID
InitializeDefaultData(
VOID
);
VOID
InitializeStrings(
VOID
);
VOID
FreeStrings(
VOID
);
NET_API_STATUS
InitializeServer (
VOID
);
NET_API_STATUS
LoadServer (
VOID
);
VOID
SetServerName (
VOID
);
VOID
SetDomainName (
VOID
);
DWORD
DiscoverDrives (
VOID
);
NET_API_STATUS
TerminateServer (
VOID
);
VOID
UnloadServer (
VOID
);
NET_API_STATUS
SsInitialize (
IN DWORD argc,
IN LPWSTR argv[]
)
/*++
Routine Description:
This routine controls initialization of the server service and
server driver. It sets up server data stored in the server
service, parses the command line parameters in case any data needs
to be changed, and then starts the file server.
Arguments:
argc - the count of command-line arguments.
argv - an array of pointers to the command line arguments.
Return Value:
NET_API_STATUS - results of operation.
--*/
{
NET_API_STATUS error;
//
// Initialize the resource that protects access to global server
// information.
//
SS_ASSERT( !SsServerInfoResourceInitialized );
RtlInitializeResource( &SsServerInfoResource );
//
// We hold this resource while we are doing announcements, and when
// we communicate with the FSD. These ought to be quick operations,
// but it's really unpredictable under load. Indicate to the RTL
// that we really don't know how long it'll take.
//
SsServerInfoResource.Flags |= RTL_RESOURCE_FLAG_LONG_TERM;
SsServerInfoResourceInitialized = TRUE;
//
// Get the internationalizable special share remarks
//
InitializeStrings( );
//
// Initialize the server name list bits list.
//
SsServerNameList = NULL;
IF_DEBUG(INITIALIZATION) {
SS_PRINT(( "SsInitialize: resource initialized.\n" ));
}
//
// Create the event used for termination synchronization.
//
SS_ASSERT( SsTerminationEvent == NULL );
SsTerminationEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
if ( SsTerminationEvent == NULL ) {
error = GetLastError( );
SS_PRINT(( "SsInitialize: CreateEvent failed: %ld\n", error ));
return error;
}
//
// Initialize the server data to its default values stored in
// srvconfg.h.
//
InitializeDefaultData( );
IF_DEBUG(INITIALIZATION) {
SS_PRINT(( "SsInitialize: default data initialized.\n" ));
}
//
// Get the computer name.
//
SetServerName( );
//
// Get the primary domain for this computer.
//
SetDomainName( );
//
// See if we are the top of a DFS tree
//
SsSetDfsRoot();
//
// Verify that the various registry keys under the main server
// service key exist.
//
error = SsCheckRegistry( );
if ( error != NO_ERROR ) {
IF_DEBUG(INITIALIZATION_ERRORS) {
SS_PRINT(( "SsInitialize: SsCheckRegistry failed: %ld\n", error ));
}
return error;
}
IF_DEBUG(INITIALIZATION) {
SS_PRINT(( "SsInitialize: registry keys verified.\n" ));
}
//
// Load server configuration data from the registry.
//
error = SsLoadConfigurationParameters( );
if ( error != NO_ERROR ) {
IF_DEBUG(INITIALIZATION_ERRORS) {
SS_PRINT(( "SsInitialize: SsLoadConfigurationParameters failed: "
"%ld\n", error ));
}
return error;
}
IF_DEBUG(INITIALIZATION) {
SS_PRINT(( "SsInitialize: configuration parameters loaded.\n" ));
}
//
// Parse the command line. This will change server data values as
// specified.
//
error = SsParseCommandLine( argc, argv, TRUE );
if ( error != NO_ERROR ) {
IF_DEBUG(INITIALIZATION_ERRORS) {
SS_PRINT(( "SsInitialize: SsParseCommandLine failed: %ld\n",
error ));
}
return error;
}
IF_DEBUG(INITIALIZATION) {
SS_PRINT(( "SsInitialize: command line parsed.\n" ));
}
//
// Set up the security objects that will be used to validate access
// for APIs.
//
error = SsCreateSecurityObjects( );
if ( error != NO_ERROR ) {
return error;
}
IF_DEBUG(INITIALIZATION) {
SS_PRINT(( "SsInitialize: security initialized.\n" ));
}
//
// Start the file server driver.
//
error = InitializeServer( );
if ( error != NO_ERROR ) {
return error;
}
IF_DEBUG(INITIALIZATION) {
SS_PRINT(( "SsInitialize: server FSP initialized.\n" ));
}
//
// Start XACTSRV, if requested.
//
// *** This must be done AFTER the server driver is started, but
// BEFORE sticky shares are recreated, otherwise downlevel print
// shares are lost.
//
if ( SsData.ServerInfo599.sv599_acceptdownlevelapis ) {
error = XsStartXactsrv( );
if ( error != NO_ERROR ) {
return error;
}
}
//
// Create the default shares needed by the server.
//
error = CreateDefaultShares( );
if ( error != NO_ERROR ) {
return error;
}
IF_DEBUG(INITIALIZATION) {
SS_PRINT(( "SsInitialize: default shares created.\n" ));
}
//
// Complete loading the configuration--sticky shares and transports.
// These must be done after the server FSP has started.
//
error = SsRecreateStickyShares( );
if ( error != NO_ERROR ) {
return error;
}
IF_DEBUG(INITIALIZATION) {
SS_PRINT(( "SsInitialize: sticky shares reloaded.\n" ));
}
#ifndef SRV_PNP_POWER
error = SsBindToTransports( );
if ( error != NO_ERROR ) {
return error;
}
IF_DEBUG(INITIALIZATION) {
SS_PRINT(( "SsInitialize: transports bound.\n" ));
}
#endif
//
// Set information used in server announcements.
//
SsSetExportedServerType( NULL, FALSE, FALSE );
//
// Server initialization was successful.
//
return NO_ERROR;
} // SsInitialize
NET_API_STATUS
SsTerminate (
VOID
)
/*++
Routine Description:
This routine sends the FSCTL_SRV_SHUTDOWN control code to the server
FSD to tell it to terminate its FSP.
Arguments:
None.
Return Value:
None.
--*/
{
NET_API_STATUS error;
PNAME_LIST_ENTRY Service;
PTRANSPORT_LIST_ENTRY Transport;
//
// Shut the server FSD/FSP down.
//
error = TerminateServer( );
//
// Shut down XACTSRV.
//
XsStopXactsrv( );
//
// Delete security objects.
//
SsDeleteSecurityObjects( );
//
// Close the network announcement event.
//
if (SsAnnouncementEvent != NULL) {
CloseHandle( SsAnnouncementEvent );
SsAnnouncementEvent = NULL;
}
//
// Close the local announcement event.
//
if (SsStatusChangedEvent != NULL) {
CloseHandle( SsStatusChangedEvent );
SsStatusChangedEvent = NULL;
}
//
// Close the termination event.
//
if ( SsTerminationEvent != NULL ) {
CloseHandle( SsTerminationEvent );
SsTerminationEvent = NULL;
}
//
// Free up the transport service list.
//
while( SsServerNameList != NULL ) {
PNAME_LIST_ENTRY Service = SsServerNameList;
while( Service->Transports != NULL ) {
PTRANSPORT_LIST_ENTRY Next = Service->Transports->Next;
MIDL_user_free( Service->Transports );
Service->Transports = Next;
}
SsServerNameList = Service->Next;
MIDL_user_free( Service );
}
//
// Delete the server info resource.
//
if ( SsServerInfoResourceInitialized ) {
RtlDeleteResource( &SsServerInfoResource );
SsServerInfoResourceInitialized = FALSE;
}
//
// Free up any string relate memory
//
FreeStrings() ;
return error;
} // SsTerminate
NET_API_STATUS
CreateDefaultShares (
VOID
)
/*++
Routine Description:
This routine sends the NetShareAdd API to the server to add the
default server shares using the data above.
Arguments:
None.
Return Value:
NET_API_STATUS - results of operation.
--*/
{
NET_API_STATUS error;
SHARE_INFO_2 shareInfo;
SHARE_INFO shInfo;
WCHAR diskShareName[3];
WCHAR diskSharePath[4];
ULONG i;
DWORD diskMask;
DWORD diskconfiguration;
//
// Create IPC$.
//
// !!! Need to verify the remarks for these default shares.
//
shareInfo.shi2_netname = IPC_SHARE_NAME;
shareInfo.shi2_type = STYPE_IPC;
shareInfo.shi2_remark = NULL;
shareInfo.shi2_permissions = 0;
shareInfo.shi2_max_uses = SHI_USES_UNLIMITED;
shareInfo.shi2_current_uses = 0;
shareInfo.shi2_path = NULL;
shareInfo.shi2_passwd = NULL;
shInfo.ShareInfo2 = &shareInfo;
error = NetrShareAdd( NULL, 2, &shInfo, NULL );
if ( error != NO_ERROR ) {
IF_DEBUG(INITIALIZATION_ERRORS) {
SS_PRINT(( "CreateDefaultShares: failed to add " FORMAT_LPWSTR
": %X\n", shareInfo.shi2_netname, error ));
}
} else {
IF_DEBUG(INITIALIZATION) {
SS_PRINT(( "CreateDefaultShares: added default share "
FORMAT_LPWSTR "\n", shareInfo.shi2_netname, error ));
}
}
//
// If this is a workstation, and the AutoShareWks key is set to TRUE then
// automatically create the admin$ and drive$ shares.
//
//
// If this is a server, and the AutoShareServer key is set to TRUE then
// automatically create the admin$ and drive$ shares.
//
if( (SsData.ServerInfo598.sv598_producttype == NtProductWinNt &&
SsData.ServerInfo598.sv598_autosharewks) ||
(SsData.ServerInfo598.sv598_producttype != NtProductWinNt &&
SsData.ServerInfo598.sv598_autoshareserver ) ) {
//
// Create ADMIN$.
//
shareInfo.shi2_netname = ADMIN_SHARE_NAME;
shareInfo.shi2_type = STYPE_DISKTREE;
shareInfo.shi2_remark = NULL;
shareInfo.shi2_permissions = 1;
shareInfo.shi2_max_uses = SHI_USES_UNLIMITED;
shareInfo.shi2_current_uses = 0;
shareInfo.shi2_path = NULL;
shareInfo.shi2_passwd = NULL;
error = NetrShareAdd( NULL, 2, &shInfo, NULL );
if ( error != NO_ERROR ) {
IF_DEBUG(INITIALIZATION_ERRORS) {
SS_PRINT(( "CreateDefaultShares: failed to add " FORMAT_LPWSTR
": %X\n", shareInfo.shi2_netname, error ));
}
} else {
IF_DEBUG(INITIALIZATION) {
SS_PRINT(( "CreateDefaultShares: added default share "
FORMAT_LPWSTR "\n", shareInfo.shi2_netname, error ));
}
}
//
// Loop through available drives, creating an admin share for each
// one. Note that we allow "holes" in the drive letter space.
//
diskShareName[0] = 'A';
diskShareName[1] = '$';
diskShareName[2] = '\0';
diskSharePath[0] = diskShareName[0];
diskSharePath[1] = ':';
diskSharePath[2] = '\\';
diskSharePath[3] = '\0';
shareInfo.shi2_netname = diskShareName;
shareInfo.shi2_type = STYPE_DISKTREE;
shareInfo.shi2_remark = SsDiskAdminShareRemark;
shareInfo.shi2_permissions = 1;
shareInfo.shi2_max_uses = SHI_USES_UNLIMITED;
shareInfo.shi2_current_uses = 0;
shareInfo.shi2_path = diskSharePath;
shareInfo.shi2_passwd = NULL;
diskconfiguration = DiscoverDrives();
for ( i = 0, diskMask = 0x80000000;
(i < SRVSVC_MAX_NUMBER_OF_DISKS) && (diskShareName[0] <= 'Z');
i++, diskShareName[0]++, diskSharePath[0]++, diskMask >>= 1 ) {
if ( (diskconfiguration & diskMask) != 0) {
error = NetrShareAdd( NULL, 2, &shInfo, NULL );
if ( error != NO_ERROR ) {
IF_DEBUG(INITIALIZATION_ERRORS) {
SS_PRINT(( "CreateDefaultShares: failed to add "
FORMAT_LPWSTR ": %X\n",
shareInfo.shi2_netname, error ));
}
} else {
IF_DEBUG(INITIALIZATION) {
SS_PRINT(( "CreateDefaultShares: added default share "
FORMAT_LPWSTR "\n",
shareInfo.shi2_netname, error ));
}
}
}
}
}
return NO_ERROR;
} // CreateDefaultShares
DWORD
DiscoverDrives (
VOID
)
/*++
Routine Description:
This routine returns a bit mask representing the local drives present
on the system.
Arguments:
None.
Return Value:
DrivesAvailable - A 32 bit field representing the available drives on
the system. The MSB represents drive A, the next represents drive
B, etc. The extra 6 bits are currently unsed.
--*/
{
WCHAR rootDirPath[4];
WCHAR driveLetter;
DWORD drivesAvailable = 0;
DWORD driveMask = 0x80000000;
UINT driveType;
rootDirPath[1] = ':';
rootDirPath[2] = '\\';
rootDirPath[3] = '\0';
for ( driveLetter = 'A';
driveLetter <= 'Z';
driveLetter++ ) {
rootDirPath[0] = driveLetter;
driveType = SsGetDriveType( rootDirPath );
//
// We only put fixed disk drives into the mask. We used to put
// removables, CD-ROMs, and RAM disks into the list. But this
// list is used for two purposes: creation of X$ shares (for
// backup purposes), and free disk space checking (for admin
// purposes). Neither of these uses applies very well to these
// devices.
//
if ( driveType == DRIVE_FIXED
//|| driveType == DRIVE_REMOVABLE
//|| driveType == DRIVE_CDROM
//|| driveType == DRIVE_RAMDISK
) {
//
// This is a valid drive letter
//
drivesAvailable |= driveMask;
}
//
// Update drive mask for the next drive
//
driveMask /= 2;
}
return drivesAvailable;
}
VOID
InitializeDefaultData(
VOID
)
/*++
Routine Description:
This routine sets up the default data in the server service by using
the values in srvconfg.h.
Arguments:
None.
Return Value:
None.
--*/
{
NET_API_STATUS error;
CSHORT i;
OSVERSIONINFO VersionInformation;
WCHAR szNumber[ sizeof( SsData.szVersionNumber ) / sizeof( WCHAR ) ], *p;
//
// Loop through all the defined fields, setting them as we go.
//
for ( i = 0; SsServerInfoFields[i].FieldName != NULL; i++ ) {
error = SsSetField(
&SsServerInfoFields[i],
&SsServerInfoFields[i].DefaultValue,
FALSE,
NULL
);
SS_ASSERT( error == NO_ERROR );
}
SsData.NumberOfPrintShares = 0;
//
// Get the system version and product name
//
VersionInformation.dwOSVersionInfoSize = sizeof( VersionInformation );
i = GetVersionEx( &VersionInformation );
SS_ASSERT( i == TRUE );
SsData.ServerInfo102.sv102_version_major = VersionInformation.dwMajorVersion;
SsData.ServerInfo102.sv102_version_minor = VersionInformation.dwMinorVersion;
wcscpy( SsData.ServerProductName, SERVER_PRODUCT_NAME );
//
// Convert the version number to a version number string...
//
szNumber[ sizeof( szNumber ) / sizeof( szNumber[0] ) - 1 ] = L'\0';
for( p = &szNumber[ sizeof( szNumber ) / sizeof( szNumber[0] ) - 2 ]; p > &szNumber[0]; p-- ) {
*p = L"0123456789"[ VersionInformation.dwMinorVersion % 10 ];
VersionInformation.dwMinorVersion /= 10;
if( VersionInformation.dwMinorVersion == 0 )
break;
}
*(--p) = L'.';
do {
*(--p) = L"0123456789"[ VersionInformation.dwMajorVersion % 10 ];
VersionInformation.dwMajorVersion /= 10;
} while( VersionInformation.dwMajorVersion && p > &szNumber[0] );
//
// ... and store it in SsData
//
wcscpy( SsData.szVersionNumber, p );
} // InitializeDefaultData
NET_API_STATUS
InitializeServer (
VOID
)
/*++
Routine Description:
This routine sends the FSCTL_SRV_STARTUP control code to the server
FSD to tell it to start and initialize its FSP.
Arguments:
None.
Return Value:
NET_API_STATUS - results of operation.
--*/
{
NET_API_STATUS error;
PSERVER_REQUEST_PACKET srp;
SS_ASSERT( !SsServerFspStarted );
//
// Load the server driver.
//
error = LoadServer( );
//
// Get a handle to the server.
//
error = SsOpenServer( NULL );
if ( error != NO_ERROR ) {
return error;
}
//
// Get an SRP and set it up with the appropriate level.
//
srp = SsAllocateSrp( );
if ( srp == NULL ) {
return ERROR_NOT_ENOUGH_MEMORY;
}
srp->Level = (ULONG)SS_STARTUP_LEVEL;
//
// Pass domain name to the server.
//
RtlInitUnicodeString( &srp->Name1, SsData.LongDomainNameBuffer[0] ?
SsData.LongDomainNameBuffer :
SsData.DomainNameBuffer );
//
// Pass server name to the server.
//
RtlInitUnicodeString( &srp->Name2, SsData.ServerNameBuffer );
//
// Send the request on to the server.
//
error = SsServerFsControl(
NULL,
FSCTL_SRV_STARTUP,
srp,
&SsData.ServerInfo102,
sizeof(SERVER_INFO_102) + sizeof(SERVER_INFO_599) +
sizeof(SERVER_INFO_598)
);
if ( error == NO_ERROR ) {
SsServerFspStarted = TRUE;
}
//
// Free the SRP and return.
//
SsFreeSrp( srp );
return error;
} // InitializeServer
#ifdef SRV_PNP_POWER
NET_API_STATUS
StartPnpNotifications (
VOID
)
/*++
Routine Description:
This routine sends the FSCTL_SRV_BEGIN_PNP_NOTIFICATIONS control code to the server
FSD to tell it to start monitoring transport PNP notifications
Arguments:
None.
Return Value:
NET_API_STATUS - results of operation.
--*/
{
NET_API_STATUS error;
//
// Send the request on to the server.
//
error = SsServerFsControl(
NULL,
FSCTL_SRV_BEGIN_PNP_NOTIFICATIONS,
NULL,
NULL,
0
);
IF_DEBUG(INITIALIZATION) {
if( error != NO_ERROR ) {
SS_PRINT(( "StartPnpNotifications: error %X\n", error ));
}
}
return error;
} // InitializeServer
#endif
NET_API_STATUS
LoadServer (
VOID
)
{
NTSTATUS status;
NET_API_STATUS error;
LPWSTR registryPathBuffer;
UNICODE_STRING registryPath;
ULONG privileges[1];
LPWSTR subString[1];
IF_DEBUG(INITIALIZATION) {
SS_PRINT(( "LoadServer: entered\n" ));
}
registryPathBuffer = (LPWSTR)MIDL_user_allocate(
sizeof(SERVICE_REGISTRY_KEY) +
sizeof(SERVER_DRIVER_NAME)
);
if ( registryPathBuffer == NULL ) {
IF_DEBUG(INITIALIZATION_ERRORS) {
SS_PRINT(( "LoadServer: Unable to allocate memory\n" ));
}
return ERROR_NOT_ENOUGH_MEMORY;
}
privileges[0] = SE_LOAD_DRIVER_PRIVILEGE;
error = NetpGetPrivilege( 1, privileges );
if ( error != NO_ERROR ) {
IF_DEBUG(INITIALIZATION_ERRORS) {
SS_PRINT(( "LoadServer: Unable to enable privilege: %ld\n",
error ));
}
MIDL_user_free( registryPathBuffer );
return error;
}
wcscpy( registryPathBuffer, SERVICE_REGISTRY_KEY );
wcscat( registryPathBuffer, SERVER_DRIVER_NAME );
RtlInitUnicodeString( &registryPath, registryPathBuffer );
status = NtLoadDriver( &registryPath );
MIDL_user_free( registryPathBuffer );
NetpReleasePrivilege( );
if ( status == STATUS_IMAGE_ALREADY_LOADED ) {
status = STATUS_SUCCESS;
}
if ( !NT_SUCCESS(status) ) {
IF_DEBUG(INITIALIZATION_ERRORS) {
SS_PRINT(( "LoadServer: Unable to load driver: %lx\n",
status ));
}
subString[0] = SERVER_DRIVER_NAME;
SsLogEvent(
EVENT_SRV_CANT_LOAD_DRIVER,
1,
subString,
status
);
}
IF_DEBUG(INITIALIZATION) {
SS_PRINT(( "LoadServer: returning\n" ));
}
return RtlNtStatusToDosError(status);
} // LoadServer
NET_API_STATUS
ConvertStringToTransportAddress (
IN PUNICODE_STRING InputName,
OUT CHAR TransportAddress[ MAX_PATH ],
OUT PULONG TransportAddressLength
)
{
OEM_STRING computerName;
if( InputName == NULL || InputName->Length == 0 ) {
RtlCopyMemory( TransportAddress,
SsServerTransportAddress,
SsServerTransportAddressLength );
*TransportAddressLength = SsServerTransportAddressLength;
return NO_ERROR;
}
if( InputName->Length > (MAX_PATH - 1 ) * sizeof( WCHAR ) ) {
return ERROR_INVALID_PARAMETER;
}
//
// Write directly to the output buffer
//
computerName.Buffer = TransportAddress;
computerName.MaximumLength = MAX_PATH;
//
// Convert To Oem Name
//
(VOID) RtlUpcaseUnicodeStringToOemString(
&computerName,
InputName,
FALSE
);
//
// Make sure it is exactly NETBIOS_NAME_LEN characters
//
if( computerName.Length < NETBIOS_NAME_LEN ) {
RtlCopyMemory( TransportAddress + computerName.Length,
" ",
NETBIOS_NAME_LEN - computerName.Length
);
*TransportAddressLength = NETBIOS_NAME_LEN;
} else {
*TransportAddressLength = NETBIOS_NAME_LEN;
}
return NO_ERROR;
} // ConvertStringToTransportAddress
VOID
SetDomainName (
VOID
)
/*++
Routine Description:
Tries to get the Cairo domain. If it can't then:
Calls NetpGetDomainName to determine the domain name the server
should use.
Arguments:
None.
Return Value:
None.
--*/
{
NET_API_STATUS error;
LPWSTR domainName;
#ifdef _CAIRO_
WCHAR szDomainName[MAX_PATH];
DWORD dwSize = MAX_PATH;
if(SUCCEEDED(DSGetDomainName(szDomainName, &dwSize))
&&
(szDomainName[0] == L'\\'))
{
STRCPY( SsData.LongDomainNameBuffer, szDomainName );
}
#endif
//
// Get the domain name.
//
error = NetpGetDomainName( &domainName );
SS_ASSERT( error == NO_ERROR );
//
// Copy the name into our name buffer.
//
STRCPY( SsData.DomainNameBuffer, domainName );
//
// Free the storage allocated by NetpGetComputerName.
//
(VOID)NetApiBufferFree( domainName );
IF_DEBUG(INITIALIZATION) {
SS_PRINT(( "SetDomainName: domain name set to " FORMAT_LPWSTR
"(could be overridden later!)\n",
SsData.DomainNameBuffer ));
}
return;
} // SetDomainName
VOID
SetServerName (
VOID
)
/*++
Routine Description:
Calls NetpGetComputerName to determine the name the server should use
to register itself on the network.
Arguments:
None.
Return Value:
None.
--*/
{
NET_API_STATUS error;
LPWSTR computerName;
//
// Get the computer name.
//
error = NetpGetComputerName( &computerName );
SS_ASSERT( error == NO_ERROR );
//
// Copy the name into our name buffer. This name is returned to
// our apis.
//
STRCPY( SsData.ServerNameBuffer, computerName );
//
// Free the storage allocated by NetpGetComputerName.
//
(void) NetApiBufferFree( computerName );
//
// Uppercase the server name. This name is used for announcements.
//
{
UNICODE_STRING serverName;
SsData.ServerAnnounceName.Length =
serverName.Length =
(USHORT) (STRLEN( SsData.ServerNameBuffer ) * sizeof(WCHAR));
SsData.ServerAnnounceName.MaximumLength =
serverName.MaximumLength =
(USHORT) (serverName.Length + sizeof(WCHAR));
serverName.Buffer = SsData.ServerNameBuffer;
SsData.ServerAnnounceName.Buffer = SsData.AnnounceNameBuffer;
(VOID)RtlUpcaseUnicodeString(
&SsData.ServerAnnounceName,
&serverName,
FALSE
);
//
// Make the server name in Netbios format.
//
error = ConvertStringToTransportAddress(
&serverName,
SsServerTransportAddress,
&SsServerTransportAddressLength
);
SS_ASSERT( error == NO_ERROR );
}
IF_DEBUG(INITIALIZATION) {
SS_PRINT(( "SetServerName: server name set to " FORMAT_LPWSTR
" (could be overridden later!)\n",
SsData.ServerNameBuffer ));
}
return;
} // SetServerName
NET_API_STATUS
TerminateServer (
VOID
)
/*++
Routine Description:
This routine sends the FSCTL_SRV_SHUTDOWN control code to the server
FSD to tell it to shutdown operations.
Arguments:
None.
Return Value:
None.
--*/
{
NET_API_STATUS error = NO_ERROR;
if ( SsServerFspStarted ) {
SsServerFspStarted = FALSE;
//
// Send the request on to the server.
//
error = SsServerFsControl(
NULL,
FSCTL_SRV_SHUTDOWN,
NULL,
NULL,
0
);
if ( (error != NO_ERROR) &&
(error != ERROR_SERVER_HAS_OPEN_HANDLES) ) {
IF_DEBUG(TERMINATION_ERRORS) {
SS_PRINT(( "TerminateServer: FSCTL_SRV_SHUTDOWN failed: %ld\n",
error ));
}
}
//
// Unload the server driver, unless there are other open handles
// to the server. We don't unload the driver in this case
// because the driver won't actually go away until the
// additional handles are closed, so the driver will not be
// fully unloaded. This would cause a subsequent server startup
// to fail.
//
if ( error != ERROR_SERVER_HAS_OPEN_HANDLES ) {
IF_DEBUG(TERMINATION) {
SS_PRINT(( "TerminateServer: Unloading server\n" ));
}
UnloadServer( );
}
}
//
// Close the handle to the server.
//
SsCloseServer( );
return error;
} // TerminateServer
VOID
UnloadServer (
VOID
)
{
NTSTATUS status;
NET_API_STATUS error;
LPWSTR registryPathBuffer;
UNICODE_STRING registryPath;
ULONG privileges[1];
LPWSTR subString[1];
registryPathBuffer = (LPWSTR)MIDL_user_allocate(
sizeof(SERVICE_REGISTRY_KEY) +
sizeof(SERVER_DRIVER_NAME)
);
if ( registryPathBuffer == NULL ) {
IF_DEBUG(TERMINATION_ERRORS) {
SS_PRINT(( "UnloadServer: Unable to allocate memory\n" ));
}
return;
}
privileges[0] = SE_LOAD_DRIVER_PRIVILEGE;
error = NetpGetPrivilege( 1, privileges );
if ( error != NO_ERROR ) {
IF_DEBUG(TERMINATION_ERRORS) {
SS_PRINT(( "UnloadServer: Unable to enable privilege: %ld\n",
error ));
}
MIDL_user_free( registryPathBuffer );
return;
}
wcscpy( registryPathBuffer, SERVICE_REGISTRY_KEY );
wcscat( registryPathBuffer, SERVER_DRIVER_NAME );
RtlInitUnicodeString( &registryPath, registryPathBuffer );
status = NtUnloadDriver( &registryPath );
MIDL_user_free( registryPathBuffer );
NetpReleasePrivilege( );
if ( !NT_SUCCESS(status) ) {
IF_DEBUG(TERMINATION_ERRORS) {
SS_PRINT(( "UnloadServer: Unable to unload driver: %lx\n",
status ));
}
subString[0] = SERVER_DRIVER_NAME;
SsLogEvent(
EVENT_SRV_CANT_UNLOAD_DRIVER,
1,
subString,
status
);
}
return;
} // UnloadServer
VOID
InitializeStrings(
VOID
)
/*++
Routine Description:
Retrieve internationalizable strings from NETMSG.DLL. They
are used for share comments for IPC$, ADMIN$, C$, etc.
Routine does not report any errors. If there are problems,
the strings will be empty ones.
FreeStrings should be called to free the memory allocated
by format message and the
Arguments:
None.
Return Value:
None.
--*/
{
DWORD dwRet, dwFlags ;
HMODULE hModule ;
//
// init the strings to the default empty remark.
//
SsAdminShareRemark = SsDefaultRemark ;
SsIPCShareRemark = SsDefaultRemark ;
SsDiskAdminShareRemark = SsDefaultRemark ;
//
// load NETMSG.DLL - if we cannot, just return.
//
hModule = LoadLibrary(NETMSG_DLL) ;
if(!hModule)
return ;
//
// hit FormatMessage 3 times for the real thing...
//
dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE ;
dwRet = FormatMessage(dwFlags,
hModule,
APE2_SERVER_IPC_SHARE_REMARK,
0,
(LPWSTR) &SsIPCShareRemark,
1,
NULL) ;
if (dwRet == 0)
SsIPCShareRemark = SsDefaultRemark ;
dwRet = FormatMessage(dwFlags,
hModule,
APE2_SERVER_ADMIN_SHARE_REMARK,
0,
(LPWSTR) &SsAdminShareRemark,
1,
NULL) ;
if (dwRet == 0)
SsAdminShareRemark = SsDefaultRemark ;
dwRet = FormatMessage(dwFlags,
hModule,
APE2_SERVER_DISK_ADMIN_SHARE_REMARK,
0,
(LPWSTR) &SsDiskAdminShareRemark,
1,
NULL) ;
if (dwRet == 0)
SsDiskAdminShareRemark = SsDefaultRemark ;
FreeLibrary(hModule) ;
}
VOID
FreeStrings(
VOID
)
/*++
Routine Description:
Free the memory used by server comment strings (allocated by
FormatMessage).
Arguments:
None.
Return Value:
None.
--*/
{
//
// as long as the strings do not point to the default (static data),
// free them.
//
if (SsAdminShareRemark && SsAdminShareRemark != SsDefaultRemark)
LocalFree(SsAdminShareRemark) ;
SsAdminShareRemark = SsDefaultRemark ;
if (SsIPCShareRemark && SsIPCShareRemark != SsDefaultRemark)
LocalFree(SsIPCShareRemark) ;
SsIPCShareRemark = SsDefaultRemark ;
if (SsDiskAdminShareRemark && SsDiskAdminShareRemark != SsDefaultRemark)
LocalFree(SsDiskAdminShareRemark) ;
SsDiskAdminShareRemark = SsDefaultRemark ;
}