|
|
/*++
Copyright (c) 1993 Microsoft Corporation
Module Name:
adtwrap.c
Abstract:
These are the Admin Tools Service API RPC client stubs.
Author:
Dan Lafferty (danl) 25-Mar-1993
Environment:
User Mode - Win32
Revision History:
25-Mar-1993 Danl Created
--*/
//
// INCLUDES
//
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h> // needed for windows.h when I have nt.h
#include <windows.h>
#include <srvsvc.h> // MIDL generated - includes windows.h & rpc.h
#include <rpc.h>
#include <lmcons.h>
#include <lmerr.h> // NERR_ error codes
#include <lmuse.h> // LPUSE_INFO_0
#include <lmapibuf.h> // NetApiBufferFree
#include <adtcomn.h>
//
// GLOBALS
//
DWORD AdtsvcDebugLevel = DEBUG_ERROR;
//
// LOCAL PROTOTYPES
//
DWORD AdtParsePathName( LPWSTR lpPathName, LPWSTR *pNewFileName, LPWSTR *pServerName, LPWSTR *pShareName );
LPWSTR AdtFindNextToken( WCHAR Token, LPWSTR String, LPDWORD pNumChars );
DWORD NetpGetFileSecurity( IN LPWSTR lpFileName, IN SECURITY_INFORMATION RequestedInformation, OUT PSECURITY_DESCRIPTOR *pSecurityDescriptor, OUT LPDWORD pnLength )
/*++
Routine Description:
This function returns to the caller a copy of the security descriptor protecting a file or directory.
NOTE: The buffer containing the security descriptor is allocated for the caller. It is the caller's responsibility to free the buffer by calling the NetApiBufferFree() function.
Arguments:
lpFileName - A pointer to the name fo the file or directory whose security is being retrieved.
SecurityInformation - security information being requested. pSecurityDescriptor - A pointer to a location where the pointer to the security descriptor is to be placed. The security descriptor is returned in the self-relative format.
pnLength - The size, in bytes, of the returned security descriptor.
Return Value:
NO_ERROR - The operation was successful.
ERROR_NOT_ENOUGH_MEMORY - Unable to allocate memory for the security descriptor.
This function can also return any error that GetFileSecurity can return.
--*/ { NET_API_STATUS status; ADT_SECURITY_DESCRIPTOR returnedSD; PADT_SECURITY_DESCRIPTOR pReturnedSD; LPWSTR pServerName; LPWSTR pShareName; LPWSTR pNewFileName;
RpcTryExcept { //
// Pick the server name out of the filename. Or translate the
// local drive name into a \\servername\sharename.
//
status = AdtParsePathName(lpFileName,&pNewFileName,&pServerName,&pShareName); } RpcExcept (1) { //
// Get RPC exception code.
//
status = RpcExceptionCode(); } RpcEndExcept if (status != NO_ERROR) { LocalFree(pServerName); return(status); }
if (pServerName == NULL) { //
// Call Locally.
//
ADT_LOG0(TRACE,"Call Local version (PrivateGetFileSecurity)\n");
status = PrivateGetFileSecurity ( lpFileName, RequestedInformation, pSecurityDescriptor, pnLength ); return(status); } //
// This is a remote call - - use RPC
//
//
// Initialize the fields in the structure so that RPC does not
// attempt to marshall anything on input.
//
ADT_LOG0(TRACE,"Call Remote version (NetrpGetFileSecurity)\n"); returnedSD.Length = 0; returnedSD.Buffer = NULL; RpcTryExcept { pReturnedSD = NULL; status = NetrpGetFileSecurity ( pServerName, pShareName, pNewFileName, RequestedInformation, &pReturnedSD); } RpcExcept (1) { //
// Get RPC exception code.
//
status = RpcExceptionCode(); } RpcEndExcept if (status == NO_ERROR) { *pSecurityDescriptor = pReturnedSD->Buffer; *pnLength = pReturnedSD->Length; } LocalFree(pServerName);
return (status); }
DWORD NetpSetFileSecurity ( IN LPWSTR lpFileName, IN SECURITY_INFORMATION SecurityInformation, IN PSECURITY_DESCRIPTOR pSecurityDescriptor )
/*++
Routine Description:
This function can be used to set the security of a file or directory.
Arguments:
ServerName - A pointer to a string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local machine.
lpFileName - A pointer to the name of the file or directory whose security is being changed.
SecurityInformation - information describing the contents of the Security Descriptor.
pSecurityDescriptor - A pointer to a well formed Security Descriptor.
Return Value:
NO_ERROR - The operation was successful.
This function can also return any error that SetFileSecurity can return.
--*/ { DWORD status= NO_ERROR; NTSTATUS ntStatus=STATUS_SUCCESS; ADT_SECURITY_DESCRIPTOR descriptorToPass; DWORD nSDLength; LPWSTR pNewFileName=NULL; LPWSTR pServerName=NULL; LPWSTR pShareName;
nSDLength = 0;
RpcTryExcept { //
// Pick the server name out of the filename. Or translate the
// local drive name into a \\servername\sharename.
//
status = AdtParsePathName(lpFileName,&pNewFileName,&pServerName,&pShareName); } RpcExcept (1) { //
// Get RPC exception code.
//
status = RpcExceptionCode(); } RpcEndExcept
if (status != NO_ERROR) { if (pServerName != NULL) { LocalFree(pServerName); } return(status); }
if (pServerName == NULL) { //
// Call Locally and return result.
//
status = PrivateSetFileSecurity ( lpFileName, SecurityInformation, pSecurityDescriptor); return(status); } //
// Call remotely
//
RpcTryExcept { //
// Force the Security Descriptor to be self-relative if it is not
// already.
// The first call to RtlMakeSelfRelativeSD is used to determine the
// size.
//
ntStatus = RtlMakeSelfRelativeSD( pSecurityDescriptor, NULL, &nSDLength); if (ntStatus != STATUS_BUFFER_TOO_SMALL) { status = RtlNtStatusToDosError(ntStatus); goto CleanExit; } descriptorToPass.Length = nSDLength; descriptorToPass.Buffer = LocalAlloc (LMEM_FIXED,nSDLength); if (descriptorToPass.Buffer == NULL) { status = ERROR_NOT_ENOUGH_MEMORY; goto CleanExit; } //
// Make an appropriate self-relative security descriptor.
//
ntStatus = RtlMakeSelfRelativeSD( pSecurityDescriptor, descriptorToPass.Buffer, &nSDLength); if (ntStatus != NO_ERROR) { LocalFree (descriptorToPass.Buffer); status = RtlNtStatusToDosError(ntStatus); goto CleanExit; } status = NetrpSetFileSecurity ( pServerName, pShareName, pNewFileName, SecurityInformation, &descriptorToPass);
LocalFree (descriptorToPass.Buffer);
CleanExit: ; } RpcExcept (1) { //
// Get RPC exception code.
//
status = RpcExceptionCode(); } RpcEndExcept LocalFree(pServerName); return (status);
}
DWORD AdtParsePathName( LPWSTR lpPathName, LPWSTR *pNewFileName, LPWSTR *pServerName, LPWSTR *pShareName )
/*++
Routine Description:
NOTE: This function allocates memory when the path contains a remote name. The pShareName and pServerName strings are in a single buffer that is to be freed at pServerName.
pNewFileName is NOT allocate by this routine. It points to a substring within the passed in lpPathName.
Arguments:
lpPathName - This is a pointer to the filename-path string. It can have any of the following formats:
x:\filedir\file.nam (remote) \\myserver\myshare\filedir\file.nam (remote) filedir\file.nam (local)
This could also just contain a directory name (and not a filename). pNewFileName - This is a location where a pointer to the buffer containing the file name can be placed. This will just contain the filename or directory name relative to the root directory.
pServerName - This is a location where a pointer to the buffer containing the server name can be placed. If this is for the local machine, then a NULL will be placed in this location.
pShareName - This is a location where a pointer to a buffer containing the share name can be placed. If this is for the local machine, then a NULL will be placed in this location.
Return Value:
--*/ #define REMOTE_DRIVE 0
#define REMOTE_PATH 1
#define LOCAL 2
{ DWORD status = NO_ERROR; NET_API_STATUS netStatus=NERR_Success; WCHAR useName[4]; LPUSE_INFO_0 pUseInfo=NULL; LPWSTR pNewPathName=NULL; DWORD DeviceType = LOCAL; LPWSTR pPrivateServerName; LPWSTR pPrivateShareName; LPWSTR pEnd; DWORD numServerChars; DWORD numChars; WCHAR token;
*pServerName = NULL; *pShareName = NULL; //
// If the fileName starts with a drive letter, then use NetUseGetInfo
// to get the remote name.
//
if (lpPathName[1] == L':') { if (((L'a' <= lpPathName[0]) && (lpPathName[0] <= L'z')) || ((L'A' <= lpPathName[0]) && (lpPathName[0] <= L'Z'))) { //
// This is in the form of a local device. Get the server/sharename
// associated with this device.
//
wcsncpy(useName, lpPathName, 2); useName[2]=L'\0'; netStatus = NetUseGetInfo( NULL, // server name
useName, // use name
0, // level
(LPBYTE *)&pUseInfo); // buffer
if (netStatus != NERR_Success) { //
// if we get NERR_UseNotFound back, then this must be
// a local drive letter, and not a redirected one.
// In this case we return success.
//
if (netStatus == NERR_UseNotFound) { return(NERR_Success); } return(netStatus); } DeviceType = REMOTE_DRIVE; pNewPathName = pUseInfo->ui0_remote; } } else { if (wcsncmp(lpPathName,L"\\\\",2) == 0) { DeviceType = REMOTE_PATH; pNewPathName = lpPathName; } } if (DeviceType != LOCAL) {
//
// Figure out how many characters for the server and share portion
// of the string.
// Add 2 characters for the leading "\\\\", allocate a buffer, and
// copy the characters.
//
numChars = 2; pPrivateShareName = AdtFindNextToken(L'\\',pNewPathName+2,&numChars); if (pPrivateShareName == NULL) { status = ERROR_BAD_PATHNAME; goto CleanExit; } numServerChars = numChars;
token = L'\\'; if (DeviceType == REMOTE_DRIVE) { token = L'\0'; } pEnd = AdtFindNextToken(token,pPrivateShareName+1,&numChars); if (pEnd == NULL) { status = ERROR_BAD_PATHNAME; goto CleanExit; } //
// If this is a remotepath name, then the share name portion will
// also contain the '\' token. Remove this by decrementing the
// count.
//
if (DeviceType == REMOTE_PATH) { numChars--; } pPrivateServerName = LocalAlloc(LMEM_FIXED,(numChars+1) * sizeof(WCHAR)); if (pPrivateServerName == NULL) { status = GetLastError(); goto CleanExit; }
//
// Copy the the "\\servername\sharename" to the new buffer and
// place NUL characters in place of the single '\'.
//
wcsncpy(pPrivateServerName, pNewPathName, numChars); pPrivateShareName = pPrivateServerName + numServerChars;
*(pPrivateShareName -1) = L'\0'; // NUL terminate the server name
pPrivateServerName[ numChars ] = L'\0'; // NUL terminate the share name
if (DeviceType == REMOTE_PATH) { *pNewFileName = pEnd; } else { *pNewFileName = lpPathName+2; } *pServerName = pPrivateServerName; *pShareName = pPrivateShareName; } CleanExit: if (pUseInfo != NULL) { NetApiBufferFree(pUseInfo); } return(status); }
LPWSTR AdtFindNextToken( WCHAR Token, LPWSTR pString, LPDWORD pNumChars )
/*++
Routine Description:
Finds the first occurance of Token in the pString.
Arguments:
Token - This is the unicode character that we are searching for in the string.
pString - This is a pointer to the string in which the token is to be found.
pNumChars - This is a pointer to a DWORD that will upon exit increment by the number of characters found in the string (including the token).
Return Value:
If the token is found this returns a pointer to the Token. Otherwise, it returns NULL.
--*/ { DWORD saveNum=*pNumChars;
while ((*pString != Token) && (*pString != L'\0')) { pString++; (*pNumChars)++; } if (*pString != Token) { *pNumChars = saveNum; return(NULL); } (*pNumChars)++; return(pString); }
|