diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/nw/svcdlls/nwwks/lib | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to '')
-rw-r--r-- | private/nw/svcdlls/nwwks/lib/lsa.c | 537 | ||||
-rw-r--r-- | private/nw/svcdlls/nwwks/lib/makefile | 6 | ||||
-rw-r--r-- | private/nw/svcdlls/nwwks/lib/misc.c | 785 | ||||
-rw-r--r-- | private/nw/svcdlls/nwwks/lib/reg.c | 1010 | ||||
-rw-r--r-- | private/nw/svcdlls/nwwks/lib/sources | 47 | ||||
-rw-r--r-- | private/nw/svcdlls/nwwks/lib/splutil.c | 351 |
6 files changed, 2736 insertions, 0 deletions
diff --git a/private/nw/svcdlls/nwwks/lib/lsa.c b/private/nw/svcdlls/nwwks/lib/lsa.c new file mode 100644 index 000000000..1dc664aa4 --- /dev/null +++ b/private/nw/svcdlls/nwwks/lib/lsa.c @@ -0,0 +1,537 @@ +/*++ + +Copyright (c) 1993 Microsoft Corporation + +Module Name: + + lsa.c + +Abstract: + + This module provides helpers to call LSA, particularly for + manipulating secret objects. + +Author: + + Rita Wong (ritaw) 22-Apr-1993 + +--*/ + +#include <stdlib.h> + +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> + +#include <windef.h> +#include <winerror.h> +#include <winbase.h> + +#include <nwlsa.h> + +//-------------------------------------------------------------------// +// // +// Constants and Macros // +// // +//-------------------------------------------------------------------// + +#define NW_SECRET_PREFIX L"_MS_NWCS_" + + +DWORD +NwOpenPolicy( + IN ACCESS_MASK DesiredAccess, + OUT LSA_HANDLE *PolicyHandle + ) +/*++ + +Routine Description: + + This function gets a handle to the local security policy by calling + LsaOpenPolicy. + +Arguments: + + DesiredAccess - Supplies the desired access to the local security + policy. + + PolicyHandle - Receives a handle to the opened policy. + +Return Value: + + NO_ERROR - Policy handle is returned. + + Error from LSA. + +--*/ +{ + NTSTATUS ntstatus; + OBJECT_ATTRIBUTES ObjAttributes; + + + // + // Open a handle to the local security policy. Initialize the + // objects attributes structure first. + // + InitializeObjectAttributes( + &ObjAttributes, + NULL, + 0L, + NULL, + NULL + ); + + ntstatus = LsaOpenPolicy( + NULL, + &ObjAttributes, + DesiredAccess, + PolicyHandle + ); + + if (! NT_SUCCESS(ntstatus)) { + KdPrint(("NWWORKSTATION: LsaOpenPolicy returns %08lx\n", + ntstatus)); + + return RtlNtStatusToDosError(ntstatus); + } + + return NO_ERROR; +} + + +DWORD +NwOpenSecret( + IN ACCESS_MASK DesiredAccess, + IN LSA_HANDLE PolicyHandle, + IN LPWSTR LsaSecretName, + OUT PLSA_HANDLE SecretHandle + ) +/*++ + +Routine Description: + + This function opens a handle to the specified secret object. + +Arguments: + + DesiredAccess - Supplies the desired access to the secret object. + + PolicyHandle - Supplies a handle to an already opened LSA policy. + + LsaSecretName - Supplies the name of the secret to open. + + SecretHandle - Receives the handle of the opened secret. + +Return Value: + + NO_ERROR - Secret handle is returned. + + Error from LSA. + +--*/ +{ + NTSTATUS ntstatus; + UNICODE_STRING SecretNameString; + + + RtlInitUnicodeString(&SecretNameString, LsaSecretName); + + ntstatus = LsaOpenSecret( + PolicyHandle, + &SecretNameString, + DesiredAccess, + SecretHandle + ); + + + if (! NT_SUCCESS(ntstatus)) { + KdPrint(("NWWORKSTATION: LsaOpenSecret %ws returns %08lx\n", + LsaSecretName, ntstatus)); + + return RtlNtStatusToDosError(ntstatus); + } + + return NO_ERROR; +} + + +DWORD +NwFormSecretName( + IN LPWSTR Qualifier, + OUT LPWSTR *LsaSecretName + ) +/*++ + +Routine Description: + + This function creates a secret name from the user name. + It also allocates the buffer to return the created secret name which + must be freed by the caller using LocalFree when done with it. + +Arguments: + + Qualifier - Supplies the qualifier which forms part of part of the secret + object name we are creating. + + LsaSecretName - Receives a pointer to the buffer which contains the + secret object name. + +Return Value: + + NO_ERROR - Successfully returned secret name. + + ERROR_NOT_ENOUGH_MEMORY - Failed to allocate buffer to hold the secret + name. + +--*/ +{ + if ((*LsaSecretName = (LPWSTR)LocalAlloc( + 0, + (wcslen(NW_SECRET_PREFIX) + + wcslen(Qualifier) + + 1) * sizeof(WCHAR) + )) == NULL) { + + KdPrint(("NWWORKSTATION: NwFormSecretName: LocalAlloc failed %lu\n", + GetLastError())); + return ERROR_NOT_ENOUGH_MEMORY; + } + + wcscpy(*LsaSecretName, NW_SECRET_PREFIX); + wcscat(*LsaSecretName, Qualifier); + + return NO_ERROR; +} + + + +DWORD +NwSetPassword( + IN LPWSTR Qualifier, + IN LPWSTR Password + ) +/*++ + +Routine Description: + + This function opens ( creates one if needed ) the LSA secret object, + and sets it with the specified password. + +Arguments: + + Qualifier - Supplies the qualifier which forms part of part of the secret + object name to be created. + + Password - Supplies the user specified password for an account. + +Return Value: + + NO_ERROR - Secret object for the password is created and set with new value. + + Error from LSA. + +--*/ +{ + DWORD status; + NTSTATUS ntstatus; + LSA_HANDLE PolicyHandle; + + LSA_HANDLE SecretHandle; + UNICODE_STRING SecretNameString; + LPWSTR LsaSecretName; + + UNICODE_STRING NewPasswordString; + UNICODE_STRING OldPasswordString; + + + // + // Open a handle to the local security policy. + // + if ((status = NwOpenPolicy( + POLICY_CREATE_SECRET, + &PolicyHandle + )) != NO_ERROR) { + KdPrint(("NWWORKSTATION: NwCreatePassword: NwOpenPolicy failed\n")); + return status; + } + + // + // Create the LSA secret object. But first, form a secret name. + // + if ((status = NwFormSecretName( + Qualifier, + &LsaSecretName + )) != NO_ERROR) { + (void) LsaClose(PolicyHandle); + return status; + } + + RtlInitUnicodeString(&SecretNameString, LsaSecretName); + + ntstatus = LsaCreateSecret( + PolicyHandle, + &SecretNameString, + SECRET_SET_VALUE | DELETE, + &SecretHandle + ); + + + // + // note: ignore object already exists error. just use the existing + // object. this could be because the user didnt completely cleanup + // during deinstall. the unique names makes it unlikely to be a real + // collision. + // + if ( ntstatus == STATUS_OBJECT_NAME_COLLISION ) { + ntstatus = NwOpenSecret( + SECRET_SET_VALUE, + PolicyHandle, + LsaSecretName, + &SecretHandle + ); + } + + // + // Don't need the name or policy handle anymore. + // + (void) LocalFree((HLOCAL) LsaSecretName); + (void) LsaClose(PolicyHandle); + + if (! NT_SUCCESS(ntstatus)) { + + KdPrint(("NWWORKSTATION: NwCreatePassword: LsaCreateSecret or LsaOpenSecret returned %08lx for %ws\n", ntstatus, LsaSecretName)); + + return RtlNtStatusToDosError(ntstatus); + } + + + RtlInitUnicodeString(&OldPasswordString, NULL); + RtlInitUnicodeString(&NewPasswordString, Password); + + ntstatus = LsaSetSecret( + SecretHandle, + &NewPasswordString, + &OldPasswordString + ); + + if (! NT_SUCCESS(ntstatus)) { + KdPrint(("NWWORKSTATION NwCreatePassword: LsaSetSecret returned %08lx\n", + ntstatus)); + + status = RtlNtStatusToDosError(ntstatus); + + // + // Delete the secret object + // + ntstatus = LsaDelete(SecretHandle); + + if (! NT_SUCCESS(ntstatus)) { + KdPrint(("NWWORKSTATION: NwCreatePassword: LsaDelete to restore back to original returned %08lx\n", + ntstatus)); + (void) LsaClose(SecretHandle); + } + + // + // Secret handle is closed by LsaDelete if successfully deleted. + // + return status; + } + + (void) LsaClose(SecretHandle); + + return NO_ERROR; +} + + + +DWORD +NwDeletePassword( + IN LPWSTR Qualifier + ) +/*++ + +Routine Description: + + This function deletes the LSA secret object whose name is derived + from the specified Qualifier. + +Arguments: + + Qualifier - Supplies the qualifier which forms part of part of the secret + object name to be deleted. + +Return Value: + + NO_ERROR - Secret object for password is deleted. + + Error from LSA. + +--*/ +{ + DWORD status; + NTSTATUS ntstatus; + + LSA_HANDLE PolicyHandle; + + LSA_HANDLE SecretHandle; + LPWSTR LsaSecretName; + + + // + // Open a handle to the local security policy. + // + if ((status = NwOpenPolicy( + POLICY_VIEW_LOCAL_INFORMATION, + &PolicyHandle + )) != NO_ERROR) { + KdPrint(("NWWORKSTATION: NwDeletePassword: NwOpenPolicy failed\n")); + return status; + } + + // + // Get the secret object name from the specified user name. + // + if ((status = NwFormSecretName( + Qualifier, + &LsaSecretName + )) != NO_ERROR) { + (void) LsaClose(PolicyHandle); + return status; + } + + status = NwOpenSecret( + DELETE, + PolicyHandle, + LsaSecretName, + &SecretHandle + ); + + // + // Don't need the name or policy handle anymore. + // + (void) LocalFree((HLOCAL) LsaSecretName); + (void) LsaClose(PolicyHandle); + + if (status != NO_ERROR) { + KdPrint(("NWWORKSTATION: NwDeletePassword: NwOpenSecret failed\n")); + return status; + } + + ntstatus = LsaDelete(SecretHandle); + + if (! NT_SUCCESS(ntstatus)) { + KdPrint(("NWWORKSTATION: NwDeletePassword: LsaDelete returned %08lx\n", + ntstatus)); + (void) LsaClose(SecretHandle); + return RtlNtStatusToDosError(ntstatus); + } + + return NO_ERROR; +} + + + +DWORD +NwGetPassword( + IN LPWSTR Qualifier, + OUT PUNICODE_STRING *Password, + OUT PUNICODE_STRING *OldPassword + ) +/*++ + +Routine Description: + + This function retrieves the current password and old password + values from the service secret object given the user name. + +Arguments: + + Qualifier - Supplies the qualifier which forms part of the key to the + secret object name. + + Password - Receives a pointer to the string structure that contains + the password. + + OldPassword - Receives a pointer to the string structure that + contains the old password. + +Return Value: + + NO_ERROR - Secret object for password is changed to new value. + + Error from LSA. + +--*/ +{ + DWORD status; + NTSTATUS ntstatus; + + LSA_HANDLE PolicyHandle; + LSA_HANDLE SecretHandle; + + LPWSTR LsaSecretName; + + + // + // Open a handle to the local security policy to read the + // value of the secret. + // + if ((status = NwOpenPolicy( + POLICY_VIEW_LOCAL_INFORMATION, + &PolicyHandle + )) != NO_ERROR) { + return status; + } + + // + // Get the secret object name from the specified user name. + // + if ((status = NwFormSecretName( + Qualifier, + &LsaSecretName + )) != NO_ERROR) { + (void) LsaClose(PolicyHandle); + return status; + } + + status = NwOpenSecret( + SECRET_QUERY_VALUE, + PolicyHandle, + LsaSecretName, + &SecretHandle + ); + + // + // Don't need the name or policy handle anymore. + // + (void) LocalFree((HLOCAL) LsaSecretName); + (void) LsaClose(PolicyHandle); + + if (status != NO_ERROR) { + KdPrint(("NWWORKSTATION: ScGetSecret: ScOpenSecret failed\n")); + return status; + } + + // + // Query the old value of the secret object so that we can + // we can restore it if we fail to change the password later. + // + ntstatus = LsaQuerySecret( + SecretHandle, + Password, + NULL, // don't need set time + OldPassword, + NULL // don't need set time + ); + + (void) LsaClose(SecretHandle); + + if (! NT_SUCCESS(ntstatus)) { + KdPrint(("NWWORKSTATION: NwGetPassword: LsaQuerySecret for previous values returned %08lx\n", + ntstatus)); + + return RtlNtStatusToDosError(ntstatus); + } + + return NO_ERROR; +} diff --git a/private/nw/svcdlls/nwwks/lib/makefile b/private/nw/svcdlls/nwwks/lib/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/nw/svcdlls/nwwks/lib/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/nw/svcdlls/nwwks/lib/misc.c b/private/nw/svcdlls/nwwks/lib/misc.c new file mode 100644 index 000000000..e28db0a84 --- /dev/null +++ b/private/nw/svcdlls/nwwks/lib/misc.c @@ -0,0 +1,785 @@ +/*++ + +Copyright (c) 1993 Microsoft Corporation + +Module Name: + + api.c + +Abstract: + + This module contains misc APIs that are used by the + NWC wksta. + +Author: + + ChuckC 2-Mar-94 Created + + +Revision History: + +--*/ + + +#include <stdlib.h> +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> +#include <windows.h> +#include <nwcons.h> +#include <nwmisc.h> +#include <nwapi32.h> +#include "nwstatus.h" +#include "nwevent.h" + +DWORD +NwMapStatus( + IN NTSTATUS NtStatus + ); + +DWORD +NwOpenPreferredServer( + PHANDLE ServerHandle + ); + +NTSTATUS +NwOpenHandle( + IN PUNICODE_STRING ObjectName, + IN BOOL ValidateFlag, + OUT PHANDLE ObjectHandle + ); + +NTSTATUS +NwCallNtOpenFile( + OUT PHANDLE ObjectHandle, + IN ACCESS_MASK DesiredAccess, + IN PUNICODE_STRING ObjectName, + IN ULONG OpenOptions + ); + + +// +// list of error mappings known for E3H calls. we do not have a single list +// because Netware reuses the numbers depending on call. +// + +typedef struct _ERROR_MAP_ENTRY +{ + UCHAR NetError; + NTSTATUS ResultingStatus; +} ERROR_MAP_ENTRY ; + +ERROR_MAP_ENTRY Error_Map_Bindery[] = +{ + + // + // NetWare specific error mappings. Specific to E3H. + // + { 1, STATUS_DISK_FULL }, + {128, STATUS_SHARING_VIOLATION }, + {129, STATUS_INSUFF_SERVER_RESOURCES }, + {130, STATUS_ACCESS_DENIED }, + {131, STATUS_DATA_ERROR }, + {132, STATUS_ACCESS_DENIED }, + {133, STATUS_ACCESS_DENIED }, + {134, STATUS_ACCESS_DENIED }, + {135, STATUS_OBJECT_NAME_INVALID }, + {136, STATUS_INVALID_HANDLE }, + {137, STATUS_ACCESS_DENIED }, + {138, STATUS_ACCESS_DENIED }, + {139, STATUS_ACCESS_DENIED }, + {140, STATUS_ACCESS_DENIED }, + {141, STATUS_SHARING_VIOLATION }, + {142, STATUS_SHARING_VIOLATION }, + {143, STATUS_ACCESS_DENIED }, + {144, STATUS_ACCESS_DENIED }, + {145, STATUS_OBJECT_NAME_COLLISION }, + {146, STATUS_OBJECT_NAME_COLLISION }, + {147, STATUS_ACCESS_DENIED }, + {148, STATUS_ACCESS_DENIED }, + {150, STATUS_INSUFF_SERVER_RESOURCES }, + {151, STATUS_NO_SPOOL_SPACE }, + {152, STATUS_NO_SUCH_DEVICE }, + {153, STATUS_DISK_FULL }, + {154, STATUS_NOT_SAME_DEVICE }, + {155, STATUS_INVALID_HANDLE }, + {156, STATUS_OBJECT_PATH_NOT_FOUND }, + {157, STATUS_INSUFF_SERVER_RESOURCES }, + {158, STATUS_OBJECT_PATH_INVALID }, + {159, STATUS_SHARING_VIOLATION }, + {160, STATUS_DIRECTORY_NOT_EMPTY }, + {161, STATUS_DATA_ERROR }, + {162, STATUS_SHARING_VIOLATION }, + {192, STATUS_ACCESS_DENIED }, + {198, STATUS_ACCESS_DENIED }, + {211, STATUS_ACCESS_DENIED }, + {212, STATUS_PRINT_QUEUE_FULL }, + {213, STATUS_PRINT_CANCELLED }, + {214, STATUS_ACCESS_DENIED }, + {215, STATUS_PASSWORD_RESTRICTION }, + {216, STATUS_PASSWORD_RESTRICTION }, + {220, STATUS_ACCOUNT_DISABLED }, + {222, STATUS_PASSWORD_EXPIRED }, + {223, STATUS_PASSWORD_EXPIRED }, + {239, STATUS_OBJECT_NAME_INVALID }, + {240, STATUS_OBJECT_NAME_INVALID }, + {251, STATUS_INVALID_PARAMETER }, + {252, STATUS_NO_MORE_ENTRIES }, + {253, STATUS_FILE_LOCK_CONFLICT }, + {254, STATUS_FILE_LOCK_CONFLICT }, + {255, STATUS_UNSUCCESSFUL} +}; + + +ERROR_MAP_ENTRY Error_Map_General[] = +{ + { 1, STATUS_DISK_FULL }, + {128, STATUS_SHARING_VIOLATION }, + {129, STATUS_INSUFF_SERVER_RESOURCES }, + {130, STATUS_ACCESS_DENIED }, + {131, STATUS_DATA_ERROR }, + {132, STATUS_ACCESS_DENIED }, + {133, STATUS_ACCESS_DENIED }, + {134, STATUS_ACCESS_DENIED }, + {135, STATUS_OBJECT_NAME_INVALID }, + {136, STATUS_INVALID_HANDLE }, + {137, STATUS_ACCESS_DENIED }, + {138, STATUS_ACCESS_DENIED }, + {139, STATUS_ACCESS_DENIED }, + {140, STATUS_ACCESS_DENIED }, + {141, STATUS_SHARING_VIOLATION }, + {142, STATUS_SHARING_VIOLATION }, + {143, STATUS_ACCESS_DENIED }, + {144, STATUS_ACCESS_DENIED }, + {145, STATUS_OBJECT_NAME_COLLISION }, + {146, STATUS_OBJECT_NAME_COLLISION }, + {147, STATUS_ACCESS_DENIED }, + {148, STATUS_ACCESS_DENIED }, + {150, STATUS_INSUFF_SERVER_RESOURCES }, + {151, STATUS_NO_SPOOL_SPACE }, + {152, STATUS_NO_SUCH_DEVICE }, + {153, STATUS_DISK_FULL }, + {154, STATUS_NOT_SAME_DEVICE }, + {155, STATUS_INVALID_HANDLE }, + {156, STATUS_OBJECT_PATH_NOT_FOUND }, + {157, STATUS_INSUFF_SERVER_RESOURCES }, + {158, STATUS_OBJECT_PATH_INVALID }, + {159, STATUS_SHARING_VIOLATION }, + {160, STATUS_DIRECTORY_NOT_EMPTY }, + {161, STATUS_DATA_ERROR }, + {162, STATUS_SHARING_VIOLATION }, + {192, STATUS_ACCESS_DENIED }, + {198, STATUS_ACCESS_DENIED }, + {211, STATUS_ACCESS_DENIED }, + {212, STATUS_PRINT_QUEUE_FULL }, + {213, STATUS_PRINT_CANCELLED }, + {214, STATUS_ACCESS_DENIED }, + {215, STATUS_DEVICE_BUSY }, + {216, STATUS_DEVICE_DOES_NOT_EXIST }, + {220, STATUS_ACCOUNT_DISABLED }, + {222, STATUS_PASSWORD_EXPIRED }, + {223, STATUS_PASSWORD_EXPIRED }, + {239, STATUS_OBJECT_NAME_INVALID }, + {240, STATUS_OBJECT_NAME_INVALID }, + {251, STATUS_INVALID_PARAMETER }, + {252, STATUS_NO_MORE_ENTRIES }, + {253, STATUS_FILE_LOCK_CONFLICT }, + {254, STATUS_FILE_LOCK_CONFLICT }, + {255, STATUS_UNSUCCESSFUL} +}; + +#define NUM_ERRORS(x) (sizeof(x)/sizeof(x[0])) + +DWORD +NwMapBinderyCompletionCode( + IN NTSTATUS NtStatus + ) +/*++ + +Routine Description: + + This function takes a bindery completion code embedded in an NT status + code and maps it to the appropriate Win32 error code. Used specifically + for E3H operations. + +Arguments: + + NtStatus - Supplies the NT status (that contains the code in low 16 bits) + +Return Value: + + Returns the appropriate Win32 error. + +--*/ +{ + DWORD i; UCHAR code ; + + // + // A small optimization for the most common case. + // + if (NtStatus == STATUS_SUCCESS) + return NO_ERROR; + + // + // Map connection errors specially. + // + + if ( ( (NtStatus & 0xFFFF0000) == 0xC0010000) && + ( (NtStatus & 0xFF00) != 0 ) ) + { + return ERROR_UNEXP_NET_ERR; + } + + // + // if facility code not set, assume it is NT Status + // + if ( (NtStatus & 0xFFFF0000) != 0xC0010000) + return RtlNtStatusToDosError(NtStatus); + + code = NtStatus & 0x000000FF ; + for (i = 0; i < NUM_ERRORS(Error_Map_Bindery); i++) + { + if (Error_Map_Bindery[i].NetError == code) + return( NwMapStatus(Error_Map_Bindery[i].ResultingStatus)); + } + + // + // if cannot find let NwMapStatus do its best + // + return NwMapStatus(NtStatus); +} + + + +DWORD +NwMapStatus( + IN NTSTATUS NtStatus + ) +/*++ + +Routine Description: + + This function takes an NT status code and maps it to the appropriate + Win32 error code. If facility code is set, assume it is NW specific + +Arguments: + + NtStatus - Supplies the NT status. + +Return Value: + + Returns the appropriate Win32 error. + +--*/ +{ + DWORD i; UCHAR code ; + + // + // A small optimization for the most common case. + // + if (NtStatus == STATUS_SUCCESS) + return NO_ERROR; + + // + // Map connection errors specially. + // + + if ( ( (NtStatus & 0xFFFF0000) == 0xC0010000) && + ( (NtStatus & 0xFF00) != 0 ) ) + { + return ERROR_UNEXP_NET_ERR; + } + + // + // if facility code set, assume it is NW Completion code + // + if ( (NtStatus & 0xFFFF0000) == 0xC0010000) + { + code = NtStatus & 0x000000FF ; + for (i = 0; i < NUM_ERRORS(Error_Map_General); i++) + { + if (Error_Map_General[i].NetError == code) + { + // + // map it to NTSTATUS and then drop thru to map to Win32 + // + NtStatus = Error_Map_General[i].ResultingStatus ; + break ; + } + } + } + + switch (NtStatus) { + case STATUS_OBJECT_NAME_COLLISION: + return ERROR_ALREADY_ASSIGNED; + + case STATUS_OBJECT_NAME_NOT_FOUND: + return ERROR_NOT_CONNECTED; + + case STATUS_IMAGE_ALREADY_LOADED: + case STATUS_REDIRECTOR_STARTED: + return ERROR_SERVICE_ALREADY_RUNNING; + + case STATUS_REDIRECTOR_HAS_OPEN_HANDLES: + return ERROR_REDIRECTOR_HAS_OPEN_HANDLES; + + case STATUS_NO_MORE_FILES: + case STATUS_NO_MORE_ENTRIES: + return WN_NO_MORE_ENTRIES; + + case STATUS_MORE_ENTRIES: + return WN_MORE_DATA; + + case STATUS_CONNECTION_IN_USE: + return ERROR_DEVICE_IN_USE; + + case NWRDR_PASSWORD_HAS_EXPIRED: + return NW_PASSWORD_HAS_EXPIRED; + + case STATUS_INVALID_DEVICE_REQUEST: + return ERROR_CONNECTION_INVALID; + + default: + return RtlNtStatusToDosError(NtStatus); + } +} + +DWORD +NwGetGraceLoginCount( + LPWSTR Server, + LPWSTR UserName, + LPDWORD lpResult + ) +/*++ + +Routine Description: + + Get the number grace logins for a user. + +Arguments: + + Server - the server to authenticate against + + UserName - the user account + +Return Value: + + Returns the appropriate Win32 error. + +--*/ +{ + DWORD status ; + HANDLE hConn ; + CHAR UserNameO[NW_MAX_USERNAME_LEN+1] ; + BYTE LoginControl[128] ; + BYTE MoreFlags, PropFlags ; + + // + // skip the backslashes if present + // + if (*Server == L'\\') + Server += 2 ; + + // + // attach to the NW server + // + if (status = NWAttachToFileServerW(Server, + 0, + &hConn)) + { + return status ; + } + + // + // convert unicode UserName to OEM, and then call the NCP + // + if ( !WideCharToMultiByte(CP_OEMCP, + 0, + UserName, + -1, + UserNameO, + sizeof(UserNameO), + NULL, + NULL)) + { + status = GetLastError() ; + } + else + { + status = NWReadPropertyValue( hConn, + UserNameO, + OT_USER, + "LOGIN_CONTROL", + 1, + LoginControl, + &MoreFlags, + &PropFlags) ; + } + + // + // dont need these anymore. if any error, bag out + // + (void) NWDetachFromFileServer(hConn) ; + + + if (status == NO_ERROR) + *lpResult = (DWORD) LoginControl[7] ; + + return status ; +} + + +WORD +NwParseNdsUncPath( + IN OUT LPWSTR * Result, + IN LPWSTR ContainerName, + IN ULONG flag +) +/*++ + +Routine Description: + + This function is used to extract either the tree name, fully distinguished + name path to an object, or object name, out of a complete NDS UNC path. + +Arguments: + + Result - parsed result buffer. + ContainerName - Complete NDS UNC path that is to be parsed. + flag - Flag indicating operation to be performed: + + PARSE_NDS_GET_TREE_NAME + PARSE_NDS_GET_PATH_NAME + PARSE_NDS_GET_OBJECT_NAME + + +Return Value: + + Length of string in result buffer. If error occured, 0 is returned. + +--*/ // NwParseNdsUncPath +{ + unsigned short length = 2; + unsigned short totalLength = wcslen( ContainerName ); + + if ( totalLength < 2 ) + return 0; + + // + // First get length to indicate the character in the string that indicates the + // "\" in between the tree name and the rest of the UNC path. + // + // Example: \\<tree name>\<path to object>[\|.]<object> + // ^ + // | + // + while ( length < totalLength && ContainerName[length] != L'\\' ) + { + length++; + } + + if ( flag == PARSE_NDS_GET_TREE_NAME ) + { + *Result = (LPWSTR) ( ContainerName + 2 ); + + return ( length - 2 ) * sizeof( WCHAR ); // Take off 2 for the two \\'s + } + + if ( flag == PARSE_NDS_GET_PATH_NAME && length == totalLength ) + { + *Result = ContainerName; + + return 0; + } + + if ( flag == PARSE_NDS_GET_PATH_NAME ) + { + *Result = ContainerName + length + 1; + + return ( totalLength - length - 1 ) * sizeof( WCHAR ); + } + + *Result = ContainerName + totalLength - 1; + length = 1; + + while ( **Result != L'\\' ) + { + *Result--; + length++; + } + + *Result++; + length--; + + return length * sizeof( WCHAR ); +} + + +DWORD +NwOpenAServer( + PWCHAR pwszServName, + PHANDLE ServerHandle, + BOOL fVerify + ) +/*++ + +Routine Description: + + This routine opens a handle to a server. + +Arguments: + + ServerHandle - Receives an opened handle to the preferred or + nearest server. + +Return Value: + + NO_ERROR or reason for failure. + +--*/ +{ + UNICODE_STRING AServer; + WCHAR wszName[sizeof(NW_RDR_NAME) + (48 * sizeof(WCHAR))]; + DWORD wLen; + + + if(!pwszServName) + { + pwszServName = NW_RDR_PREFERRED_SERVER; + RtlInitUnicodeString(&AServer, wszName); + } + else + { + wLen = wcslen(pwszServName); + if(wLen > 47) + { + return(WSAEFAULT); + } + wcscpy(wszName, NW_RDR_NAME); + wcscat(wszName, pwszServName); + RtlInitUnicodeString(&AServer, wszName); + } + + return RtlNtStatusToDosError( + NwOpenHandle(&AServer, fVerify, ServerHandle) + ); + +} + + +DWORD +NwOpenPreferredServer( + PHANDLE ServerHandle + ) +/*++ + +Routine Description: + + This routine opens a handle to the preferred server. If the + preferred server has not been specified, a handle to the + nearest server is opened instead. + +Arguments: + + ServerHandle - Receives an opened handle to the preferred or + nearest server. + +Return Value: + + NO_ERROR or reason for failure. + +--*/ +{ + UNICODE_STRING PreferredServer; + + + // + // The NetWare redirector recognizes "*" to mean the preferred + // or nearest server. + // + RtlInitUnicodeString(&PreferredServer, NW_RDR_PREFERRED_SERVER); + + return RtlNtStatusToDosError( + NwOpenHandle(&PreferredServer, FALSE, ServerHandle) + ); + +} + + +NTSTATUS +NwOpenHandle( + IN PUNICODE_STRING ObjectName, + IN BOOL ValidateFlag, + OUT PHANDLE ObjectHandle + ) +/*++ + +Routine Description: + + This function opens a handle to \Device\Nwrdr\<ObjectName>. + +Arguments: + + ObjectName - Supplies the name of the redirector object to open. + + ValidateFlag - Supplies a flag which if TRUE, opens the handle to + the object by validating the default user account. + + ObjectHandle - Receives a pointer to the opened object handle. + +Return Value: + + STATUS_SUCCESS or reason for failure. + +--*/ +{ + ACCESS_MASK DesiredAccess = SYNCHRONIZE; + + + if (ValidateFlag) { + + // + // The redirector only authenticates the default user credential + // if the remote resource is opened with write access. + // + DesiredAccess |= FILE_WRITE_DATA; + } + + + *ObjectHandle = NULL; + + return NwCallNtOpenFile( + ObjectHandle, + DesiredAccess, + ObjectName, + FILE_SYNCHRONOUS_IO_NONALERT + ); + +} + + +NTSTATUS +NwCallNtOpenFile( + OUT PHANDLE ObjectHandle, + IN ACCESS_MASK DesiredAccess, + IN PUNICODE_STRING ObjectName, + IN ULONG OpenOptions + ) +{ + + NTSTATUS ntstatus; + IO_STATUS_BLOCK IoStatusBlock; + OBJECT_ATTRIBUTES ObjectAttributes; + + + + InitializeObjectAttributes( + &ObjectAttributes, + ObjectName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL + ); + + ntstatus = NtOpenFile( + ObjectHandle, + DesiredAccess, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_VALID_FLAGS, + OpenOptions + ); + + if (!NT_ERROR(ntstatus) && + !NT_INFORMATION(ntstatus) && + !NT_WARNING(ntstatus)) { + + ntstatus = IoStatusBlock.Status; + + } + + return ntstatus; +} + + +BOOL +NwConvertToUnicode( + OUT LPWSTR *UnicodeOut, + IN LPSTR OemIn + ) +/*++ + +Routine Description: + + This function converts the given OEM string to a Unicode string. + The Unicode string is returned in a buffer allocated by this + function and must be freed with LocalFree. + +Arguments: + + UnicodeOut - Receives a pointer to the Unicode string. + + OemIn - This is a pointer to an ansi string that is to be converted. + +Return Value: + + TRUE - The conversion was successful. + + FALSE - The conversion was unsuccessful. In this case a buffer for + the unicode string was not allocated. + +--*/ +{ + NTSTATUS ntstatus; + DWORD BufSize; + UNICODE_STRING UnicodeString; + OEM_STRING OemString; + + + // + // Allocate a buffer for the unicode string. + // + + BufSize = (strlen(OemIn) + 1) * sizeof(WCHAR); + + *UnicodeOut = LocalAlloc(LMEM_ZEROINIT, BufSize); + + if (*UnicodeOut == NULL) { + KdPrint(("NWWORKSTATION: NwConvertToUnicode:LocalAlloc failed %lu\n", + GetLastError())); + return FALSE; + } + + // + // Initialize the string structures + // + RtlInitAnsiString((PANSI_STRING) &OemString, OemIn); + + UnicodeString.Buffer = *UnicodeOut; + UnicodeString.MaximumLength = (USHORT) BufSize; + UnicodeString.Length = 0; + + // + // Call the conversion function. + // + ntstatus = RtlOemStringToUnicodeString( + &UnicodeString, // Destination + &OemString, // Source + FALSE // Allocate the destination + ); + + if (ntstatus != STATUS_SUCCESS) { + + KdPrint(("NWWORKSTATION: NwConvertToUnicode: RtlOemStringToUnicodeString failure x%08lx\n", + ntstatus)); + + (void) LocalFree((HLOCAL) *UnicodeOut); + *UnicodeOut = NULL; + return FALSE; + } + + *UnicodeOut = UnicodeString.Buffer; + + return TRUE; + +} diff --git a/private/nw/svcdlls/nwwks/lib/reg.c b/private/nw/svcdlls/nwwks/lib/reg.c new file mode 100644 index 000000000..2259d0f90 --- /dev/null +++ b/private/nw/svcdlls/nwwks/lib/reg.c @@ -0,0 +1,1010 @@ +/*++ + +Copyright (c) 1993 Microsoft Corporation + +Module Name: + + reg.c + +Abstract: + + This module provides helpers to call the registry used by both + the client and server sides of the workstation. + +Author: + + Rita Wong (ritaw) 22-Apr-1993 + +--*/ + +#include <stdlib.h> +#include <stdio.h> + +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> + +#include <windef.h> +#include <winerror.h> +#include <winbase.h> +#include <winreg.h> + +#include <nwsnames.h> +#include <nwreg.h> +#include <nwapi.h> +#include <lmcons.h> +#include <lmerr.h> + +#define LMSERVER_LINKAGE_REGKEY L"System\\CurrentControlSet\\Services\\LanmanServer\\Linkage" +#define OTHERDEPS_VALUENAME L"OtherDependencies" + +// +// Forward Declare +// + +static +DWORD +NwRegQueryValueExW( + IN HKEY hKey, + IN LPWSTR lpValueName, + OUT LPDWORD lpReserved, + OUT LPDWORD lpType, + OUT LPBYTE lpData, + IN OUT LPDWORD lpcbData + ); + +static +DWORD +EnumAndDeleteShares( + VOID + ) ; + +DWORD +CalcNullNullSize( + WCHAR *pszNullNull + ) ; + +WCHAR * +FindStringInNullNull( + WCHAR *pszNullNull, + WCHAR *pszString + ) ; + +VOID +RemoveNWCFromNullNullList( + WCHAR *OtherDeps + ) ; + + + + +DWORD +NwReadRegValue( + IN HKEY Key, + IN LPWSTR ValueName, + OUT LPWSTR *Value + ) +/*++ + +Routine Description: + + This function allocates the output buffer and reads the requested + value from the registry into it. + +Arguments: + + Key - Supplies opened handle to the key to read from. + + ValueName - Supplies name of the value to retrieve data. + + Value - Returns a pointer to the output buffer which points to + the memory allocated and contains the data read in from the + registry. This pointer must be freed with LocalFree when done. + +Return Value: + + ERROR_NOT_ENOUGH_MEMORY - Failed to create buffer to read value into. + + Error from registry call. + +--*/ +{ + LONG RegError; + DWORD NumRequired = 0; + DWORD ValueType; + + + // + // Set returned buffer pointer to NULL. + // + *Value = NULL; + + RegError = NwRegQueryValueExW( + Key, + ValueName, + NULL, + &ValueType, + (LPBYTE) NULL, + &NumRequired + ); + + if (RegError != ERROR_SUCCESS && NumRequired > 0) { + + if ((*Value = (LPWSTR) LocalAlloc( + LMEM_ZEROINIT, + (UINT) NumRequired + )) == NULL) { + + KdPrint(("NWWORKSTATION: NwReadRegValue: LocalAlloc of size %lu failed %lu\n", + NumRequired, GetLastError())); + + return ERROR_NOT_ENOUGH_MEMORY; + } + + RegError = NwRegQueryValueExW( + Key, + ValueName, + NULL, + &ValueType, + (LPBYTE) *Value, + &NumRequired + ); + } + else if (RegError == ERROR_SUCCESS) { + KdPrint(("NWWORKSTATION: NwReadRegValue got SUCCESS with NULL buffer.")); + return ERROR_FILE_NOT_FOUND; + } + + if (RegError != ERROR_SUCCESS) { + + if (*Value != NULL) { + (void) LocalFree((HLOCAL) *Value); + *Value = NULL; + } + + return (DWORD) RegError; + } + + return NO_ERROR; +} + + +static +DWORD +NwRegQueryValueExW( + IN HKEY hKey, + IN LPWSTR lpValueName, + OUT LPDWORD lpReserved, + OUT LPDWORD lpType, + OUT LPBYTE lpData, + IN OUT LPDWORD lpcbData + ) +/*++ + +Routine Description: + + This routine supports the same functionality as Win32 RegQueryValueEx + API, except that it works. It returns the correct lpcbData value when + a NULL output buffer is specified. + + This code is stolen from the service controller. + +Arguments: + + same as RegQueryValueEx + +Return Value: + + NO_ERROR or reason for failure. + +--*/ +{ + NTSTATUS ntstatus; + UNICODE_STRING ValueName; + PKEY_VALUE_FULL_INFORMATION KeyValueInfo; + DWORD BufSize; + + + UNREFERENCED_PARAMETER(lpReserved); + + // + // Make sure we have a buffer size if the buffer is present. + // + if ((ARGUMENT_PRESENT(lpData)) && (! ARGUMENT_PRESENT(lpcbData))) { + return ERROR_INVALID_PARAMETER; + } + + RtlInitUnicodeString(&ValueName, lpValueName); + + // + // Allocate memory for the ValueKeyInfo + // + BufSize = *lpcbData + sizeof(KEY_VALUE_FULL_INFORMATION) + + ValueName.Length + - sizeof(WCHAR); // subtract memory for 1 char because it's included + // in the sizeof(KEY_VALUE_FULL_INFORMATION). + + KeyValueInfo = (PKEY_VALUE_FULL_INFORMATION) LocalAlloc( + LMEM_ZEROINIT, + (UINT) BufSize + ); + + if (KeyValueInfo == NULL) { + KdPrint(("NWWORKSTATION: NwRegQueryValueExW: LocalAlloc failed %lu\n", + GetLastError())); + return ERROR_NOT_ENOUGH_MEMORY; + } + + ntstatus = NtQueryValueKey( + hKey, + &ValueName, + KeyValueFullInformation, + (PVOID) KeyValueInfo, + (ULONG) BufSize, + (PULONG) &BufSize + ); + + if ((NT_SUCCESS(ntstatus) || (ntstatus == STATUS_BUFFER_OVERFLOW)) + && ARGUMENT_PRESENT(lpcbData)) { + + *lpcbData = KeyValueInfo->DataLength; + } + + if (NT_SUCCESS(ntstatus)) { + + if (ARGUMENT_PRESENT(lpType)) { + *lpType = KeyValueInfo->Type; + } + + + if (ARGUMENT_PRESENT(lpData)) { + memcpy( + lpData, + (LPBYTE)KeyValueInfo + KeyValueInfo->DataOffset, + KeyValueInfo->DataLength + ); + } + } + + (void) LocalFree((HLOCAL) KeyValueInfo); + + return RtlNtStatusToDosError(ntstatus); + +} + +VOID +NwLuidToWStr( + IN PLUID LogonId, + OUT LPWSTR LogonIdStr + ) +/*++ + +Routine Description: + + This routine converts a LUID into a string in hex value format so + that it can be used as a registry key. + +Arguments: + + LogonId - Supplies the LUID. + + LogonIdStr - Receives the string. This routine assumes that this + buffer is large enough to fit 17 characters. + +Return Value: + + None. + +--*/ +{ + swprintf(LogonIdStr, L"%08lx%08lx", LogonId->HighPart, LogonId->LowPart); +} + +VOID +NwWStrToLuid( + IN LPWSTR LogonIdStr, + OUT PLUID LogonId + ) +/*++ + +Routine Description: + + This routine converts a string in hex value format into a LUID. + +Arguments: + + LogonIdStr - Supplies the string. + + LogonId - Receives the LUID. + +Return Value: + + None. + +--*/ +{ + swscanf(LogonIdStr, L"%08lx%08lx", &LogonId->HighPart, &LogonId->LowPart); +} + +VOID +NwDeleteCurrentUser( + VOID + ) +/*++ + +Routine Description: + + This routine deletes the current user value under the parameters key. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + LONG RegError; + HKEY WkstaKey; + + // + // Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services + // \NWCWorkstation\Parameters + // + RegError = RegOpenKeyExW( + HKEY_LOCAL_MACHINE, + NW_WORKSTATION_REGKEY, + REG_OPTION_NON_VOLATILE, + KEY_READ | KEY_WRITE | DELETE, + &WkstaKey + ); + + if (RegError != NO_ERROR) { + KdPrint(("NWPROVAU: NwpInitializeRegistry open NWCWorkstation\\Parameters key unexpected error %lu!\n", + RegError)); + return; + } + + // + // Delete CurrentUser value first so that the workstation won't be + // reading this stale value. Ignore error since it may not exist. + // + (void) RegDeleteValueW( + WkstaKey, + NW_CURRENTUSER_VALUENAME + ); + + (void) RegCloseKey(WkstaKey); +} + +DWORD +NwDeleteServiceLogon( + IN PLUID Id OPTIONAL + ) +/*++ + +Routine Description: + + This routine deletes a specific service logon ID key in the registry + if a logon ID is specified, otherwise it deletes all service logon + ID keys. + +Arguments: + + Id - Supplies the logon ID to delete. NULL means delete all. + +Return Status: + + None. + +--*/ +{ + LONG RegError; + LONG DelError; + HKEY ServiceLogonKey; + + WCHAR LogonIdKey[NW_MAX_LOGON_ID_LEN]; + + + RegError = RegOpenKeyExW( + HKEY_LOCAL_MACHINE, + NW_SERVICE_LOGON_REGKEY, + REG_OPTION_NON_VOLATILE, + KEY_READ | KEY_WRITE | DELETE, + &ServiceLogonKey + ); + + if (RegError != ERROR_SUCCESS) { + return RegError; + } + + if (ARGUMENT_PRESENT(Id)) { + + // + // Delete the key specified. + // + NwLuidToWStr(Id, LogonIdKey); + + DelError = RegDeleteKeyW(ServiceLogonKey, LogonIdKey); + + } + else { + + // + // Delete all service logon ID keys. + // + + do { + + RegError = RegEnumKeyW( + ServiceLogonKey, + 0, + LogonIdKey, + sizeof(LogonIdKey) / sizeof(WCHAR) + ); + + if (RegError == ERROR_SUCCESS) { + + // + // Got a logon id key, delete it. + // + + DelError = RegDeleteKeyW(ServiceLogonKey, LogonIdKey); + } + else if (RegError != ERROR_NO_MORE_ITEMS) { + KdPrint((" NwDeleteServiceLogon: failed to enum logon IDs %lu\n", RegError)); + } + + } while (RegError == ERROR_SUCCESS); + } + + (void) RegCloseKey(ServiceLogonKey); + + return ((DWORD) DelError); +} + + + +DWORD +NwpRegisterGatewayShare( + IN LPWSTR ShareName, + IN LPWSTR DriveName + ) +/*++ + +Routine Description: + + This routine remembers that a gateway share has been created so + that it can be cleanup up when NWCS is uninstalled. + +Arguments: + + ShareName - name of share + DriveName - name of drive that is shared + +Return Status: + + Win32 error of any failure. + +--*/ +{ + DWORD status ; + + + // + // make sure we have valid parameters + // + if (ShareName && DriveName) + { + HKEY hKey ; + DWORD dwDisposition ; + + // + // + // Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services + // \NWCWorkstation\Shares (create it if not there) + // + status = RegCreateKeyExW( + HKEY_LOCAL_MACHINE, + NW_WORKSTATION_GATEWAY_SHARES, + 0, + L"", + REG_OPTION_NON_VOLATILE, + KEY_WRITE, // desired access + NULL, // default security + &hKey, + &dwDisposition // ignored + ); + + if ( status ) + return status ; + + // + // wtite out value with valuename=sharename, valuedata=drive + // + status = RegSetValueExW( + hKey, + ShareName, + 0, + REG_SZ, + (LPBYTE) DriveName, + (wcslen(DriveName)+1) * sizeof(WCHAR)) ; + + (void) RegCloseKey( hKey ); + } + else + status = ERROR_INVALID_PARAMETER ; + + return status ; + +} + +DWORD +NwpCleanupGatewayShares( + VOID + ) +/*++ + +Routine Description: + + This routine cleans up all persistent share info and also tidies + up the registry for NWCS. Later is not needed in uninstall, but is + there so we have a single routine that completely disables the + gateway. + +Arguments: + + None. + +Return Status: + + Win32 error for failed APIs. + +--*/ +{ + DWORD status, FinalStatus = NO_ERROR ; + HKEY WkstaKey = NULL, + ServerLinkageKey = NULL ; + LPWSTR OtherDeps = NULL ; + + // + // Enumeratre and delete all shares + // + FinalStatus = status = EnumAndDeleteShares() ; + + // + // if update registry by cleaning out both Drive and Shares keys. + // ignore return values here. the keys may not be present. + // + (void) RegDeleteKeyW( + HKEY_LOCAL_MACHINE, + NW_WORKSTATION_GATEWAY_DRIVES + ) ; + + (void) RegDeleteKeyW( + HKEY_LOCAL_MACHINE, + NW_WORKSTATION_GATEWAY_SHARES + ) ; + + // + // Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services + // \NWCWorkstation\Parameters + // + status = RegOpenKeyExW( + HKEY_LOCAL_MACHINE, + NW_WORKSTATION_REGKEY, + REG_OPTION_NON_VOLATILE, // options + KEY_WRITE, // desired access + &WkstaKey + ); + + if (status == ERROR_SUCCESS) + { + // + // delete the gateway account and gateway enabled flag. + // ignore failures here (the values may not be present) + // + (void) RegDeleteValueW( + WkstaKey, + NW_GATEWAYACCOUNT_VALUENAME + ) ; + (void) RegDeleteValueW( + WkstaKey, + NW_GATEWAY_ENABLE + ) ; + + (void) RegCloseKey( WkstaKey ); + } + + // + // store new status if necessary + // + if (FinalStatus == NO_ERROR) + FinalStatus = status ; + + // + // Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services + // \LanmanServer\Linkage + // + status = RegOpenKeyExW( + HKEY_LOCAL_MACHINE, + LMSERVER_LINKAGE_REGKEY, + REG_OPTION_NON_VOLATILE, // options + KEY_WRITE | KEY_READ, // desired access + &ServerLinkageKey + ); + + if (status == ERROR_SUCCESS) + { + // + // remove us from the OtherDependencies. + // ignore read failures here (it may not be present) + // + status = NwReadRegValue( + ServerLinkageKey, + OTHERDEPS_VALUENAME, + &OtherDeps + ); + + if (status == NO_ERROR) + { + // + // this call munges the list to remove NWC if there. + // + RemoveNWCFromNullNullList(OtherDeps) ; + + status = RegSetValueExW( + ServerLinkageKey, + OTHERDEPS_VALUENAME, + 0, + REG_MULTI_SZ, + (BYTE *)OtherDeps, + CalcNullNullSize(OtherDeps) * sizeof(WCHAR)) ; + + (void) LocalFree(OtherDeps) ; + } + else + { + status = NO_ERROR ; + } + + (void) RegCloseKey( ServerLinkageKey ); + } + + // + // store new status if necessary + // + if (FinalStatus == NO_ERROR) + FinalStatus = status ; + + + return (FinalStatus) ; +} + +DWORD +NwpClearGatewayShare( + IN LPWSTR ShareName + ) +/*++ + +Routine Description: + + This routine deletes a specific share from the remembered gateway + shares in the registry. + +Arguments: + + ShareName - share value to delete + +Return Status: + + Win32 status code. + +--*/ +{ + DWORD status = NO_ERROR ; + + // + // check that paramter is non null + // + if (ShareName) + { + HKEY hKey ; + + // + // + // Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services + // \NWCWorkstation\Drives + // + status = RegOpenKeyExW( + HKEY_LOCAL_MACHINE, + NW_WORKSTATION_GATEWAY_SHARES, + REG_OPTION_NON_VOLATILE, // options + KEY_WRITE, // desired access + &hKey + ); + + if ( status ) + return status ; + + status = RegDeleteValueW( + hKey, + ShareName + ) ; + + (void) RegCloseKey( hKey ); + } + else + status = ERROR_INVALID_PARAMETER ; + + return status ; +} + +typedef NET_API_STATUS (*PF_NETSHAREDEL) ( + LPWSTR server, + LPWSTR name, + DWORD reserved) ; + +#define NETSHAREDELSTICKY_API "NetShareDelSticky" +#define NETSHAREDEL_API "NetShareDel" +#define NETAPI_DLL L"NETAPI32" + +DWORD +EnumAndDeleteShares( + VOID + ) +/*++ + +Routine Description: + + This routine removes all persister share info in the server for + all gateway shares. + +Arguments: + + None. + +Return Status: + + Win32 error code. + +--*/ +{ + DWORD err, i, type ; + HKEY hKey = NULL ; + FILETIME FileTime ; + HANDLE hNetapi = NULL ; + PF_NETSHAREDEL pfNetShareDel, pfNetShareDelSticky ; + WCHAR Class[256], Share[NNLEN+1], Device[MAX_PATH+1] ; + DWORD dwClass, dwSubKeys, dwMaxSubKey, dwMaxClass, + dwValues, dwMaxValueName, dwMaxValueData, dwSDLength, + dwShareLength, dwDeviceLength ; + + // + // load the library so that not everyone needs link to netapi32 + // + if (!(hNetapi = LoadLibraryW(NETAPI_DLL))) + return (GetLastError()) ; + + // + // get addresses of the 2 functions we are interested in + // + if (!(pfNetShareDel = (PF_NETSHAREDEL) GetProcAddress(hNetapi, + NETSHAREDEL_API))) + { + err = GetLastError() ; + goto ExitPoint ; + } + + if (!(pfNetShareDelSticky = (PF_NETSHAREDEL) GetProcAddress(hNetapi, + NETSHAREDELSTICKY_API))) + { + err = GetLastError() ; + goto ExitPoint ; + } + + // + // Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services + // \NWCGateway\Shares + // + err = RegOpenKeyExW( + HKEY_LOCAL_MACHINE, + NW_WORKSTATION_GATEWAY_SHARES, + REG_OPTION_NON_VOLATILE, // options + KEY_READ, // desired access + &hKey + ); + + if ( err ) + goto ExitPoint ; + + // + // read the info about that key + // + dwClass = sizeof(Class)/sizeof(Class[0]) ; + err = RegQueryInfoKeyW(hKey, + Class, + &dwClass, + NULL, + &dwSubKeys, + &dwMaxSubKey, + &dwMaxClass, + &dwValues, + &dwMaxValueName, + &dwMaxValueData, + &dwSDLength, + &FileTime) ; + if ( err ) + { + goto ExitPoint ; + } + + // + // for each value found, we have a share to delete + // + for (i = 0; i < dwValues; i++) + { + dwShareLength = sizeof(Share)/sizeof(Share[0]) ; + dwDeviceLength = sizeof(Device) ; + type = REG_SZ ; + err = RegEnumValueW(hKey, + i, + Share, + &dwShareLength, + NULL, + &type, + (LPBYTE)Device, + &dwDeviceLength) ; + + // + // cleanup the share. try delete the share proper. if not + // there, remove the sticky info instead. + // + if (!err) + { + err = (*pfNetShareDel)(NULL, Share, 0) ; + + if (err == NERR_NetNameNotFound) + { + (void) (*pfNetShareDelSticky)(NULL, Share, 0) ; + } + } + + // + // ignore errors within the loop. we can to carry on to + // cleanup as much as possible. + // + err = NO_ERROR ; + } + + + +ExitPoint: + + if (hKey) + (void) RegCloseKey( hKey ); + + if (hNetapi) + (void) FreeLibrary(hNetapi) ; + + return err ; +} + + +DWORD +CalcNullNullSize( + WCHAR *pszNullNull + ) +/*++ + +Routine Description: + + Walk thru a NULL NULL string, counting the number of + characters, including the 2 nulls at the end. + +Arguments: + + Pointer to a NULL NULL string + +Return Status: + + Count of number of *characters*. See description. + +--*/ +{ + + DWORD dwSize = 0 ; + WCHAR *pszTmp = pszNullNull ; + + if (!pszNullNull) + return 0 ; + + while (*pszTmp) + { + DWORD dwLen = wcslen(pszTmp) + 1 ; + + dwSize += dwLen ; + pszTmp += dwLen ; + } + + return (dwSize+1) ; +} + +WCHAR * +FindStringInNullNull( + WCHAR *pszNullNull, + WCHAR *pszString +) +/*++ + +Routine Description: + + Walk thru a NULL NULL string, looking for the search string + +Arguments: + + pszNullNull: the string list we will search. + pszString: what we are searching for. + +Return Status: + + The start of the string if found. Null, otherwise. + +--*/ +{ + WCHAR *pszTmp = pszNullNull ; + + if (!pszNullNull || !*pszNullNull) + return NULL ; + + do { + + if (_wcsicmp(pszTmp,pszString)==0) + return pszTmp ; + + pszTmp += wcslen(pszTmp) + 1 ; + + } while (*pszTmp) ; + + return NULL ; +} + +VOID +RemoveNWCFromNullNullList( + WCHAR *OtherDeps + ) +/*++ + +Routine Description: + + Remove the NWCWorkstation string from a null null string. + +Arguments: + + OtherDeps: the string list we will munge. + +Return Status: + + None. + +--*/ +{ + LPWSTR pszTmp0, pszTmp1 ; + + // + // find the NWCWorkstation string + // + pszTmp0 = FindStringInNullNull(OtherDeps, NW_WORKSTATION_SERVICE) ; + + if (!pszTmp0) + return ; + + pszTmp1 = pszTmp0 + wcslen(pszTmp0) + 1 ; // skip past it + + // + // shift the rest up + // + memmove(pszTmp0, pszTmp1, CalcNullNullSize(pszTmp1)*sizeof(WCHAR)) ; +} diff --git a/private/nw/svcdlls/nwwks/lib/sources b/private/nw/svcdlls/nwwks/lib/sources new file mode 100644 index 000000000..5911ce45b --- /dev/null +++ b/private/nw/svcdlls/nwwks/lib/sources @@ -0,0 +1,47 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +MAJORCOMP=nw +MINORCOMP=nwwlib + +TARGETNAME=nwwlib +TARGETPATH=obj +TARGETTYPE=LIBRARY + +INCLUDES=..\inc;..\..\..\inc;$(_NTROOT)\private\inc + +SOURCES= \ + lsa.c \ + reg.c \ + misc.c \ + splutil.c + +UNICODE=1 + +NET_C_DEFINES=-DRPC_NO_WINDOWS_H -DNOT_USED + +UMTYPE=console + +UMLIBS= \ + obj\*\nwwlib.lib + +OPTIONAL_UMTEST= diff --git a/private/nw/svcdlls/nwwks/lib/splutil.c b/private/nw/svcdlls/nwwks/lib/splutil.c new file mode 100644 index 000000000..4f0c6fd9b --- /dev/null +++ b/private/nw/svcdlls/nwwks/lib/splutil.c @@ -0,0 +1,351 @@ +/*++ + +Copyright (c) 1993 Microsoft Corporation + +Module Name: + + splutil.c + +Abstract: + + This module provides all the utility functions for the netware print + provider. + +Author: + + Yi-Hsin Sung (yihsins) 15-Apr-1993 + +Revision History: + +--*/ + +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> + +#include <windows.h> +#include <winspool.h> +#include <splutil.h> + +DWORD PrinterInfo1Offsets[]={offsetof(LPPRINTER_INFO_1W, pDescription), + offsetof(LPPRINTER_INFO_1W, pName), + offsetof(LPPRINTER_INFO_1W, pComment), + 0xFFFFFFFF}; + +DWORD PrinterInfo2Offsets[]={offsetof(LPPRINTER_INFO_2W, pServerName), + offsetof(LPPRINTER_INFO_2W, pPrinterName), + offsetof(LPPRINTER_INFO_2W, pShareName), + offsetof(LPPRINTER_INFO_2W, pPortName), + offsetof(LPPRINTER_INFO_2W, pDriverName), + offsetof(LPPRINTER_INFO_2W, pComment), + offsetof(LPPRINTER_INFO_2W, pLocation), + offsetof(LPPRINTER_INFO_2W, pDevMode), + offsetof(LPPRINTER_INFO_2W, pSepFile), + offsetof(LPPRINTER_INFO_2W, pPrintProcessor), + offsetof(LPPRINTER_INFO_2W, pDatatype), + offsetof(LPPRINTER_INFO_2W, pParameters), + offsetof(LPPRINTER_INFO_2W, pSecurityDescriptor), + 0xFFFFFFFF}; + +DWORD PrinterInfo3Offsets[]={offsetof(LPPRINTER_INFO_3, pSecurityDescriptor), + 0xFFFFFFFF}; + +DWORD JobInfo1Offsets[]={offsetof(LPJOB_INFO_1W, pPrinterName), + offsetof(LPJOB_INFO_1W, pMachineName), + offsetof(LPJOB_INFO_1W, pUserName), + offsetof(LPJOB_INFO_1W, pDocument), + offsetof(LPJOB_INFO_1W, pDatatype), + offsetof(LPJOB_INFO_1W, pStatus), + 0xFFFFFFFF}; + +DWORD JobInfo2Offsets[]={offsetof(LPJOB_INFO_2W, pPrinterName), + offsetof(LPJOB_INFO_2W, pMachineName), + offsetof(LPJOB_INFO_2W, pUserName), + offsetof(LPJOB_INFO_2W, pDocument), + offsetof(LPJOB_INFO_2W, pNotifyName), + offsetof(LPJOB_INFO_2W, pDatatype), + offsetof(LPJOB_INFO_2W, pPrintProcessor), + offsetof(LPJOB_INFO_2W, pParameters), + offsetof(LPJOB_INFO_2W, pDriverName), + offsetof(LPJOB_INFO_2W, pDevMode), + offsetof(LPJOB_INFO_2W, pStatus), + offsetof(LPJOB_INFO_2W, pSecurityDescriptor), + 0xFFFFFFFF}; + +DWORD AddJobInfo1Offsets[]={offsetof(LPADDJOB_INFO_1W, Path), + 0xFFFFFFFF}; + + +VOID +MarshallUpStructure( + LPBYTE lpStructure, + LPDWORD lpOffsets, + LPBYTE lpBufferStart +) +{ + register DWORD i=0; + + while (lpOffsets[i] != -1) { + + if ((*(LPBYTE *)(lpStructure+lpOffsets[i]))) { + (*(LPBYTE *)(lpStructure+lpOffsets[i]))+=(DWORD)lpBufferStart; + } + + i++; + } +} + + + +VOID +MarshallDownStructure( + LPBYTE lpStructure, + LPDWORD lpOffsets, + LPBYTE lpBufferStart +) +{ + register DWORD i=0; + + if (!lpStructure) + return; + + while (lpOffsets[i] != -1) { + + if ((*(LPBYTE*)(lpStructure+lpOffsets[i]))) { + (*(LPBYTE*)(lpStructure+lpOffsets[i]))-=(DWORD)lpBufferStart; + } + + i++; + } +} + + + +LPVOID +AllocNwSplMem( + DWORD flags, + DWORD cb +) +/*++ + +Routine Description: + + This function will allocate local memory. It will possibly allocate extra + memory and fill this with debugging information for the debugging version. + +Arguments: + + flags - Flags to be passed to LocalAlloc + + cb - The amount of memory to allocate in bytes + +Return Value: + + NON-NULL - A pointer to the allocated memory + +--*/ +{ + LPDWORD pMem; + DWORD cbNew; + +#if DBG + cbNew = cb + 2*sizeof(DWORD); + if (cbNew & 3) + cbNew += sizeof(DWORD) - (cbNew & 3); +#else + cbNew = cb; +#endif + + pMem = (LPDWORD) LocalAlloc( flags, cbNew ); + + if ( !pMem ) + { + KdPrint(("Memory Allocation in AllocNwSplMem failed for %d bytes\n", cbNew)); + return NULL; + } + +#if DBG + *pMem = cb; + *(LPDWORD)((LPBYTE)pMem+cbNew-sizeof(DWORD)) = 0xdeadbeef; + return (LPVOID) (pMem + 1); +#else + return (LPVOID) pMem; +#endif + +} + + + +VOID +FreeNwSplMem( + LPVOID pMem, + DWORD cb +) +/*++ + +Routine Description: + + This function will frees the local memory allocated by AllocSplMem. + Extra checking will be performed in the debug version to ensure that + the size to be freed is indeed the size we allocated through AllocSplMem. + +Arguments: + + pMem - A pointer to the allocated memory + cb - The amount of memory to free + +Return Value: + +--*/ +{ + DWORD cbNew; + LPDWORD pNewMem; + + if ( !pMem ) + return; + + pNewMem = pMem; +#if DBG + pNewMem--; + cbNew = cb + 2*sizeof(DWORD); + if ( cbNew & 3 ) + cbNew += sizeof(DWORD) - (cbNew & 3); + + if ( ( *pNewMem != cb ) + || (*(LPDWORD)((LPBYTE)pNewMem + cbNew - sizeof(DWORD)) != 0xdeadbeef) + ) + { + KdPrint(("Corrupt Memory in FreeNwSplMem : %0lx\n", pNewMem )); + return; + } +#else + cbNew = cb; +#endif + + LocalFree( (LPVOID) pNewMem ); +} + + + +LPWSTR +AllocNwSplStr( + LPWSTR pStr +) +/*++ + +Routine Description: + + This function will allocate enough local memory to store the specified + string, and copy that string to the allocated memory + +Arguments: + + pStr - Pointer to the string that needs to be allocated and stored + +Return Value: + + NON-NULL - A pointer to the allocated memory containing the string + +--*/ +{ + LPWSTR pMem; + + if ( !pStr ) + return NULL; + + if ( pMem = AllocNwSplMem(0, (wcslen(pStr) + 1) * sizeof(WCHAR))) + wcscpy(pMem, pStr); + + return pMem; +} + + + +VOID +FreeNwSplStr( + LPWSTR pStr +) +/*++ + +Routine Description: + + This function will frees the string allocated by AllocSplStr. + Extra checking will be performed in the debug version to ensure that + the size to be freed is indeed the size we allocated through AllocSplStr. + +Arguments: + + pStr - A pointer to the allocated string + +Return Value: + +--*/ +{ + if ( pStr ) + FreeNwSplMem(pStr, (wcslen(pStr) + 1) * sizeof(WCHAR)); +} + + + +BOOL +ValidateUNCName( + LPWSTR pName +) +/*++ + +Routine Description: + + This function will checks whether the given name is a valid UNC + name ( in the form \\server\name) or not. + +Arguments: + + pName - The supplied name + +Return Value: + + TRUE - The name given is a valid UNC name + FALSE - Otherwise + +--*/ +{ + if ( pName + && (*pName++ == L'\\') + && (*pName++ == L'\\') + && (wcschr(pName, L'\\')) + ) + { + return TRUE; + } + + return FALSE; +} + +#ifndef NOT_USED + +LPWSTR +GetNextElement(LPWSTR *pPtr, WCHAR token) +{ + LPWSTR pszRestOfString = *pPtr; + LPWSTR pszRetval = NULL; + LPWSTR pszStr = NULL; + + if ( *pszRestOfString == L'\0') + return NULL; + + if ((pszStr = wcschr (pszRestOfString, token))== NULL ) + { + pszRetval = *pPtr; + *pPtr += wcslen(*pPtr); + return pszRetval; + } + else + { + *pszStr = L'\0'; + pszRetval = *pPtr ; + *pPtr = ++pszStr ; + return pszRetval ; + } +} + +#endif |