/*++ Copyright (c) 1991-1992 Microsoft Corporation Module Name: SrvStub.C Abstract: These are the server service API RPC client stubs. Author: Dan Lafferty (danl) 06-Feb-1991 Environment: User Mode - Win32 Revision History: 06-Feb-1991 Danl Created 07-Jun-1991 JohnRo Added downlevel support for NetServer APIs. Added NET_API_FUNCTION where necessary. 15-Jul-1991 RFirth Integrated RxNetShare routines into NetShare stubs 24-Jul-1991 JohnRo Implement downlevel NetConnectionEnum. Try using macros. 25-Jul-1991 JohnRo Quiet DLL stub debug output. Use NetRpc.h macros for NetServer APIs. 06-Sep-1991 JohnRo Downlevel NetFile APIs. 25-Sep-1991 JohnRo Use NetRpc.h macros for all other APIs, to quiet normal debug output. 07-Oct-1991 JohnRo RAID 3210: "NET FILE 0" causes assertion. (Was bug in NetFileGetInfo DLL stub.) 16-Oct-1991 JohnRo Implement remote NetSession APIs. Changed LPSTR to LPTSTR. 07-Nov-1991 JohnRo RAID 4186: assert in RxNetShareAdd and other DLL stub problems. 12-Nov-1991 JohnRo APIs in this file need SERVICE_SERVER started to run locally. 04-Dec-1991 JohnRo Change RxNetServerSetInfo() to new-style interface. Fixed bug in calling RxNetShareSetInfo(). 09-May-1992 rfirth Resurrect NetStatisticsGet as NetServerStatisticsGet 5-Aug-1992 JohnsonA Added new share info level 502 to enable passing of security descriptors. 08-Sep-1992 JohnRo Fix NET_API_FUNCTION references. --*/ // // INCLUDES // #include // DbgPrint prototype #include // DbgPrint #include // DataTypes and runtime APIs #include // generated by the MIDL complier #include // GENERIC_ENUM_STRUCT #include // NET_API_STATUS #include // (needed by netrpc.h) #include // (needed by netrpc.h) #include // (needed by netrpc.h) #include // NetError codes #include // NetpIsServiceStarted(). #include // NetpNtStatusToApiStatus #include // NET_REMOTE_ macros. #include // SUPPORTS_RPC #include // Required by rxsess.h. #include // Needed by . #include // RxNetConnection routines. #include // RxNetFile routines. #include // RxNetRemoteTOD #include // RxNetServer routines. #include // RxNetSession routines. #include // RxNetShare routines #include // NetpIsRemote #include // NetServerStatisticsGet private prototype #include // RxNetStatisticsGet (down-level) #include // prototypes for Netps canonicalization functions #include // prototypes for down-level canonicalization functions #include #include "cscp.h" #define SET_ERROR_PARAMETER(a) \ if ( ARGUMENT_PRESENT( parm_err ) ) { *parm_err = a; } NET_API_STATUS NET_API_FUNCTION NetCharDevControl ( IN LPCWSTR servername, IN LPCWSTR devname, IN DWORD opcode ) /*++ Routine Description: This is the DLL entrypoint for NetCharDevControl. Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. devname --A pointer to the ASCIIZ string containing the name of the device to control opcode --Control opcode: currently defined are: CHARDEV_CLOSE for the device closed. Return Value: --*/ { NET_API_STATUS apiStatus; NET_REMOTE_TRY_RPC apiStatus = NetrCharDevControl ( (LPWSTR)servername, (LPWSTR)devname, opcode); NET_REMOTE_RPC_FAILED( "NetCharDevControl", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) apiStatus = ERROR_NOT_SUPPORTED; NET_REMOTE_END return(apiStatus); } // NetCharDevControl NET_API_STATUS NET_API_FUNCTION NetCharDevEnum ( IN LPCWSTR servername, IN DWORD level, OUT LPBYTE *bufptr, IN DWORD prefmaxlen, OUT LPDWORD entriesread, OUT LPDWORD totalentries, IN OUT LPDWORD resume_handle ) /*++ Routine Description: This is the DLL entrypoint for NetCharDevEnum. Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. level --Level of information required. 0 and 1 are valid. bufptr --On return a pointer to the return information structure is returned in the address pointed to by bufptr. prefmaxlen --Prefered maximum length of returned data (in 8-bit bytes). 0xffffffff specifies no limit. entriesread --On return the actual enumerated element count is located in the DWORD pointed to by entriesread. totalentries --On return the total entries available to be enumerated is located in the DWORD pointed to by totalentries. resumehandle --On return, a resume handle is stored in the DWORD pointed to by resumehandle, and is used to continue an existing character device search. The handle should be zero on the first call and left unchanged for subsequent calls. If resumehandle is NULL, then no resume handle is stored.. Return Value: --*/ { NET_API_STATUS apiStatus; GENERIC_INFO_CONTAINER genericInfoContainer; GENERIC_ENUM_STRUCT infoStruct; genericInfoContainer.Buffer = NULL; genericInfoContainer.EntriesRead = 0; infoStruct.Container = &genericInfoContainer; infoStruct.Level = level; NET_REMOTE_TRY_RPC apiStatus = NetrCharDevEnum ( (LPWSTR)servername, (LPCHARDEV_ENUM_STRUCT)&infoStruct, prefmaxlen, totalentries, resume_handle); if (genericInfoContainer.Buffer != NULL) { *bufptr = (LPBYTE)genericInfoContainer.Buffer; *entriesread = genericInfoContainer.EntriesRead; } else { *bufptr = NULL; *entriesread = 0; } NET_REMOTE_RPC_FAILED( "NetCharDevEnum", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) apiStatus = ERROR_NOT_SUPPORTED; NET_REMOTE_END return(apiStatus); } // NetCharDevEnum NET_API_STATUS NET_API_FUNCTION NetCharDevGetInfo ( IN LPCWSTR servername, IN LPCWSTR devname, IN DWORD level, OUT LPBYTE *bufptr ) /*++ Routine Description: This is the DLL entrypoint for NetCharDevGetInfo. Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. devname --A pointer to the ASCIIZ string containing the name of the device to return information on. level --Level of information required. 0 and 1 are valid. bufptr --On return a pointer to the return information structure is returned in the address pointed to by bufptr. Return Value: --*/ { NET_API_STATUS apiStatus; *bufptr = NULL; // Must be NULL so RPC knows to till it in. NET_REMOTE_TRY_RPC apiStatus = NetrCharDevGetInfo ( (LPWSTR)servername, (LPWSTR)devname, level, (LPCHARDEV_INFO) bufptr); NET_REMOTE_RPC_FAILED( "NetCharDevGetInfo", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) apiStatus = ERROR_NOT_SUPPORTED; NET_REMOTE_END return(apiStatus); } // NetCharDevGetInfo NET_API_STATUS NET_API_FUNCTION NetCharDevQEnum ( IN LPCWSTR servername, IN LPCWSTR username, IN DWORD level, OUT LPBYTE *bufptr, IN DWORD prefmaxlen, OUT LPDWORD entriesread, OUT LPDWORD totalentries, IN OUT LPDWORD resume_handle ) /*++ Routine Description: This is the DLL entrypoint for NetCharDevQEnum. Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. username --A pointer to an ASCIIZ string containing an a username for the active queues of interest. This parameter is optional, if NULL then all device queues are enumerated. level --Level of information required. 0 and 1 are valid. bufptr --On return a pointer to the return information structure is returned in the address pointed to by bufptr. prefmaxlen --Prefered maximum length of returned data (in 8-bit bytes). 0xffffffff specifies no limit. entriesread --On return the actual enumerated element count is located in the DWORD pointed to by entriesread. totalentries --On return the total entries available to be enumerated is located in the DWORD pointed to by totalentries. resumehandle --On return, a resume handle is stored in the DWORD pointed to by resumehandle, and is used to continue an existing character device queue search. The handle should be Return Value: --*/ { NET_API_STATUS apiStatus; GENERIC_INFO_CONTAINER genericInfoContainer; GENERIC_ENUM_STRUCT infoStruct; genericInfoContainer.Buffer = NULL; genericInfoContainer.EntriesRead = 0; infoStruct.Container = &genericInfoContainer; infoStruct.Level = level; NET_REMOTE_TRY_RPC apiStatus = NetrCharDevQEnum ( (LPWSTR)servername, (LPWSTR)username, (LPCHARDEVQ_ENUM_STRUCT) &infoStruct, prefmaxlen, totalentries, resume_handle); if (genericInfoContainer.Buffer != NULL) { *bufptr = (LPBYTE)genericInfoContainer.Buffer; *entriesread = genericInfoContainer.EntriesRead; } else { *bufptr = NULL; *entriesread = 0; } NET_REMOTE_RPC_FAILED( "NetCharDevQEnum", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) apiStatus = ERROR_NOT_SUPPORTED; NET_REMOTE_END return(apiStatus); } // NetCharDevQEnum NET_API_STATUS NET_API_FUNCTION NetCharDevQGetInfo ( IN LPCWSTR servername, IN LPCWSTR queuename, IN LPCWSTR username, IN DWORD level, OUT LPBYTE *bufptr ) /*++ Routine Description: This is the DLL entrypoint for NetCharDevQGetInfo. Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. queuename --A pointer to an ASCIIZ string containing the name of the queue to return information on. username --A pointer to an ASCIIZ string containing the username of the a user whose job of of interest for the cq1_numahead count. level --Level of information required. 0 and 1 are valid. bufptr --On return a pointer to the return information structure is returned in the address pointed to by bufptr. Return Value: --*/ { NET_API_STATUS apiStatus; *bufptr = NULL; // Must be NULL so RPC knows to till it in. NET_REMOTE_TRY_RPC apiStatus = NetrCharDevQGetInfo ( (LPWSTR)servername, (LPWSTR)queuename, (LPWSTR)username, level, (LPCHARDEVQ_INFO) bufptr); NET_REMOTE_RPC_FAILED( "NetCharDevQGetInfo", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) apiStatus = ERROR_NOT_SUPPORTED; NET_REMOTE_END return(apiStatus); } // NetCharDevQGetInfo NET_API_STATUS NET_API_FUNCTION NetCharDevQPurge ( IN LPCWSTR servername, IN LPCWSTR queuename ) /*++ Routine Description: This is the DLL entrypoint for NetCharDevQPurge. Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. queuename --A pointer to an ASCIIZ string containing the name of the queue to be purged. Return Value: --*/ { NET_API_STATUS apiStatus; NET_REMOTE_TRY_RPC apiStatus = NetrCharDevQPurge ( (LPWSTR)servername, (LPWSTR)queuename); NET_REMOTE_RPC_FAILED( "NetCharDevQPurge", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) apiStatus = ERROR_NOT_SUPPORTED; NET_REMOTE_END return(apiStatus); } // NetCharDevQPurge NET_API_STATUS NET_API_FUNCTION NetCharDevQPurgeSelf ( IN LPCWSTR servername, IN LPCWSTR queuename, IN LPCWSTR computername ) /*++ Routine Description: This is the DLL entrypoint for NetCharDevQPurgeSelf. Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. queuename --A pointer to an ASCIIZ string containing the name of the queue to be purged of pending entries from the specified computer. Return Value: --*/ { NET_API_STATUS apiStatus; NET_REMOTE_TRY_RPC apiStatus = NetrCharDevQPurgeSelf ( (LPWSTR)servername, (LPWSTR)queuename, (LPWSTR)computername); NET_REMOTE_RPC_FAILED( "NetCharDevQPurgeSelf", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) apiStatus = ERROR_NOT_SUPPORTED; NET_REMOTE_END return(apiStatus); } // NetCharDevQPurgeSelf NET_API_STATUS NET_API_FUNCTION NetCharDevQSetInfo ( IN LPCWSTR servername, IN LPCWSTR queuename, IN DWORD level, IN LPBYTE buf, OUT LPDWORD parm_err ) /*++ Routine Description: This is the DLL entrypoint for NetCharDevQSetInfo. Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. queuename --A pointer to an ASCIIZ string containing the name of the queue to set information on. level --Level of information to set. buf --A pointer to a buffer containing the chardev information. If parmnum is non zero then the buffer contains only the appropriate data for the specific element. If parmnum is zero, then the buffer contains the whole chardev information structure. parm_err --Optional pointer to a DWORD to return the index of the first parameter in error when ERROR_INVALID_PARAMETER is returned. If NULL the parameter is not returned on error. Return Value: --*/ { NET_API_STATUS apiStatus; NET_REMOTE_TRY_RPC apiStatus = NetrCharDevQSetInfo ( (LPWSTR)servername, (LPWSTR)queuename, level, (LPCHARDEVQ_INFO) &buf, parm_err); NET_REMOTE_RPC_FAILED( "NetCharDevQSetInfo", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) apiStatus = ERROR_NOT_SUPPORTED; NET_REMOTE_END return(apiStatus); } // NetCharDevQSetInfo NET_API_STATUS NET_API_FUNCTION NetConnectionEnum ( IN LPTSTR servername, IN LPTSTR qualifier, IN DWORD level, OUT LPBYTE *bufptr, IN DWORD prefmaxlen, OUT LPDWORD entriesread, OUT LPDWORD totalentries, IN OUT LPDWORD resume_handle ) /*++ Routine Description: This is the DLL entrypoint for NetConnectionEnum. Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. qualifier --A pointer to an ASCIIZ string containing a sharename or computername for the connections of interest. If it is a sharename, then all the connections made to that sharename are listed. If it is a computername (i.e. it starts with two backslash characters), then NetConnectionEnum lists all connections made from that computer to the server specified. level --Level of information required. 0 and 1 are valid. bufptr --On return a pointer to the return information structure is returned in the address pointed to by bufptr. prefmaxlen --Prefered maximum length of returned data (in 8-bit bytes). 0xffffffff specifies no limit. entriesread --On return the actual enumerated element count is located in the DWORD pointed to by entriesread. Return Value: --*/ { NET_API_STATUS apiStatus; GENERIC_INFO_CONTAINER genericInfoContainer; GENERIC_ENUM_STRUCT infoStruct; genericInfoContainer.Buffer = NULL; genericInfoContainer.EntriesRead = 0; infoStruct.Container = &genericInfoContainer; infoStruct.Level = level; NET_REMOTE_TRY_RPC apiStatus = NetrConnectionEnum ( servername, qualifier, (LPCONNECT_ENUM_STRUCT)&infoStruct, prefmaxlen, totalentries, resume_handle); if (genericInfoContainer.Buffer != NULL) { *bufptr = (LPBYTE)genericInfoContainer.Buffer; *entriesread = genericInfoContainer.EntriesRead; } else { *bufptr = NULL; *entriesread = 0; } NET_REMOTE_RPC_FAILED( "NetConnectionEnum", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) // // Try call to downlevel. // apiStatus = RxNetConnectionEnum( servername, qualifier, level, bufptr, prefmaxlen, entriesread, totalentries, resume_handle ); NET_REMOTE_END return(apiStatus); } // NetConnectionEnum NET_API_STATUS NET_API_FUNCTION NetFileClose ( IN LPTSTR servername, IN DWORD fileid ) /*++ Routine Description: This is the DLL entrypoint for NetFileClose. Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. fileid --The fileid of the opened resource instance to be closed. Return Value: --*/ { NET_API_STATUS apiStatus; NET_REMOTE_TRY_RPC apiStatus = NetrFileClose ( servername, fileid); NET_REMOTE_RPC_FAILED( "NetFileClose", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) apiStatus = RxNetFileClose ( servername, fileid); NET_REMOTE_END return(apiStatus); } NET_API_STATUS NET_API_FUNCTION NetFileEnum ( IN LPTSTR servername, IN LPTSTR basepath, IN LPTSTR username, IN DWORD level, OUT LPBYTE *bufptr, IN DWORD prefmaxlen, OUT LPDWORD entriesread, OUT LPDWORD totalentries, IN OUT PDWORD_PTR resume_handle ) /*++ Routine Description: This is the DLL entrypoint for NetFileEnum. Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. basepath --A pointer to an ASCIIZ string containing a qualifier for the returned information. If NULL then all open resources are enumerated, else only resources which have basepath as a prefix are enumerated. username --A pointer to an ASCIIZ string that specifies the name of the user. If not NULL, username serves as a qualifier to the ennumeration. The files returned are limited to those that have usernames matching the qualifier. If username is NULL, no username qualifier is used. level --Level of information required. 2 and 3 are valid. bufptr --On return a pointer to the return information structure is returned in the address pointed to by bufptr. prefmaxlen --Prefered maximum length of returned data (in 8-bit bytes). 0xffffffff specifies no limit. entriesread --On return the actual enumerated element count is located in the DWORD pointed to by entriesread. totalentries --On return the total entries available to be enumerated is located in the DWORD pointed to by totalentries. resumehandle --On return, a resume handle is stored in the DWORD pointed to by resumehandle, and is used to continue an existing file search. The handle should be zero on the first call and left unchanged for subsequent calls. If resumehandle is NULL, then no resume handle is stored.. Return Value: --*/ { NET_API_STATUS apiStatus; GENERIC_INFO_CONTAINER genericInfoContainer; GENERIC_ENUM_STRUCT infoStruct; genericInfoContainer.Buffer = NULL; genericInfoContainer.EntriesRead = 0; infoStruct.Container = &genericInfoContainer; infoStruct.Level = level; NET_REMOTE_TRY_RPC // // NetrFileEnum's resume_handle parm is a true index that will remain // 32 bits wide for on-the-wire compatibility. Thus, the cast to // (PDWORD) here works. // apiStatus = NetrFileEnum ( servername, basepath, username, (LPFILE_ENUM_STRUCT) &infoStruct, prefmaxlen, totalentries, (PDWORD)resume_handle); if (genericInfoContainer.Buffer != NULL) { *bufptr = (LPBYTE)genericInfoContainer.Buffer; *entriesread = genericInfoContainer.EntriesRead; } else { *bufptr = NULL; *entriesread = 0; } NET_REMOTE_RPC_FAILED( "NetFileEnum", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) apiStatus = RxNetFileEnum( servername, basepath, username, level, bufptr, prefmaxlen, entriesread, totalentries, resume_handle); NET_REMOTE_END return(apiStatus); } // NetFileEnum NET_API_STATUS NET_API_FUNCTION NetFileGetInfo ( IN LPTSTR servername, IN DWORD fileid, IN DWORD level, OUT LPBYTE *bufptr ) /*++ Routine Description: This is the DLL entrypoint for NetFileGetInfo. Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. fileid --The fileid of the open resource to return information on. The fileid value must be that returned in a previous enumeration call. level --Level of information required. 2 and 3 are valid. bufptr --On return a pointer to the return information structure is returned in the address pointed to by bufptr. Return Value: --*/ { NET_API_STATUS apiStatus; *bufptr = NULL; // Must be NULL so RPC knows to fill it in. NET_REMOTE_TRY_RPC apiStatus = NetrFileGetInfo ( servername, fileid, level, (LPFILE_INFO) bufptr); NET_REMOTE_RPC_FAILED( "NetFileGetInfo", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) apiStatus = RxNetFileGetInfo ( servername, fileid, level, bufptr); NET_REMOTE_END return(apiStatus); } // NetFileGetInfo NET_API_STATUS NET_API_FUNCTION NetSessionDel ( IN LPTSTR servername, IN LPTSTR clientname, IN LPTSTR username ) /*++ Routine Description: This is the DLL entrypoint for NetSessionDel. Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. clientname --A pointer to an ASCIIZ string containing the computername of the client to disconnect. username --A pointer to an ASCIIZ string containing the name of the user whose session is to be terminated. A NULL indicates that all users' sessions from the computername specified are to be terminated. Return Value: --*/ { NET_API_STATUS apiStatus; NET_REMOTE_TRY_RPC apiStatus = NetrSessionDel ( servername, clientname, username); NET_REMOTE_RPC_FAILED("NetSessionDel", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER ) // // Call downlevel version of the API. // apiStatus = RxNetSessionDel ( servername, clientname, username); NET_REMOTE_END return(apiStatus); } // NetSessionDel NET_API_STATUS NET_API_FUNCTION NetSessionEnum ( IN LPTSTR servername, IN LPTSTR clientname, IN LPTSTR username, IN DWORD level, OUT LPBYTE *bufptr, IN DWORD prefmaxlen, OUT LPDWORD entriesread, OUT LPDWORD totalentries, IN OUT LPDWORD resume_handle ) /*++ Routine Description: This is the DLL entrypoint for NetSessionEnum. Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. clientname --A pointer to an ASCIIZ string containing the name of the computer session for which information is to be returned. A NULL pointer or string specifies that all computer sessions on the server are to be ennumerated. username --A pointer to an ASCIIZ string containing the name of the the user for which to ennumerate the sessions. A NULL pointer or string specifies that sessions for all users are to be ennumerated. level --Level of information required. 0, 1, 2 and 10 are valid. bufptr --On return a pointer to the return information structure is returned in the address pointed to by bufptr. prefmaxlen --Prefered maximum length of returned data (in 8-bit bytes). 0xffffffff specifies no limit. entriesread --On return the actual enumerated element count is located in the DWORD pointed to by entriesread. totalentries --On return the total entries available to be enumerated is located in the DWORD pointed to by totalentries. resumehandle --On return, a resume handle is stored in the DWORD pointed to by resumehandle, and is used to continue an existing session search. The handle should be zero on the first call and left unchanged for subsequent calls. If resumehandle is NULL, then no resume handle is stored. Return Value: --*/ { NET_API_STATUS apiStatus; GENERIC_INFO_CONTAINER genericInfoContainer; GENERIC_ENUM_STRUCT infoStruct; genericInfoContainer.Buffer = NULL; genericInfoContainer.EntriesRead = 0; infoStruct.Container = &genericInfoContainer; infoStruct.Level = level; NET_REMOTE_TRY_RPC apiStatus = NetrSessionEnum ( servername, clientname, username, (PSESSION_ENUM_STRUCT) &infoStruct, prefmaxlen, totalentries, resume_handle); if (genericInfoContainer.Buffer != NULL) { *bufptr = (LPBYTE)genericInfoContainer.Buffer; *entriesread = genericInfoContainer.EntriesRead; } else { *bufptr = NULL; *entriesread = 0; } NET_REMOTE_RPC_FAILED("NetSessionEnum", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER ) // // Call downlevel version of the API. // apiStatus = RxNetSessionEnum ( servername, clientname, username, level, bufptr, prefmaxlen, entriesread, totalentries, resume_handle); NET_REMOTE_END return(apiStatus); } // NetSessionEnum NET_API_STATUS NET_API_FUNCTION NetSessionGetInfo ( IN LPTSTR servername, IN LPTSTR clientname, IN LPTSTR username, IN DWORD level, OUT LPBYTE *bufptr ) /*++ Routine Description: This is the DLL entrypoint for NetSessionEnum. Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. clientname --A pointer to an ASCIIZ string containing the name of the computer session for which information is to be returned. This field cannot be NULL. username --A pointer to an ASCIIZ string containing the name of the the user for which to ennumerate the sessions. This field cannot be NULL. level --Level of information required. 0, 1, 2 and 10 are valid. bufptr --On return a pointer to the return information structure is returned in the address pointed to by bufptr. Return Value: --*/ { NET_API_STATUS apiStatus; GENERIC_INFO_CONTAINER genericInfoContainer; GENERIC_ENUM_STRUCT infoStruct; DWORD totalentries; if ( clientname == NULL || username == NULL ) { return ERROR_INVALID_PARAMETER; } genericInfoContainer.Buffer = NULL; genericInfoContainer.EntriesRead = 0; infoStruct.Container = &genericInfoContainer; infoStruct.Level = level; NET_REMOTE_TRY_RPC apiStatus = NetrSessionEnum ( servername, clientname, username, (PSESSION_ENUM_STRUCT) &infoStruct, (DWORD)-1, &totalentries, NULL); if (genericInfoContainer.Buffer != NULL) { *bufptr = (LPBYTE)genericInfoContainer.Buffer; } else { *bufptr = NULL; if ( apiStatus == NO_ERROR ) { return NERR_ClientNameNotFound; } } NET_REMOTE_RPC_FAILED("NetSessionGetInfo", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER ) // // Call downlevel version of the API. // apiStatus = RxNetSessionGetInfo ( servername, clientname, username, level, bufptr); NET_REMOTE_END return(apiStatus); } // NetSessionGetInfo NET_API_STATUS NET_API_FUNCTION NetShareAdd ( IN LPTSTR servername, IN DWORD level, IN LPBYTE buf, OUT LPDWORD parm_err ) /*++ Routine Description: This is the DLL entrypoint for NetShareAdd. Only levels 2 and 502 are allowed. Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. level --Level of information provided. Must be 2. buf --A pointer to a buffer containing the share information structure. parm_err --Optional pointer to a DWORD to return the index of the first parameter in error when ERROR_INVALID_PARAMETER is returned. If NULL the parameter is not returned on error. Return Value: --*/ { NET_API_STATUS apiStatus; NTSTATUS status; ULONG SDLength = 0; ULONG oldSDLength; PSECURITY_DESCRIPTOR securityDescriptor = NULL; PSECURITY_DESCRIPTOR oldSecurityDescriptor = NULL; // // do the parameter validation here - this way we only need do it once and // in a centralized place // if (level != 2 && level != 502) { return ERROR_INVALID_LEVEL; } NET_REMOTE_TRY_RPC if ( level == 502 ) { PSHARE_INFO_502 shi502 = (LPSHARE_INFO_502) buf; // // Save this. We need to restore this later. // oldSecurityDescriptor = shi502->shi502_security_descriptor; oldSDLength = shi502->shi502_reserved; if ( oldSecurityDescriptor != NULL ) { if ( !RtlValidSecurityDescriptor( oldSecurityDescriptor) ) { SET_ERROR_PARAMETER( SHARE_FILE_SD_PARMNUM ); return ERROR_INVALID_PARAMETER; } // // Make a self relative security descriptor for use in the // RPC call.. // status = RtlMakeSelfRelativeSD( oldSecurityDescriptor, NULL, &SDLength ); if (status != STATUS_BUFFER_TOO_SMALL) { SET_ERROR_PARAMETER( SHARE_FILE_SD_PARMNUM ); return(ERROR_INVALID_PARAMETER); } else { securityDescriptor = MIDL_user_allocate( SDLength ); if ( securityDescriptor == NULL) { return ERROR_NOT_ENOUGH_MEMORY; } else { // // make an appropriate self-relative security descriptor // status = RtlMakeSelfRelativeSD( oldSecurityDescriptor, (PSECURITY_DESCRIPTOR) securityDescriptor, &SDLength ); if ( !NT_SUCCESS(status) ) { MIDL_user_free( securityDescriptor ); SET_ERROR_PARAMETER( SHARE_FILE_SD_PARMNUM ); return(ERROR_INVALID_PARAMETER); } shi502->shi502_security_descriptor = securityDescriptor; shi502->shi502_reserved = SDLength; } } } else { shi502->shi502_reserved = 0; } } apiStatus = NetrShareAdd ( servername, level, (LPSHARE_INFO) &buf, parm_err); if ( securityDescriptor != NULL ) { // // restore old values // PSHARE_INFO_502 shi502 = (LPSHARE_INFO_502) buf; shi502->shi502_security_descriptor = oldSecurityDescriptor; shi502->shi502_reserved = oldSDLength; MIDL_user_free( securityDescriptor ); } NET_REMOTE_RPC_FAILED( "NetShareAdd", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) // // Call downlevel server. // if ( level != 502 ) { apiStatus = RxNetShareAdd( servername, 2, buf, parm_err ); } else { apiStatus = ERROR_NOT_SUPPORTED; } NET_REMOTE_END return(apiStatus); } // NetShareAdd NET_API_STATUS NET_API_FUNCTION NetShareCheck ( IN LPTSTR servername, IN LPTSTR device, OUT LPDWORD type ) /*++ Routine Description: This is the DLL entrypoint for NetShareCheck Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. device --A pointer to an ASCIIZ string containing the name of the device to check for shared access. type --On return the address pointed to by the type parameter contains the type of share the device is offered with. This field is only set if success was returned. Return Value: --*/ { NET_API_STATUS apiStatus; if (!(device && *device) || !type) { return ERROR_INVALID_PARAMETER; } NET_REMOTE_TRY_RPC apiStatus = NetrShareCheck ( servername, device, type); NET_REMOTE_RPC_FAILED( "NetShareCheck", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) // // Call downlevel server. // apiStatus = RxNetShareCheck(servername, device, type); NET_REMOTE_END return(apiStatus); } // NetShareCheck NET_API_STATUS NET_API_FUNCTION NetShareDel ( IN LPTSTR servername, IN LPTSTR netname, IN DWORD reserved ) /*++ Routine Description: This is the DLL entrypoint for NetShareDel. Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. netname --A pointer to an ASCIIZ string containing the netname of the share to delete. reserved --Reserved, must be zero. Return Value: --*/ { NET_API_STATUS apiStatus; BOOL committingIpcDelete = FALSE; SHARE_DEL_HANDLE handle; BOOL tryDownLevel = FALSE; if ( !netname || (*netname == 0) || reserved ) { return ERROR_INVALID_PARAMETER; } RpcTryExcept { if ( STRICMP( netname, TEXT("IPC$") ) != 0 ) { apiStatus = NetrShareDel( servername, netname, reserved ); } else { apiStatus = NetrShareDelStart( servername, netname, reserved, &handle ); if ( apiStatus == NERR_Success ) { committingIpcDelete = TRUE; apiStatus = NetrShareDelCommit( &handle ); } } } RpcExcept ( 1 ) { RPC_STATUS rpcStatus; rpcStatus = RpcExceptionCode( ); if ( committingIpcDelete && (rpcStatus == RPC_S_CALL_FAILED) ) { apiStatus = NERR_Success; } else { apiStatus = NetpHandleRpcFailure( "NetShareDel", rpcStatus, servername, SERVICE_SERVER, NET_REMOTE_FLAG_NORMAL, &tryDownLevel ); } } RpcEndExcept if (apiStatus == NERR_TryDownLevel) { tryDownLevel = TRUE; } if ( tryDownLevel ) { // // Call downlevel server. // // note: push value 0 instead of real reserved // apiStatus = RxNetShareDel(servername, netname, 0); } return apiStatus; } // NetShareDel NET_API_STATUS NET_API_FUNCTION NetShareDelSticky ( IN LPTSTR servername, IN LPTSTR netname, IN DWORD reserved ) /*++ Routine Description: This is the DLL entrypoint for NetShareDelSticky. Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. netname --A pointer to an ASCIIZ string containing the netname of the share to delete. reserved --Reserved, must be zero. Return Value: --*/ { NET_API_STATUS apiStatus; if (!(netname && *netname) || reserved) { return ERROR_INVALID_PARAMETER; } NET_REMOTE_TRY_RPC apiStatus = NetrShareDelSticky ( servername, netname, reserved); NET_REMOTE_RPC_FAILED( "NetShareDelSticky", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) // // No downlevel call. // apiStatus = ERROR_NOT_SUPPORTED; NET_REMOTE_END return(apiStatus); } // NetShareDelSticky NET_API_STATUS NET_API_FUNCTION NetShareEnum ( IN LPTSTR servername, IN DWORD level, OUT LPBYTE *bufptr, IN DWORD prefmaxlen, OUT LPDWORD entriesread, OUT LPDWORD totalentries, IN OUT LPDWORD resume_handle ) /*++ Routine Description: This is the DLL entrypoint for NetShareEnum Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. level --Level of information required. 0, 1 and 2 are valid. bufptr --On return a pointer to the return information structure is returned in the address pointed to by bufptr. prefmaxlen --Prefered maximum length of returned data (in 8-bit bytes). 0xffffffff specifies no limit. entriesread --On return the actual enumerated element count is located in the DWORD pointed to by entriesread. totalentries --On return the total entries available to be enumerated is located in the DWORD pointed to by totalentries. resumehandle --On return, a resume handle is stored in the DWORD pointed to by resumehandle, and is used to continue an existing share search. The handle should be zero on the first call and left unchanged for subsequent calls. If resumehandle is NULL, then no resume handle is stored.. Return Value: --*/ { NET_API_STATUS apiStatus; GENERIC_INFO_CONTAINER genericInfoContainer; GENERIC_ENUM_STRUCT infoStruct; // // check the caller's parameters // *totalentries = *entriesread = 0; *bufptr = NULL; if ( (level > 2) && (level != 501) && (level != 502) ) { return ERROR_INVALID_LEVEL; } genericInfoContainer.Buffer = NULL; genericInfoContainer.EntriesRead = 0; infoStruct.Container = &genericInfoContainer; infoStruct.Level = level; NET_REMOTE_TRY_RPC apiStatus = NetrShareEnum ( servername, (LPSHARE_ENUM_STRUCT) &infoStruct, prefmaxlen, totalentries, resume_handle); if (genericInfoContainer.Buffer != NULL) { *bufptr = (LPBYTE)genericInfoContainer.Buffer; *entriesread = genericInfoContainer.EntriesRead; } else { *bufptr = NULL; *entriesread = 0; } NET_REMOTE_RPC_FAILED( "NetShareEnum", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) // // Call downlevel server. // if ( level != 502 && level != 501 ) { apiStatus = RxNetShareEnum(servername, level, bufptr, prefmaxlen, entriesread, totalentries, resume_handle); } else { apiStatus = ERROR_NOT_SUPPORTED; } NET_REMOTE_END // // If we haven't gotten anything, and the server is offline, // return the offline share state // if( ( *bufptr == NULL || *entriesread == 0 ) && ARGUMENT_PRESENT( servername ) && CSCIsServerOffline( servername ) ) { NET_API_STATUS cscStatus; cscStatus = CSCNetShareEnum( servername, level, bufptr, entriesread, totalentries ); if( cscStatus == NERR_Success ) { apiStatus = cscStatus; } } return(apiStatus); } // NetShareEnum NET_API_STATUS NET_API_FUNCTION NetShareEnumSticky ( IN LPTSTR servername, IN DWORD level, OUT LPBYTE *bufptr, IN DWORD prefmaxlen, OUT LPDWORD entriesread, OUT LPDWORD totalentries, IN OUT LPDWORD resume_handle ) /*++ Routine Description: This is the DLL entrypoint for NetShareEnumSticky Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. level --Level of information required. 0, 1 and 2 are valid. bufptr --On return a pointer to the return information structure is returned in the address pointed to by bufptr. prefmaxlen --Prefered maximum length of returned data (in 8-bit bytes). 0xffffffff specifies no limit. entriesread --On return the actual enumerated element count is located in the DWORD pointed to by entriesread. totalentries --On return the total entries available to be enumerated is located in the DWORD pointed to by totalentries. resumehandle --On return, a resume handle is stored in the DWORD pointed to by resumehandle, and is used to continue an existing share search. The handle should be zero on the first call and left unchanged for subsequent calls. If resumehandle is NULL, then no resume handle is stored.. Return Value: --*/ { NET_API_STATUS apiStatus; GENERIC_INFO_CONTAINER genericInfoContainer; GENERIC_ENUM_STRUCT infoStruct; // // check the caller's parameters // *totalentries = *entriesread = 0; *bufptr = NULL; if ( (level > 2) && (level != 501) && (level != 502) ) { return ERROR_INVALID_LEVEL; } genericInfoContainer.Buffer = NULL; genericInfoContainer.EntriesRead = 0; infoStruct.Container = &genericInfoContainer; infoStruct.Level = level; NET_REMOTE_TRY_RPC apiStatus = NetrShareEnumSticky ( servername, (LPSHARE_ENUM_STRUCT) &infoStruct, prefmaxlen, totalentries, resume_handle); if (genericInfoContainer.Buffer != NULL) { *bufptr = (LPBYTE)genericInfoContainer.Buffer; *entriesread = genericInfoContainer.EntriesRead; } else { *bufptr = NULL; *entriesread = 0; } NET_REMOTE_RPC_FAILED( "NetShareEnum", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) // // No downlevel support // apiStatus = ERROR_NOT_SUPPORTED; NET_REMOTE_END return(apiStatus); } // NetShareEnumSticky NET_API_STATUS NET_API_FUNCTION NetShareGetInfo ( IN LPTSTR servername, IN LPTSTR netname, IN DWORD level, OUT LPBYTE *bufptr ) /*++ Routine Description: NetShareGetInfo Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. netname --A pointer to an ASCIIZ string containing the netname of the share to return information on. level --Level of information required. 0, 1 and 2 are valid. bufptr --On return a pointer to the return information structure is returned in the address pointed to by bufptr. Return Value: --*/ { NET_API_STATUS apiStatus; if (bufptr == NULL) { return ERROR_INVALID_PARAMETER; } *bufptr = NULL; // Must be NULL so RPC knows to fill it in. if ( (level > 2) && (level != 501) && (level != 502) && (level != 1005) ) { return ERROR_INVALID_LEVEL; } if (!(netname && *netname)) { return ERROR_INVALID_PARAMETER; } NET_REMOTE_TRY_RPC apiStatus = NetrShareGetInfo ( servername, netname, level, (LPSHARE_INFO) bufptr); NET_REMOTE_RPC_FAILED( "NetShareGetInfo", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) // // Call downlevel server. // if( level == 0 || level == 1 || level == 2 ) { apiStatus = RxNetShareGetInfo(servername, netname, level, bufptr); } else { apiStatus = ERROR_NOT_SUPPORTED; } NET_REMOTE_END if( *bufptr == NULL && ARGUMENT_PRESENT( servername ) && ARGUMENT_PRESENT( netname ) && CSCIsServerOffline( servername) ) { NET_API_STATUS cscStatus; cscStatus = CSCNetShareGetInfo ( servername, netname, level, bufptr ); if( cscStatus == NERR_Success ) { apiStatus = cscStatus; } } return(apiStatus); } // NetShareGetInfo NET_API_STATUS NET_API_FUNCTION NetShareSetInfo ( IN LPTSTR servername, IN LPTSTR netname, IN DWORD level, IN LPBYTE buf, OUT LPDWORD parm_err ) /*++ Routine Description: This is the DLL entrypoint for NetShareSetInfo Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. netname --A pointer to an ASCIIZ string containing the netname of the share to set information on. level --Level of information to set. buf --A pointer to a buffer containing the share information. If parmnum is non zero then the buffer contains only the appropriate data for the specific element. parm_err --Optional pointer to a DWORD to return the index of the first parameter in error when ERROR_INVALID_PARAMETER is returned. If NULL the parameter is not returned on error. Return Value: --*/ { NET_API_STATUS apiStatus; NTSTATUS status; ULONG sdLength = 0; ULONG oldSdLength; PSECURITY_DESCRIPTOR securityDescriptor = NULL; PSECURITY_DESCRIPTOR oldSecurityDescriptor = NULL; LPSHARE_INFO_1501 shi1501 = NULL; NET_REMOTE_TRY_RPC // // If the info level can change the security descriptor, get // the necessary information. // // *** Note that this code expects the layout of the reserved // and security_descriptor fields in the 502 struct to // match the 1501 struct. // if ( level == 502 ) { if (buf == NULL) { SET_ERROR_PARAMETER(PARM_ERROR_UNKNOWN); return ERROR_INVALID_PARAMETER; } shi1501 = (LPSHARE_INFO_1501)&((LPSHARE_INFO_502)buf)->shi502_reserved; } else if ( level == SHARE_FILE_SD_INFOLEVEL ) { shi1501 = (LPSHARE_INFO_1501)buf; } if ( shi1501 != NULL ) { oldSdLength = shi1501->shi1501_reserved; oldSecurityDescriptor = shi1501->shi1501_security_descriptor; if ( oldSecurityDescriptor != NULL ) { // // Make a self relative security descriptor for use in the // RPC call. // if ( !RtlValidSecurityDescriptor( oldSecurityDescriptor) ) { SET_ERROR_PARAMETER( SHARE_FILE_SD_PARMNUM ); return ERROR_INVALID_PARAMETER; } status = RtlMakeSelfRelativeSD( oldSecurityDescriptor, NULL, &sdLength ); if ( status != STATUS_BUFFER_TOO_SMALL ) { SET_ERROR_PARAMETER( SHARE_FILE_SD_PARMNUM ); return ERROR_INVALID_PARAMETER; } else { securityDescriptor = MIDL_user_allocate( sdLength ); if ( securityDescriptor == NULL) { return ERROR_NOT_ENOUGH_MEMORY; } else { // // Make an appropriate self-relative security // descriptor. // status = RtlMakeSelfRelativeSD( oldSecurityDescriptor, securityDescriptor, &sdLength ); if ( !NT_SUCCESS(status) ) { MIDL_user_free( securityDescriptor ); SET_ERROR_PARAMETER( SHARE_FILE_SD_PARMNUM ); return ERROR_INVALID_PARAMETER; } shi1501->shi1501_reserved = sdLength; shi1501->shi1501_security_descriptor = securityDescriptor; } } } else { shi1501->shi1501_reserved = 0; } } apiStatus = NetrShareSetInfo( servername, netname, level, (LPSHARE_INFO) &buf, parm_err); if ( shi1501 != NULL ) { // // restore old values // shi1501->shi1501_reserved = oldSdLength; shi1501->shi1501_security_descriptor = oldSecurityDescriptor; MIDL_user_free( securityDescriptor ); } NET_REMOTE_RPC_FAILED( "NetShareSetInfo", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) // // Call downlevel server. // if ( level != 502 && level != 501 && level != SHARE_FILE_SD_INFOLEVEL && level != 1005 ) { apiStatus = RxNetShareSetInfo( servername, netname, level, buf, parm_err); } else { apiStatus = ERROR_NOT_SUPPORTED; } NET_REMOTE_END return(apiStatus); } // NetShareSetInfo NET_API_STATUS NET_API_FUNCTION NetServerDiskEnum ( IN LPTSTR servername, IN DWORD level, OUT LPBYTE *bufptr, IN DWORD prefmaxlen, OUT LPDWORD entriesread, OUT LPDWORD totalentries, IN OUT LPDWORD resume_handle ) /*++ Routine Description: This is the DLL entrypoint for NetServerDiskEnum. Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. level --Level of information required. 0 is the only valid level. bufptr --On return a pointer to the return information structure is returned in the address pointed to by bufptr. prefmaxlen --Prefered maximum length of returned data (in 8-bit bytes). 0xffffffff specifies no limit. entriesread --On return the actual enumerated element count is located in the DWORD pointed to by entriesread. totalentries --On return the total entries available to be enumerated is located in the DWORD pointed to by totalentries resumehandle --On return, a resume handle is stored in the DWORD pointed to by resumehandle, and is used to continue an existing server disk search. The handle should be zero on the first call and left unchanged for subsequent calls. If resumehandle is NULL, then no resume handle is stored.. Return Value: --*/ { NET_API_STATUS apiStatus; DISK_ENUM_CONTAINER diskEnumContainer; diskEnumContainer.Buffer = NULL; NET_REMOTE_TRY_RPC apiStatus = NetrServerDiskEnum ( servername, level, &diskEnumContainer, prefmaxlen, totalentries, resume_handle); if (diskEnumContainer.Buffer != NULL) { *bufptr = (LPBYTE)diskEnumContainer.Buffer; } else { *bufptr = NULL; } if (diskEnumContainer.EntriesRead > 0) { // // We must subtract out the extra count that we added so // that RPC would buffer the extra NUL at the end of the list. // *entriesread = diskEnumContainer.EntriesRead - 1; } else { *entriesread = 0; } NET_REMOTE_RPC_FAILED( "NetServerDiskEnum", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) // // Call downlevel version of the API. // apiStatus = RxNetServerDiskEnum( servername, level, bufptr, prefmaxlen, entriesread, totalentries, resume_handle); NET_REMOTE_END return(apiStatus); } // NetServerDiskEnum NET_API_STATUS NET_API_FUNCTION NetServerGetInfo ( IN LPTSTR servername, IN DWORD level, OUT LPBYTE *bufptr ) /*++ Routine Description: This is the DLL entrypoint for NetServerGetInfo Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. level --Level of information required. 100, 101 and 102 are valid for all platforms. 302, 402, 403, 502 are valid for the appropriate platform. bufptr --On return a pointer to the return information structure is returned in the address pointed to by bufptr. Return Value: --*/ { NET_API_STATUS apiStatus; *bufptr = NULL; // Must be NULL so RPC knows to fill it in. NET_REMOTE_TRY_RPC apiStatus = NetrServerGetInfo ( servername, level, (LPSERVER_INFO) bufptr); NET_REMOTE_RPC_FAILED( "NetServerGetInfo", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) // // Call downlevel version of the API. // apiStatus = RxNetServerGetInfo ( servername, level, bufptr); NET_REMOTE_END return(apiStatus); } // NetServerGetInfo NET_API_STATUS NET_API_FUNCTION NetServerSetInfo ( IN LPTSTR servername, IN DWORD level, IN LPBYTE buf, OUT LPDWORD parm_err ) /*++ Routine Description: This is the DLL entrypoint for NetServerSetInfo. Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. level --Level of information to set. buf --A pointer to a buffer containing the server information. If parmnum is non zero then the buffer contains only the appropriate data for the specific element. parm_err --Optional pointer to a DWORD to return the index of the first parameter in error when ERROR_INVALID_PARAMETER is returned. If NULL the parameter is not returned on error. Return Value: --*/ { NET_API_STATUS apiStatus; NET_REMOTE_TRY_RPC apiStatus = NetrServerSetInfo ( servername, level, (LPSERVER_INFO ) &buf, parm_err); NET_REMOTE_RPC_FAILED( "NetServerSetInfo", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) // // Call downlevel server. // apiStatus = RxNetServerSetInfo( servername, level, buf, parm_err); NET_REMOTE_END return(apiStatus); } // NetServerSetInfo NET_API_STATUS NET_API_FUNCTION NetServerStatisticsGet ( IN LPTSTR servername, IN DWORD level, IN DWORD options, OUT LPBYTE *bufptr ) /*++ Routine Description: This is the DLL entrypoint for NetStatisticsGet. Arguments: servername --Points to an ASCIIZ string that contains the name of the server on which to execute NetStatisticsGet. A NULL pointer or NULL string specifies the local computer. level --Specifies the level of detail requested; must be 0. options --Specifies the options flags. Bit(s) Meaning 0 Clear statistics. 1-31 Reserved; must be 0. bufptr --On return a pointer to the returned information is returned in the address pointed to by bufptr. Return Value: --*/ { NET_API_STATUS apiStatus; *bufptr = NULL; // Must be NULL so RPC knows to fill it in. NET_REMOTE_TRY_RPC apiStatus = NetrServerStatisticsGet ( servername, SERVICE_SERVER, level, options, (LPSTAT_SERVER_0 *) bufptr); NET_REMOTE_RPC_FAILED( "NetServerStatisticsGet", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) // // RPC call didn't work - try down-level routine // apiStatus = RxNetStatisticsGet( servername, SERVICE_SERVER, level, options, bufptr ); NET_REMOTE_END return(apiStatus); } // NetServerStatisticsGet NET_API_STATUS NET_API_FUNCTION NetServerTransportAdd ( IN LPTSTR servername, IN DWORD level, IN LPBYTE bufptr ) /*++ Routine Description: This is the DLL entrypoint for NetServerTransportAdd Arguments: Return Value: --*/ { NET_API_STATUS apiStatus; NET_REMOTE_TRY_RPC apiStatus = NetrServerTransportAdd ( servername, level, (LPSERVER_TRANSPORT_INFO_0) bufptr); NET_REMOTE_RPC_FAILED( "NetServerTransportAdd", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) // // No downlevel call. // apiStatus = ERROR_NOT_SUPPORTED; NET_REMOTE_END return(apiStatus); } // NetServerTransportAdd NET_API_STATUS NET_API_FUNCTION NetServerTransportDelEx ( IN LPTSTR servername, IN DWORD level, IN LPBYTE bufptr ) /*++ Routine Description: This is the DLL entrypoint for NetServerTransportAdd Arguments: Return Value: --*/ { NET_API_STATUS apiStatus; NET_REMOTE_TRY_RPC apiStatus = NetrServerTransportDelEx ( servername, level, (LPTRANSPORT_INFO) bufptr); NET_REMOTE_RPC_FAILED( "NetServerTransportDel", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) // // No downlevel call. // apiStatus = ERROR_NOT_SUPPORTED; NET_REMOTE_END // Around the Win2K/NT4 time frame a bug was introduced for TransportDel with // level other than 0. In these cases, the buffer was cast instead of marshalled // correctly over RPC. This means that Level 1 never worked anyway. To fix this, // we added a new RPC interface that supports all the other levels. However, downlevel // servers will not support this interface. In these cases, we call back with the TRUE // level 0 interface to satisfy backwards compatibility if( apiStatus == RPC_S_PROCNUM_OUT_OF_RANGE ) { apiStatus = NetServerTransportDel( servername, 0, bufptr ); } return(apiStatus); } // NetServerTransportDel NET_API_STATUS NET_API_FUNCTION NetServerTransportDel ( IN LPTSTR servername, IN DWORD level, IN LPBYTE bufptr ) /*++ Routine Description: This is the DLL entrypoint for NetServerTransportAdd Arguments: Return Value: --*/ { NET_API_STATUS apiStatus; if( level == 0 ) { NET_REMOTE_TRY_RPC apiStatus = NetrServerTransportDel ( servername, level, (LPSERVER_TRANSPORT_INFO_0) bufptr); NET_REMOTE_RPC_FAILED( "NetServerTransportDel", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) // // No downlevel call. // apiStatus = ERROR_NOT_SUPPORTED; NET_REMOTE_END } else { // If they want level 1, we need to use the new RPC interface. See // the comment in the TransportDelEx code above apiStatus = NetServerTransportDelEx( servername, level, bufptr ); } return(apiStatus); } // NetServerTransportDel NET_API_STATUS NET_API_FUNCTION NetServerTransportEnum ( IN LPTSTR servername, IN DWORD level, OUT LPBYTE *bufptr, IN DWORD prefmaxlen, OUT LPDWORD entriesread, OUT LPDWORD totalentries, IN OUT LPDWORD resume_handle ) /*++ Routine Description: This is the DLL entrypoint for NetServerTransportEnum Arguments: Return Value: --*/ { NET_API_STATUS apiStatus; GENERIC_INFO_CONTAINER genericInfoContainer; GENERIC_ENUM_STRUCT infoStruct; genericInfoContainer.Buffer = NULL; genericInfoContainer.EntriesRead = 0; infoStruct.Container = &genericInfoContainer; infoStruct.Level = level; NET_REMOTE_TRY_RPC apiStatus = NetrServerTransportEnum ( servername, (LPSERVER_XPORT_ENUM_STRUCT) &infoStruct, prefmaxlen, totalentries, resume_handle); if (genericInfoContainer.Buffer != NULL) { *bufptr = (LPBYTE)genericInfoContainer.Buffer; *entriesread = genericInfoContainer.EntriesRead; } else { *bufptr = NULL; *entriesread = 0; } NET_REMOTE_RPC_FAILED( "NetServerTransportEnum", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) // // No downlevel call. // apiStatus = ERROR_NOT_SUPPORTED; NET_REMOTE_END return(apiStatus); } // NetServerTransportEnum NET_API_STATUS NET_API_FUNCTION NetRemoteTOD ( IN LPCWSTR servername, OUT LPBYTE *bufptr ) /*++ Routine Description: This is the DLL entrypoint for NetRemoteTOD Arguments: servername - name of the server on which the API so to be executed. bufptr - the location where the address of the buffer allocated for the time-of-day information is placed. Return Value: NERR_SUCCESS if there was no error. Otherwise, the error code is returned. --*/ { NET_API_STATUS apiStatus; // // Call API // *bufptr = NULL; // Must be NULL so RPC knows to fill it in. NET_REMOTE_TRY_RPC apiStatus = NetrRemoteTOD ( (LPWSTR)servername, (TIME_OF_DAY_INFO **) bufptr); NET_REMOTE_RPC_FAILED( "NetRemoteTOD", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_TIMESOURCE ) apiStatus = RxNetRemoteTOD ( (LPWSTR)servername, (LPBYTE *) bufptr); NET_REMOTE_END return(apiStatus); } NET_API_STATUS I_NetServerSetServiceBitsEx ( IN LPWSTR ServerName, IN LPWSTR EmulatedServerName OPTIONAL, IN LPTSTR TransportName OPTIONAL, IN DWORD ServiceBitsOfInterest, IN DWORD ServiceBits, IN DWORD UpdateImmediately ) /*++ Routine Description: This is the DLL entrypoint for I_NetServerSetServiceBitsEx. This routine sets the value of the Server Type as sent in server announcement messages. It is an internal API used only by the service controller. Arguments: ServerName - Used by RPC to direct the call. This API may only be issued locally. This is enforced by the client stub. EmulatedServerName - the name server using for accepting connections on the network and for announcements. If null, use the priamary server name. TransportName - the name of one of the transports the server is bound on. If null, set the bits for all the transports. ServiceBitsOfInterest - a mask indicating which bits are significant in 'ServiceBits' ServiceBits - Bits (preassigned to various components by Microsoft) indicating which services are active. This field is not interpreted by the server service. Return Value: NET_API_STATUS - NO_ERROR or ERROR_NOT_SUPPORTED. --*/ { NET_API_STATUS apiStatus; DWORD localOrRemote; // // Don't let this API go remote. // if ((ServerName != NULL) && (*ServerName != '\0')) { apiStatus = NetpIsRemote(ServerName, &localOrRemote, NULL, 0); if (apiStatus != NERR_Success) { return apiStatus; } if (localOrRemote == ISREMOTE) { return ERROR_NOT_SUPPORTED; } } // // Do the call. // NET_REMOTE_TRY_RPC apiStatus = I_NetrServerSetServiceBitsEx ( ServerName, EmulatedServerName, TransportName, ServiceBitsOfInterest, ServiceBits, UpdateImmediately); NET_REMOTE_RPC_FAILED( "I_NetServerSetServiceBitsEx", ServerName, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) // // No downlevel call. // apiStatus = ERROR_NOT_SUPPORTED; NET_REMOTE_END return(apiStatus); } // I_NetServerSetServiceBitsEx NET_API_STATUS I_NetServerSetServiceBits ( IN LPTSTR servername, IN LPTSTR transportname, IN DWORD servicebits, IN DWORD updateimmediately ) /*++ Routine Description: This is the DLL entrypoint for I_NetServerSetServiceBits. This routine sets the value of the Server Type as sent in server announcement messages. It is an internal API used only by the service controller. Arguments: ServerName - Used by RPC to direct the call. This API may only be issued locally. This is enforced by the client stub. ServiceBits - Bits (preassigned to various components by Microsoft) indicating which services are active. This field is not interpreted by the server service. Return Value: NET_API_STATUS - NO_ERROR or ERROR_NOT_SUPPORTED. --*/ { NET_API_STATUS apiStatus; DWORD localOrRemote; // // Don't let this API go remote. // if ((servername != NULL) && (*servername != '\0')) { apiStatus = NetpIsRemote(servername, &localOrRemote, NULL, 0); if (apiStatus != NERR_Success) { return apiStatus; } if (localOrRemote == ISREMOTE) { return ERROR_NOT_SUPPORTED; } } // // Do the call. // NET_REMOTE_TRY_RPC apiStatus = I_NetrServerSetServiceBits ( servername, transportname, servicebits, updateimmediately); // // This API is called by the Service Controller only. Don't let // the failure path call any SCM APIs since that may deadlock // services.exe in the loopback. // NET_REMOTE_RPC_FAILED( "I_NetServerSetServiceBits", servername, apiStatus, NET_REMOTE_FLAG_SVC_CTRL, SERVICE_SERVER) // // No downlevel call. // apiStatus = ERROR_NOT_SUPPORTED; NET_REMOTE_END return(apiStatus); } // I_NetServerSetServiceBits // // Netps canonicalization functions. These are essentially private functions // and are called from the API stubs in canonapi.c. The canonicalization // functions have to be usable locally without going via the server service // hence they live in NETAPI.DLL, but call local functions in NETLIB if the // ServerName parameter is NULL (or designates the local machine). If the // ServerName parameter is not NULL and designates a remote computer then the // RPC function (here) will be called, hence the remote server must be // running in order to make remote canonicalization requests // NET_API_STATUS NET_API_FUNCTION NetpsNameCanonicalize( IN LPTSTR ServerName, IN LPTSTR Name, OUT LPTSTR Outbuf, IN DWORD OutbufLen, IN DWORD NameType, IN DWORD Flags ) /*++ Routine Description: Canonicalizes a name Arguments: ServerName - where to run this API Name - name to canonicalize Outbuf - where to put canonicalized name OutbufLen - length of Outbuf NameType - type of name to canonicalize Flags - control flags Return Value: NET_API_STATUS --*/ { NET_API_STATUS apiStatus; NET_REMOTE_TRY_RPC apiStatus = NetprNameCanonicalize(ServerName, Name, Outbuf, OutbufLen, NameType, Flags ); NET_REMOTE_RPC_FAILED("NetpsNameCanonicalize", ServerName, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) // // RPC call didn't work - try down-level routine // apiStatus = RxNetpNameCanonicalize(ServerName, Name, Outbuf, OutbufLen, NameType, Flags ); NET_REMOTE_END return apiStatus; } LONG NET_API_FUNCTION NetpsNameCompare( IN LPTSTR ServerName, IN LPTSTR Name1, IN LPTSTR Name2, IN DWORD NameType, IN DWORD Flags ) /*++ Routine Description: Compares two names. Must be of same type Arguments: ServerName - where to run this API Name1 - 1st name to compare Name2 - 2nd NameType - type of names Flags - control flags Return Value: LONG --*/ { NET_API_STATUS apiStatus; NET_REMOTE_TRY_RPC apiStatus = NetprNameCompare(ServerName, Name1, Name2, NameType, Flags); NET_REMOTE_RPC_FAILED("NetpsNameCompare", ServerName, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) // // RPC call didn't work - try down-level routine // apiStatus = RxNetpNameCompare(ServerName, Name1, Name2, NameType, Flags); NET_REMOTE_END return apiStatus; } NET_API_STATUS NET_API_FUNCTION NetpsNameValidate( IN LPTSTR ServerName, IN LPTSTR Name, IN DWORD NameType, IN DWORD Flags ) /*++ Routine Description: Validates a name - checks whether a name of a certain type conforms to canonicalization rules for that name type. Canonicalization rules mean character set, name syntax and length Arguments: ServerName - where to perform this function Name - name to validate NameType - what type of name it is Flags - MBZ Return Value: NET_API_STATUS --*/ { NET_API_STATUS apiStatus; NET_REMOTE_TRY_RPC apiStatus = NetprNameValidate(ServerName, Name, NameType, Flags); NET_REMOTE_RPC_FAILED("NetpsNameValidate", ServerName, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) // // RPC call didn't work - try down-level routine // apiStatus = RxNetpNameValidate(ServerName, Name, NameType, Flags); NET_REMOTE_END return apiStatus; } NET_API_STATUS NET_API_FUNCTION NetpsPathCanonicalize( IN LPTSTR ServerName, IN LPTSTR PathName, OUT LPTSTR Outbuf, IN DWORD OutbufLen, IN LPTSTR Prefix OPTIONAL, IN OUT LPDWORD PathType, IN DWORD Flags ) /*++ Routine Description: Canonicalizes a directory path or a device name Arguments: ServerName - where to run this API PathName - path to canonicalize Outbuf - where to write the canonicalized version OutbufLen - length of Outbuf in bytes Prefix - optional prefix which will be prepended to Path PathType - the type of path to canonicalize. May be different at output Flags - control flags Return Value: NET_API_STATUS --*/ { NET_API_STATUS apiStatus; NET_REMOTE_TRY_RPC apiStatus = NetprPathCanonicalize(ServerName, PathName, (LPBYTE)Outbuf, OutbufLen, Prefix, PathType, Flags ); NET_REMOTE_RPC_FAILED("NetpsPathCanonicalize", ServerName, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) // // RPC call didn't work - try down-level routine // apiStatus = RxNetpPathCanonicalize(ServerName, PathName, Outbuf, OutbufLen, Prefix, PathType, Flags ); NET_REMOTE_END return apiStatus; } LONG NET_API_FUNCTION NetpsPathCompare( IN LPTSTR ServerName, IN LPTSTR PathName1, IN LPTSTR PathName2, IN DWORD PathType, IN DWORD Flags ) /*++ Routine Description: Compares two paths. The paths are assumed to be of the same type Arguments: ServerName - where to run this API PathName1 - 1st path to compare PathName2 - 2nd PathType - types of paths Flags - control flags Return Value: LONG --*/ { NET_API_STATUS apiStatus; NET_REMOTE_TRY_RPC apiStatus = NetprPathCompare(ServerName, PathName1, PathName2, PathType, Flags ); NET_REMOTE_RPC_FAILED("NetpsPathCompare", ServerName, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) // // RPC call didn't work - try down-level routine // apiStatus = RxNetpPathCompare(ServerName, PathName1, PathName2, PathType, Flags ); NET_REMOTE_END return apiStatus; } NET_API_STATUS NET_API_FUNCTION NetpsPathType( IN LPTSTR ServerName, IN LPTSTR PathName, OUT LPDWORD PathType, IN DWORD Flags ) /*++ Routine Description: Determines the type of a path Arguments: ServerName - where to run this API PathName - to find type of PathType - returned path type Flags - control flags Return Value: NET_API_STATUS --*/ { NET_API_STATUS apiStatus; NET_REMOTE_TRY_RPC apiStatus = NetprPathType(ServerName, PathName, PathType, Flags); NET_REMOTE_RPC_FAILED("NetpsPathType", ServerName, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) // // RPC call didn't work - try down-level routine // apiStatus = RxNetpPathType(ServerName, PathName, PathType, Flags); NET_REMOTE_END return apiStatus; } NET_API_STATUS NET_API_FUNCTION NetServerTransportAddEx ( IN LPTSTR servername, IN DWORD level, IN LPBYTE bufptr ) /*++ Routine Description: This is the DLL entrypoint for NetServerTransportAddEx. It functions just like NetServerTransportAdd, but it supports level 1 as well as 0 --*/ { NET_API_STATUS apiStatus; NET_REMOTE_TRY_RPC apiStatus = NetrServerTransportAddEx ( servername, level, (LPTRANSPORT_INFO) bufptr); NET_REMOTE_RPC_FAILED( "NetServerTransportAddEx", servername, apiStatus, NET_REMOTE_FLAG_NORMAL, SERVICE_SERVER) // // No downlevel call. // apiStatus = ERROR_NOT_SUPPORTED; NET_REMOTE_END if( apiStatus == RPC_NT_PROCNUM_OUT_OF_RANGE ) { apiStatus = NERR_InvalidAPI; } return(apiStatus); } // NetServerTransportAddEx NET_API_STATUS NET_API_FUNCTION NetServerComputerNameAdd( IN LPWSTR ServerName OPTIONAL, IN LPWSTR EmulatedDomainName OPTIONAL, IN LPWSTR EmulatedServerName ) /*++ Routine Description: This is the DLL entrypoint for NetServerComputerNameAdd. This api causes 'ServerName' to respond to requests for 'EmulatedServerName'. Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. EmulatedServerName --A pointer to the ASCIIZ string containing the name which the server should stop supporting EmulatedDomainName --A pointer to the ASCIIZ string containing the domain name the server should use when announcing the presence of 'EmulatedServerName' Return Value: NERR_Success, or reason for failure --*/ { DWORD resumehandle = 0; NET_API_STATUS retval; DWORD entriesread, totalentries; DWORD i, j; BOOLEAN AddedOne = FALSE; UCHAR NetBiosName[ MAX_PATH ]; OEM_STRING NetBiosNameString; UNICODE_STRING UniName; // // Ensure a valid EmulatedServerName was passed in // if( EmulatedServerName == NULL ) { return ERROR_INVALID_PARAMETER; } // // Convert the EmulatedServerName to an OEM string // RtlInitUnicodeString( &UniName, EmulatedServerName ); NetBiosNameString.Buffer = (PCHAR)NetBiosName; NetBiosNameString.MaximumLength = sizeof( NetBiosName ); (VOID) RtlUpcaseUnicodeStringToOemString( &NetBiosNameString, &UniName, FALSE ); if( ARGUMENT_PRESENT( EmulatedDomainName ) ) { // // The caller wants to set a new computer name and domain name to the // server. This requires level 1, which is new in 4.0 // PSERVER_TRANSPORT_INFO_1 psti1; // // Enumerate all the transports so we can add the name and domain // to each one. // retval = NetServerTransportEnum ( ServerName, 1, (LPBYTE *)&psti1, (DWORD)-1, &entriesread, &totalentries, &resumehandle ); if( retval == NERR_Success ) { // // Add the new name and domain to all of the transports // for( i=0; i < entriesread; i++ ) { // // Make sure we haven't already added to this transport // for( j = 0; j < i; j++ ) { if( wcscmp( psti1[j].svti1_transportname, psti1[i].svti1_transportname ) == 0 ) break; } if( i != j ) continue; psti1[i].svti1_transportaddress = NetBiosName; psti1[i].svti1_transportaddresslength = strlen( NetBiosName ); psti1[i].svti1_domain = EmulatedDomainName; retval = NetServerTransportAddEx( ServerName, 1, (LPBYTE)&psti1[ i ] ); if( retval == NERR_Success ) { AddedOne = TRUE; } } MIDL_user_free( psti1 ); } } else { // // The caller just wants to set an alternate server name. Use level 0, // since 3.51 servers support level 0 // PSERVER_TRANSPORT_INFO_0 psti0; // // Enumerate all the transports so we can add the name and domain // to each one. // retval = NetServerTransportEnum ( ServerName, 0, (LPBYTE *)&psti0, (DWORD)-1, &entriesread, &totalentries, &resumehandle ); if( retval == NERR_Success ) { // // Add the new name to all of the transports // for( i=0; i < entriesread; i++ ) { // // Make sure we haven't already added to this transport // for( j = 0; j < i; j++ ) { if( wcscmp( psti0[j].svti0_transportname, psti0[i].svti0_transportname ) == 0 ) break; } if( i != j ) continue; psti0[i].svti0_transportaddress = NetBiosName; psti0[i].svti0_transportaddresslength = strlen( NetBiosName ); retval = NetServerTransportAdd( ServerName, 0, (LPBYTE)&psti0[ i ] ); if( retval == NERR_Success ) { AddedOne = TRUE; } } MIDL_user_free( psti0 ); } } return AddedOne ? NERR_Success : retval; } NET_API_STATUS NET_API_FUNCTION NetServerComputerNameDel ( IN LPWSTR ServerName OPTIONAL, IN LPWSTR EmulatedServerName ) /*++ Routine Description: This is the DLL entrypoint for NetServerComputerNameDel. This api causes 'ServerName' to cease responding to requests for 'EmulatedServerName' Arguments: servername --A pointer to an ASCIIZ string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine. EmulatedServerName --A pointer to the ASCIIZ string containing the name which the server should stop supporting Return Value: NERR_Success, or reason for failure --*/ { DWORD resumehandle = 0; NET_API_STATUS retval, tmpretval; DWORD entriesread, totalentries; DWORD i; UCHAR NetBiosName[MAX_PATH]; OEM_STRING NetBiosNameString; UNICODE_STRING UniName; PSERVER_TRANSPORT_INFO_0 psti0; BOOLEAN nameDeleted = FALSE; // // Ensure a valid EmulatedServerName was passed in // if( EmulatedServerName == NULL ) { return ERROR_INVALID_PARAMETER; } // // Convert the EmulatedServerName to an OEM string // RtlInitUnicodeString( &UniName, EmulatedServerName ); NetBiosNameString.Buffer = (PCHAR)NetBiosName; NetBiosNameString.MaximumLength = sizeof( NetBiosName ); (VOID) RtlUpcaseUnicodeStringToOemString( &NetBiosNameString, &UniName, FALSE ); // // Enumerate all the transports so we can delete the name from each one // retval = NetServerTransportEnum ( ServerName, 0, (LPBYTE *)&psti0, (DWORD)-1, &entriesread, &totalentries, &resumehandle ); if( retval != NERR_Success ) { return retval; } retval = ERROR_BAD_NET_NAME; // // Delete the name from all of the transports. If we were successful at least once, // then we return success. // for( i=0; i < entriesread; i++ ) { if( psti0[i].svti0_transportaddresslength != NetBiosNameString.Length ) { continue; } if( RtlCompareMemory( psti0[i].svti0_transportaddress, NetBiosName, NetBiosNameString.Length) != NetBiosNameString.Length ) { continue; } tmpretval = NetServerTransportDel( ServerName, 0, (LPBYTE)&psti0[ i ] ); if( nameDeleted == FALSE ) { retval = tmpretval; if( retval == NERR_Success ) { nameDeleted = TRUE; } } } if( entriesread ) { MIDL_user_free( psti0 ); } return retval; }