From f80022635ee475cd4e6709724b752951b6845e93 Mon Sep 17 00:00:00 2001 From: Steven Edwards Date: Tue, 10 Feb 2004 16:57:59 +0000 Subject: [PATCH] Port of netapi32 from WINE svn path=/trunk/; revision=8131 --- reactos/include/wine/ntstatus.h | 1101 ++++++++++++++ reactos/lib/netapi32/.cvsignore | 6 + reactos/lib/netapi32/Makefile.in | 24 + reactos/lib/netapi32/Makefile.ros-template | 21 + reactos/lib/netapi32/access.c | 528 +++++++ reactos/lib/netapi32/apibuf.c | 102 ++ reactos/lib/netapi32/browsr.c | 62 + reactos/lib/netapi32/nbcmdqueue.c | 199 +++ reactos/lib/netapi32/nbcmdqueue.h | 66 + reactos/lib/netapi32/nbnamecache.c | 218 +++ reactos/lib/netapi32/nbnamecache.h | 82 ++ reactos/lib/netapi32/nbt.c | 1535 ++++++++++++++++++++ reactos/lib/netapi32/netapi32.c | 79 + reactos/lib/netapi32/netapi32.rc | 38 + reactos/lib/netapi32/netapi32.spec | 274 ++++ reactos/lib/netapi32/netapi32_misc.h | 35 + reactos/lib/netapi32/netbios.c | 846 +++++++++++ reactos/lib/netapi32/netbios.h | 183 +++ reactos/lib/netapi32/stubs.c | 64 + reactos/lib/netapi32/wksta.c | 520 +++++++ 20 files changed, 5983 insertions(+) create mode 100644 reactos/include/wine/ntstatus.h create mode 100644 reactos/lib/netapi32/.cvsignore create mode 100644 reactos/lib/netapi32/Makefile.in create mode 100644 reactos/lib/netapi32/Makefile.ros-template create mode 100644 reactos/lib/netapi32/access.c create mode 100644 reactos/lib/netapi32/apibuf.c create mode 100644 reactos/lib/netapi32/browsr.c create mode 100644 reactos/lib/netapi32/nbcmdqueue.c create mode 100644 reactos/lib/netapi32/nbcmdqueue.h create mode 100644 reactos/lib/netapi32/nbnamecache.c create mode 100644 reactos/lib/netapi32/nbnamecache.h create mode 100644 reactos/lib/netapi32/nbt.c create mode 100644 reactos/lib/netapi32/netapi32.c create mode 100644 reactos/lib/netapi32/netapi32.rc create mode 100644 reactos/lib/netapi32/netapi32.spec create mode 100644 reactos/lib/netapi32/netapi32_misc.h create mode 100644 reactos/lib/netapi32/netbios.c create mode 100644 reactos/lib/netapi32/netbios.h create mode 100644 reactos/lib/netapi32/stubs.c create mode 100644 reactos/lib/netapi32/wksta.c diff --git a/reactos/include/wine/ntstatus.h b/reactos/include/wine/ntstatus.h new file mode 100644 index 00000000000..44e33b063b6 --- /dev/null +++ b/reactos/include/wine/ntstatus.h @@ -0,0 +1,1101 @@ +/* + * Win32 definitions for Windows NT + * + * Copyright 1996 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WINE_NTSTATUS_H +#define __WINE_NTSTATUS_H + +#ifndef WIN32_NO_STATUS + +/* + * Exception codes + */ + +#define STATUS_SUCCESS 0x00000000 +#define STATUS_SEVERITY_SUCCESS 0x00000000 +#define STATUS_SEVERITY_INFORMATIONAL 0x00000001 +#define STATUS_SEVERITY_WARNING 0x00000002 +#define STATUS_SEVERITY_ERROR 0x00000003 + +#define STATUS_WAIT_1 0x00000001 +#define STATUS_WAIT_2 0x00000002 +#define STATUS_WAIT_3 0x00000003 +#define STATUS_WAIT_63 0x0000003f +#define STATUS_ABANDONED 0x00000080 +#define STATUS_ABANDONED_WAIT_63 0x000000BF +#define STATUS_KERNEL_APC 0x00000100 +#define STATUS_ALERTED 0x00000101 +#define STATUS_REPARSE 0x00000104 +#define STATUS_MORE_ENTRIES 0x00000105 +#define STATUS_NOT_ALL_ASSIGNED 0x00000106 +#define STATUS_SOME_NOT_MAPPED 0x00000107 +#define STATUS_OPLOCK_BREAK_IN_PROGRESS 0x00000108 +#define STATUS_VOLUME_MOUNTED 0x00000109 +#define STATUS_RXACT_COMMITTED 0x0000010A +#define STATUS_NOTIFY_CLEANUP 0x0000010B +#define STATUS_NOTIFY_ENUM_DIR 0x0000010C +#define STATUS_NO_QUOTAS_FOR_ACCOUNT 0x0000010D +#define STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED 0x0000010E +#define STATUS_PAGE_FAULT_TRANSITION 0x00000110 +#define STATUS_PAGE_FAULT_DEMAND_ZERO 0x00000111 +#define STATUS_PAGE_FAULT_COPY_ON_WRITE 0x00000112 +#define STATUS_PAGE_FAULT_GUARD_PAGE 0x00000113 +#define STATUS_PAGE_FAULT_PAGING_FILE 0x00000114 +#define STATUS_CACHE_PAGE_LOCKED 0x00000115 +#define STATUS_CRASH_DUMP 0x00000116 +#define STATUS_BUFFER_ALL_ZEROS 0x00000117 +#define STATUS_REPARSE_OBJECT 0x00000118 +#define STATUS_RESOURCE_REQUIREMENTS_CHANGED 0x00000119 +#define STATUS_TRANSLATION_COMPLETE 0x00000120 +#define STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY 0x00000121 +#define STATUS_NOTHING_TO_TERMINATE 0x00000122 +#define STATUS_PROCESS_NOT_IN_JOB 0x00000123 +#define STATUS_PROCESS_IN_JOB 0x00000124 +#define STATUS_VOLSNAP_HIBERNATE_READY 0x00000125 +#define STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY 0x00000126 + +#define STATUS_OBJECT_NAME_EXISTS 0x40000000 +#define STATUS_THREAD_WAS_SUSPENDED 0x40000001 +#define STATUS_WORKING_SET_LIMIT_RANGE 0x40000002 +#define STATUS_IMAGE_NOT_AT_BASE 0x40000003 +#define STATUS_RXACT_STATE_CREATED 0x40000004 +#define STATUS_SEGMENT_NOTIFICATION 0x40000005 +#define STATUS_LOCAL_USER_SESSION_KEY 0x40000006 +#define STATUS_BAD_CURRENT_DIRECTORY 0x40000007 +#define STATUS_SERIAL_MORE_WRITES 0x40000008 +#define STATUS_REGISTRY_RECOVERED 0x40000009 +#define STATUS_FT_READ_RECOVERY_FROM_BACKUP 0x4000000A +#define STATUS_FT_WRITE_RECOVERY 0x4000000B +#define STATUS_SERIAL_COUNTER_TIMEOUT 0x4000000C +#define STATUS_NULL_LM_PASSWORD 0x4000000D +#define STATUS_IMAGE_MACHINE_TYPE_MISMATCH 0x4000000E +#define STATUS_RECEIVE_PARTIAL 0x4000000F +#define STATUS_RECEIVE_EXPEDITED 0x40000010 +#define STATUS_RECEIVE_PARTIAL_EXPEDITED 0x40000011 +#define STATUS_EVENT_DONE 0x40000012 +#define STATUS_EVENT_PENDING 0x40000013 +#define STATUS_CHECKING_FILE_SYSTEM 0x40000014 +#define STATUS_FATAL_APP_EXIT 0x40000015 +#define STATUS_PREDEFINED_HANDLE 0x40000016 +#define STATUS_WAS_UNLOCKED 0x40000017 +#define STATUS_SERVICE_NOTIFICATION 0x40000018 +#define STATUS_WAS_LOCKED 0x40000019 +#define STATUS_LOG_HARD_ERROR 0x4000001A +#define STATUS_ALREADY_WIN32 0x4000001B +#define STATUS_WX86_UNSIMULATE 0x4000001C +#define STATUS_WX86_CONTINUE 0x4000001D +#define STATUS_WX86_SINGLE_STEP 0x4000001E +#define STATUS_WX86_BREAKPOINT 0x4000001F +#define STATUS_WX86_EXCEPTION_CONTINUE 0x40000020 +#define STATUS_WX86_EXCEPTION_LASTCHANCE 0x40000021 +#define STATUS_WX86_EXCEPTION_CHAIN 0x40000022 +#define STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE 0x40000023 +#define STATUS_NO_YIELD_PERFORMED 0x40000024 +#define STATUS_TIMER_RESUME_IGNORED 0x40000025 +#define STATUS_ARBITRATION_UNHANDLED 0x40000026 +#define STATUS_CARDBUS_NOT_SUPPORTED 0x40000027 +#define STATUS_WX86_CREATEWX86TIB 0x40000028 +#define STATUS_MP_PROCESSOR_MISMATCH 0x40000029 +#define STATUS_HIBERNATED 0x4000002A +#define STATUS_RESUME_HIBERNATION 0x4000002B +#define STATUS_FIRMWARE_UPDATED 0x4000002C +#define STATUS_WAKE_SYSTEM 0x40000294 +#define STATUS_DS_SHUTTING_DOWN 0x40000370 + +#define RPC_NT_UUID_LOCAL_ONLY 0x40020056 +#define RPC_NT_SEND_INCOMPLETE 0x400200AF + +#define STATUS_CTX_CDM_CONNECT 0x400A0004 +#define STATUS_CTX_CDM_DISCONNECT 0x400A0005 + +#define STATUS_SXS_RELEASE_ACTIVATION_CONTEXT 0x4015000D + +#define STATUS_GUARD_PAGE_VIOLATION 0x80000001 +#define STATUS_DATATYPE_MISALIGNMENT 0x80000002 +#define STATUS_BREAKPOINT 0x80000003 +#define STATUS_SINGLE_STEP 0x80000004 +#define STATUS_BUFFER_OVERFLOW 0x80000005 +#define STATUS_NO_MORE_FILES 0x80000006 +#define STATUS_WAKE_SYSTEM_DEBUGGER 0x80000007 + +#define STATUS_HANDLES_CLOSED 0x8000000A +#define STATUS_NO_INHERITANCE 0x8000000B +#define STATUS_GUID_SUBSTITUTION_MADE 0x8000000C +#define STATUS_PARTIAL_COPY 0x8000000D +#define STATUS_DEVICE_PAPER_EMPTY 0x8000000E +#define STATUS_DEVICE_POWERED_OFF 0x8000000F +#define STATUS_DEVICE_OFF_LINE 0x80000010 +#define STATUS_DEVICE_BUSY 0x80000011 +#define STATUS_NO_MORE_EAS 0x80000012 +#define STATUS_INVALID_EA_NAME 0x80000013 +#define STATUS_EA_LIST_INCONSISTENT 0x80000014 +#define STATUS_INVALID_EA_FLAG 0x80000015 +#define STATUS_VERIFY_REQUIRED 0x80000016 +#define STATUS_EXTRANEOUS_INFORMATION 0x80000017 +#define STATUS_RXACT_COMMIT_NECESSARY 0x80000018 +#define STATUS_NO_MORE_ENTRIES 0x8000001A +#define STATUS_FILEMARK_DETECTED 0x8000001B +#define STATUS_MEDIA_CHANGED 0x8000001C +#define STATUS_BUS_RESET 0x8000001D +#define STATUS_END_OF_MEDIA 0x8000001E +#define STATUS_BEGINNING_OF_MEDIA 0x8000001F +#define STATUS_MEDIA_CHECK 0x80000020 +#define STATUS_SETMARK_DETECTED 0x80000021 +#define STATUS_NO_DATA_DETECTED 0x80000022 +#define STATUS_REDIRECTOR_HAS_OPEN_HANDLES 0x80000023 +#define STATUS_SERVER_HAS_OPEN_HANDLES 0x80000024 +#define STATUS_ALREADY_DISCONNECTED 0x80000025 +#define STATUS_LONGJUMP 0x80000026 +#define STATUS_CLEANER_CARTRIDGE_INSTALLED 0x80000027 +#define STATUS_PLUGPLAY_QUERY_VETOED 0x80000028 +#define STATUS_UNWIND_CONSOLIDATE 0x80000029 +#define STATUS_REGISTRY_HIVE_RECOVERED 0x8000002A +#define STATUS_DLL_MIGHT_BE_INSECURE 0x8000002B +#define STATUS_DLL_MIGHT_BE_INCOMPATIBLE 0x8000002C + +#define STATUS_DEVICE_REQUIRES_CLEANING 0x80000288 +#define STATUS_DEVICE_DOOR_OPEN 0x80000289 + +#define STATUS_CLUSTER_NODE_ALREADY_UP 0x80130001 +#define STATUS_CLUSTER_NODE_ALREADY_DOWN 0x80130002 +#define STATUS_CLUSTER_NETWORK_ALREADY_ONLINE 0x80130003 +#define STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE 0x80130004 +#define STATUS_CLUSTER_NODE_ALREADY_MEMBER 0x80130005 + +#define STATUS_UNSUCCESSFUL 0xC0000001 +#define STATUS_NOT_IMPLEMENTED 0xC0000002 +#define STATUS_INVALID_INFO_CLASS 0xC0000003 +#define STATUS_INFO_LENGTH_MISMATCH 0xC0000004 +#define STATUS_ACCESS_VIOLATION 0xC0000005 +#define STATUS_IN_PAGE_ERROR 0xC0000006 +#define STATUS_PAGEFILE_QUOTA 0xC0000007 +#define STATUS_BAD_INITIAL_STACK 0xC0000009 +#define STATUS_BAD_INITIAL_PC 0xC000000A +#define STATUS_INVALID_CID 0xC000000B +#define STATUS_TIMER_NOT_CANCELED 0xC000000C +#define STATUS_INVALID_PARAMETER 0xC000000D +#define STATUS_NO_SUCH_DEVICE 0xC000000E +#define STATUS_NO_SUCH_FILE 0xC000000F +#define STATUS_INVALID_DEVICE_REQUEST 0xC0000010 +#define STATUS_END_OF_FILE 0xC0000011 +#define STATUS_WRONG_VOLUME 0xC0000012 +#define STATUS_NO_MEDIA_IN_DEVICE 0xC0000013 +#define STATUS_UNRECOGNIZED_MEDIA 0xC0000014 +#define STATUS_NONEXISTENT_SECTOR 0xC0000015 +#define STATUS_MORE_PROCESSING_REQUIRED 0xC0000016 +#define STATUS_NO_MEMORY 0xC0000017 +#define STATUS_CONFLICTING_ADDRESSES 0xC0000018 +#define STATUS_NOT_MAPPED_VIEW 0xC0000019 +#define STATUS_UNABLE_TO_FREE_VM 0xC000001A +#define STATUS_UNABLE_TO_DELETE_SECTION 0xC000001B +#define STATUS_INVALID_SYSTEM_SERVICE 0xC000001C +#define STATUS_ILLEGAL_INSTRUCTION 0xC000001D +#define STATUS_INVALID_LOCK_SEQUENCE 0xC000001E +#define STATUS_INVALID_VIEW_SIZE 0xC000001F +#define STATUS_INVALID_FILE_FOR_SECTION 0xC0000020 +#define STATUS_ALREADY_COMMITTED 0xC0000021 +#define STATUS_ACCESS_DENIED 0xC0000022 +#define STATUS_BUFFER_TOO_SMALL 0xC0000023 +#define STATUS_OBJECT_TYPE_MISMATCH 0xC0000024 +#define STATUS_NONCONTINUABLE_EXCEPTION 0xC0000025 +#define STATUS_INVALID_DISPOSITION 0xC0000026 +#define STATUS_UNWIND 0xC0000027 +#define STATUS_BAD_STACK 0xC0000028 +#define STATUS_INVALID_UNWIND_TARGET 0xC0000029 +#define STATUS_NOT_LOCKED 0xC000002A +#define STATUS_PARITY_ERROR 0xC000002B +#define STATUS_UNABLE_TO_DECOMMIT_VM 0xC000002C +#define STATUS_NOT_COMMITTED 0xC000002D +#define STATUS_INVALID_PORT_ATTRIBUTES 0xC000002E +#define STATUS_PORT_MESSAGE_TOO_LONG 0xC000002F +#define STATUS_INVALID_PARAMETER_MIX 0xC0000030 +#define STATUS_INVALID_QUOTA_LOWER 0xC0000031 +#define STATUS_DISK_CORRUPT_ERROR 0xC0000032 +#define STATUS_OBJECT_NAME_INVALID 0xC0000033 +#define STATUS_OBJECT_NAME_NOT_FOUND 0xC0000034 +#define STATUS_OBJECT_NAME_COLLISION 0xC0000035 +#define STATUS_PORT_DISCONNECTED 0xC0000037 +#define STATUS_DEVICE_ALREADY_ATTACHED 0xC0000038 +#define STATUS_OBJECT_PATH_INVALID 0xC0000039 +#define STATUS_OBJECT_PATH_NOT_FOUND 0xC000003A +#define STATUS_OBJECT_PATH_SYNTAX_BAD 0xC000003B +#define STATUS_DATA_OVERRUN 0xC000003C +#define STATUS_DATA_LATE_ERROR 0xC000003D +#define STATUS_DATA_ERROR 0xC000003E +#define STATUS_CRC_ERROR 0xC000003F +#define STATUS_SECTION_TOO_BIG 0xC0000040 +#define STATUS_PORT_CONNECTION_REFUSED 0xC0000041 +#define STATUS_INVALID_PORT_HANDLE 0xC0000042 +#define STATUS_SHARING_VIOLATION 0xC0000043 +#define STATUS_QUOTA_EXCEEDED 0xC0000044 +#define STATUS_INVALID_PAGE_PROTECTION 0xC0000045 +#define STATUS_MUTANT_NOT_OWNED 0xC0000046 +#define STATUS_SEMAPHORE_LIMIT_EXCEEDED 0xC0000047 +#define STATUS_PORT_ALREADY_SET 0xC0000048 +#define STATUS_SECTION_NOT_IMAGE 0xC0000049 +#define STATUS_SUSPEND_COUNT_EXCEEDED 0xC000004A +#define STATUS_THREAD_IS_TERMINATING 0xC000004B +#define STATUS_BAD_WORKING_SET_LIMIT 0xC000004C +#define STATUS_INCOMPATIBLE_FILE_MAP 0xC000004D +#define STATUS_SECTION_PROTECTION 0xC000004E +#define STATUS_EAS_NOT_SUPPORTED 0xC000004F +#define STATUS_EA_TOO_LARGE 0xC0000050 +#define STATUS_NONEXISTENT_EA_ENTRY 0xC0000051 +#define STATUS_NO_EAS_ON_FILE 0xC0000052 +#define STATUS_EA_CORRUPT_ERROR 0xC0000053 +#define STATUS_FILE_LOCK_CONFLICT 0xC0000054 +#define STATUS_LOCK_NOT_GRANTED 0xC0000055 +#define STATUS_DELETE_PENDING 0xC0000056 +#define STATUS_CTL_FILE_NOT_SUPPORTED 0xC0000057 +#define STATUS_UNKNOWN_REVISION 0xC0000058 +#define STATUS_REVISION_MISMATCH 0xC0000059 +#define STATUS_INVALID_OWNER 0xC000005A +#define STATUS_INVALID_PRIMARY_GROUP 0xC000005B +#define STATUS_NO_IMPERSONATION_TOKEN 0xC000005C +#define STATUS_CANT_DISABLE_MANDATORY 0xC000005D +#define STATUS_NO_LOGON_SERVERS 0xC000005E +#define STATUS_NO_SUCH_LOGON_SESSION 0xC000005F +#define STATUS_NO_SUCH_PRIVILEGE 0xC0000060 +#define STATUS_PRIVILEGE_NOT_HELD 0xC0000061 +#define STATUS_INVALID_ACCOUNT_NAME 0xC0000062 +#define STATUS_USER_EXISTS 0xC0000063 +#define STATUS_NO_SUCH_USER 0xC0000064 +#define STATUS_GROUP_EXISTS 0xC0000065 +#define STATUS_NO_SUCH_GROUP 0xC0000066 +#define STATUS_MEMBER_IN_GROUP 0xC0000067 +#define STATUS_MEMBER_NOT_IN_GROUP 0xC0000068 +#define STATUS_LAST_ADMIN 0xC0000069 +#define STATUS_WRONG_PASSWORD 0xC000006A +#define STATUS_ILL_FORMED_PASSWORD 0xC000006B +#define STATUS_PASSWORD_RESTRICTION 0xC000006C +#define STATUS_LOGON_FAILURE 0xC000006D +#define STATUS_ACCOUNT_RESTRICTION 0xC000006E +#define STATUS_INVALID_LOGON_HOURS 0xC000006F +#define STATUS_INVALID_WORKSTATION 0xC0000070 +#define STATUS_PASSWORD_EXPIRED 0xC0000071 +#define STATUS_ACCOUNT_DISABLED 0xC0000072 +#define STATUS_NONE_MAPPED 0xC0000073 +#define STATUS_TOO_MANY_LUIDS_REQUESTED 0xC0000074 +#define STATUS_LUIDS_EXHAUSTED 0xC0000075 +#define STATUS_INVALID_SUB_AUTHORITY 0xC0000076 +#define STATUS_INVALID_ACL 0xC0000077 +#define STATUS_INVALID_SID 0xC0000078 +#define STATUS_INVALID_SECURITY_DESCR 0xC0000079 +#define STATUS_PROCEDURE_NOT_FOUND 0xC000007A +#define STATUS_INVALID_IMAGE_FORMAT 0xC000007B +#define STATUS_NO_TOKEN 0xC000007C +#define STATUS_BAD_INHERITANCE_ACL 0xC000007D +#define STATUS_RANGE_NOT_LOCKED 0xC000007E +#define STATUS_DISK_FULL 0xC000007F +#define STATUS_SERVER_DISABLED 0xC0000080 +#define STATUS_SERVER_NOT_DISABLED 0xC0000081 +#define STATUS_TOO_MANY_GUIDS_REQUESTED 0xC0000082 +#define STATUS_GUIDS_EXHAUSTED 0xC0000083 +#define STATUS_INVALID_ID_AUTHORITY 0xC0000084 +#define STATUS_AGENTS_EXHAUSTED 0xC0000085 +#define STATUS_INVALID_VOLUME_LABEL 0xC0000086 +#define STATUS_SECTION_NOT_EXTENDED 0xC0000087 +#define STATUS_NOT_MAPPED_DATA 0xC0000088 +#define STATUS_RESOURCE_DATA_NOT_FOUND 0xC0000089 +#define STATUS_RESOURCE_TYPE_NOT_FOUND 0xC000008A +#define STATUS_RESOURCE_NAME_NOT_FOUND 0xC000008B +#define STATUS_ARRAY_BOUNDS_EXCEEDED 0xC000008C +#define STATUS_FLOAT_DENORMAL_OPERAND 0xC000008D +#define STATUS_FLOAT_DIVIDE_BY_ZERO 0xC000008E +#define STATUS_FLOAT_INEXACT_RESULT 0xC000008F +#define STATUS_FLOAT_INVALID_OPERATION 0xC0000090 +#define STATUS_FLOAT_OVERFLOW 0xC0000091 +#define STATUS_FLOAT_STACK_CHECK 0xC0000092 +#define STATUS_FLOAT_UNDERFLOW 0xC0000093 +#define STATUS_INTEGER_DIVIDE_BY_ZERO 0xC0000094 +#define STATUS_INTEGER_OVERFLOW 0xC0000095 +#define STATUS_PRIVILEGED_INSTRUCTION 0xC0000096 +#define STATUS_TOO_MANY_PAGING_FILES 0xC0000097 +#define STATUS_FILE_INVALID 0xC0000098 +#define STATUS_ALLOTTED_SPACE_EXCEEDED 0xC0000099 +#define STATUS_INSUFFICIENT_RESOURCES 0xC000009A +#define STATUS_DFS_EXIT_PATH_FOUND 0xC000009B +#define STATUS_DEVICE_DATA_ERROR 0xC000009C +#define STATUS_DEVICE_NOT_CONNECTED 0xC000009D +#define STATUS_DEVICE_POWER_FAILURE 0xC000009E +#define STATUS_FREE_VM_NOT_AT_BASE 0xC000009F +#define STATUS_MEMORY_NOT_ALLOCATED 0xC00000A0 +#define STATUS_WORKING_SET_QUOTA 0xC00000A1 +#define STATUS_MEDIA_WRITE_PROTECTED 0xC00000A2 +#define STATUS_DEVICE_NOT_READY 0xC00000A3 +#define STATUS_INVALID_GROUP_ATTRIBUTES 0xC00000A4 +#define STATUS_BAD_IMPERSONATION_LEVEL 0xC00000A5 +#define STATUS_CANT_OPEN_ANONYMOUS 0xC00000A6 +#define STATUS_BAD_VALIDATION_CLASS 0xC00000A7 +#define STATUS_BAD_TOKEN_TYPE 0xC00000A8 +#define STATUS_BAD_MASTER_BOOT_RECORD 0xC00000A9 +#define STATUS_INSTRUCTION_MISALIGNMENT 0xC00000AA +#define STATUS_INSTANCE_NOT_AVAILABLE 0xC00000AB +#define STATUS_PIPE_NOT_AVAILABLE 0xC00000AC +#define STATUS_INVALID_PIPE_STATE 0xC00000AD +#define STATUS_PIPE_BUSY 0xC00000AE +#define STATUS_ILLEGAL_FUNCTION 0xC00000AF +#define STATUS_PIPE_DISCONNECTED 0xC00000B0 +#define STATUS_PIPE_CLOSING 0xC00000B1 +#define STATUS_PIPE_CONNECTED 0xC00000B2 +#define STATUS_PIPE_LISTENING 0xC00000B3 +#define STATUS_INVALID_READ_MODE 0xC00000B4 +#define STATUS_IO_TIMEOUT 0xC00000B5 +#define STATUS_FILE_FORCED_CLOSED 0xC00000B6 +#define STATUS_PROFILING_NOT_STARTED 0xC00000B7 +#define STATUS_PROFILING_NOT_STOPPED 0xC00000B8 +#define STATUS_COULD_NOT_INTERPRET 0xC00000B9 +#define STATUS_FILE_IS_A_DIRECTORY 0xC00000BA +#define STATUS_NOT_SUPPORTED 0xC00000BB +#define STATUS_REMOTE_NOT_LISTENING 0xC00000BC +#define STATUS_DUPLICATE_NAME 0xC00000BD +#define STATUS_BAD_NETWORK_PATH 0xC00000BE +#define STATUS_NETWORK_BUSY 0xC00000BF +#define STATUS_DEVICE_DOES_NOT_EXIST 0xC00000C0 +#define STATUS_TOO_MANY_COMMANDS 0xC00000C1 +#define STATUS_ADAPTER_HARDWARE_ERROR 0xC00000C2 +#define STATUS_INVALID_NETWORK_RESPONSE 0xC00000C3 +#define STATUS_UNEXPECTED_NETWORK_ERROR 0xC00000C4 +#define STATUS_BAD_REMOTE_ADAPTER 0xC00000C5 +#define STATUS_PRINT_QUEUE_FULL 0xC00000C6 +#define STATUS_NO_SPOOL_SPACE 0xC00000C7 +#define STATUS_PRINT_CANCELLED 0xC00000C8 +#define STATUS_NETWORK_NAME_DELETED 0xC00000C9 +#define STATUS_NETWORK_ACCESS_DENIED 0xC00000CA +#define STATUS_BAD_DEVICE_TYPE 0xC00000CB +#define STATUS_BAD_NETWORK_NAME 0xC00000CC +#define STATUS_TOO_MANY_NAMES 0xC00000CD +#define STATUS_TOO_MANY_SESSIONS 0xC00000CE +#define STATUS_SHARING_PAUSED 0xC00000CF +#define STATUS_REQUEST_NOT_ACCEPTED 0xC00000D0 +#define STATUS_REDIRECTOR_PAUSED 0xC00000D1 +#define STATUS_NET_WRITE_FAULT 0xC00000D2 +#define STATUS_PROFILING_AT_LIMIT 0xC00000D3 +#define STATUS_NOT_SAME_DEVICE 0xC00000D4 +#define STATUS_FILE_RENAMED 0xC00000D5 +#define STATUS_VIRTUAL_CIRCUIT_CLOSED 0xC00000D6 +#define STATUS_NO_SECURITY_ON_OBJECT 0xC00000D7 +#define STATUS_CANT_WAIT 0xC00000D8 +#define STATUS_PIPE_EMPTY 0xC00000D9 +#define STATUS_CANT_ACCESS_DOMAIN_INFO 0xC00000DA +#define STATUS_CANT_TERMINATE_SELF 0xC00000DB +#define STATUS_INVALID_SERVER_STATE 0xC00000DC +#define STATUS_INVALID_DOMAIN_STATE 0xC00000DD +#define STATUS_INVALID_DOMAIN_ROLE 0xC00000DE +#define STATUS_NO_SUCH_DOMAIN 0xC00000DF +#define STATUS_DOMAIN_EXISTS 0xC00000E0 +#define STATUS_DOMAIN_LIMIT_EXCEEDED 0xC00000E1 +#define STATUS_OPLOCK_NOT_GRANTED 0xC00000E2 +#define STATUS_INVALID_OPLOCK_PROTOCOL 0xC00000E3 +#define STATUS_INTERNAL_DB_CORRUPTION 0xC00000E4 +#define STATUS_INTERNAL_ERROR 0xC00000E5 +#define STATUS_GENERIC_NOT_MAPPED 0xC00000E6 +#define STATUS_BAD_DESCRIPTOR_FORMAT 0xC00000E7 +#define STATUS_INVALID_USER_BUFFER 0xC00000E8 +#define STATUS_UNEXPECTED_IO_ERROR 0xC00000E9 +#define STATUS_UNEXPECTED_MM_CREATE_ERR 0xC00000EA +#define STATUS_UNEXPECTED_MM_MAP_ERROR 0xC00000EB +#define STATUS_UNEXPECTED_MM_EXTEND_ERR 0xC00000EC +#define STATUS_NOT_LOGON_PROCESS 0xC00000ED +#define STATUS_LOGON_SESSION_EXISTS 0xC00000EE +#define STATUS_INVALID_PARAMETER_1 0xC00000EF +#define STATUS_INVALID_PARAMETER_2 0xC00000F0 +#define STATUS_INVALID_PARAMETER_3 0xC00000F1 +#define STATUS_INVALID_PARAMETER_4 0xC00000F2 +#define STATUS_INVALID_PARAMETER_5 0xC00000F3 +#define STATUS_INVALID_PARAMETER_6 0xC00000F4 +#define STATUS_INVALID_PARAMETER_7 0xC00000F5 +#define STATUS_INVALID_PARAMETER_8 0xC00000F6 +#define STATUS_INVALID_PARAMETER_9 0xC00000F7 +#define STATUS_INVALID_PARAMETER_10 0xC00000F8 +#define STATUS_INVALID_PARAMETER_11 0xC00000F9 +#define STATUS_INVALID_PARAMETER_12 0xC00000FA +#define STATUS_REDIRECTOR_NOT_STARTED 0xC00000FB +#define STATUS_REDIRECTOR_STARTED 0xC00000FC +#define STATUS_STACK_OVERFLOW 0xC00000FD +#define STATUS_NO_SUCH_PACKAGE 0xC00000FE +#define STATUS_BAD_FUNCTION_TABLE 0xC00000FF +#define STATUS_VARIABLE_NOT_FOUND 0xC0000100 +#define STATUS_DIRECTORY_NOT_EMPTY 0xC0000101 +#define STATUS_FILE_CORRUPT_ERROR 0xC0000102 +#define STATUS_NOT_A_DIRECTORY 0xC0000103 +#define STATUS_BAD_LOGON_SESSION_STATE 0xC0000104 +#define STATUS_LOGON_SESSION_COLLISION 0xC0000105 +#define STATUS_NAME_TOO_LONG 0xC0000106 +#define STATUS_FILES_OPEN 0xC0000107 +#define STATUS_CONNECTION_IN_USE 0xC0000108 +#define STATUS_MESSAGE_NOT_FOUND 0xC0000109 +#define STATUS_PROCESS_IS_TERMINATING 0xC000010A +#define STATUS_INVALID_LOGON_TYPE 0xC000010B +#define STATUS_NO_GUID_TRANSLATION 0xC000010C +#define STATUS_CANNOT_IMPERSONATE 0xC000010D +#define STATUS_IMAGE_ALREADY_LOADED 0xC000010E +#define STATUS_ABIOS_NOT_PRESENT 0xC000010F +#define STATUS_ABIOS_LID_NOT_EXIST 0xC0000110 +#define STATUS_ABIOS_LID_ALREADY_OWNED 0xC0000111 +#define STATUS_ABIOS_NOT_LID_OWNER 0xC0000112 +#define STATUS_ABIOS_INVALID_COMMAND 0xC0000113 +#define STATUS_ABIOS_INVALID_LID 0xC0000114 +#define STATUS_ABIOS_SELECTOR_NOT_AVAILABLE 0xC0000115 +#define STATUS_ABIOS_INVALID_SELECTOR 0xC0000116 +#define STATUS_NO_LDT 0xC0000117 +#define STATUS_INVALID_LDT_SIZE 0xC0000118 +#define STATUS_INVALID_LDT_OFFSET 0xC0000119 +#define STATUS_INVALID_LDT_DESCRIPTOR 0xC000011A +#define STATUS_INVALID_IMAGE_NE_FORMAT 0xC000011B +#define STATUS_RXACT_INVALID_STATE 0xC000011C +#define STATUS_RXACT_COMMIT_FAILURE 0xC000011D +#define STATUS_MAPPED_FILE_SIZE_ZERO 0xC000011E +#define STATUS_TOO_MANY_OPENED_FILES 0xC000011F +#define STATUS_CANCELLED 0xC0000120 +#define STATUS_CANNOT_DELETE 0xC0000121 +#define STATUS_INVALID_COMPUTER_NAME 0xC0000122 +#define STATUS_FILE_DELETED 0xC0000123 +#define STATUS_SPECIAL_ACCOUNT 0xC0000124 +#define STATUS_SPECIAL_GROUP 0xC0000125 +#define STATUS_SPECIAL_USER 0xC0000126 +#define STATUS_MEMBERS_PRIMARY_GROUP 0xC0000127 +#define STATUS_FILE_CLOSED 0xC0000128 +#define STATUS_TOO_MANY_THREADS 0xC0000129 +#define STATUS_THREAD_NOT_IN_PROCESS 0xC000012A +#define STATUS_TOKEN_ALREADY_IN_USE 0xC000012B +#define STATUS_PAGEFILE_QUOTA_EXCEEDED 0xC000012C +#define STATUS_COMMITMENT_LIMIT 0xC000012D +#define STATUS_INVALID_IMAGE_LE_FORMAT 0xC000012E +#define STATUS_INVALID_IMAGE_NOT_MZ 0xC000012F +#define STATUS_INVALID_IMAGE_PROTECT 0xC0000130 +#define STATUS_INVALID_IMAGE_WIN_16 0xC0000131 +#define STATUS_LOGON_SERVER_CONFLICT 0xC0000132 +#define STATUS_TIME_DIFFERENCE_AT_DC 0xC0000133 +#define STATUS_SYNCHRONIZATION_REQUIRED 0xC0000134 +#define STATUS_DLL_NOT_FOUND 0xC0000135 +#define STATUS_OPEN_FAILED 0xC0000136 +#define STATUS_IO_PRIVILEGE_FAILED 0xC0000137 +#define STATUS_ORDINAL_NOT_FOUND 0xC0000138 +#define STATUS_ENTRYPOINT_NOT_FOUND 0xC0000139 +#define STATUS_CONTROL_C_EXIT 0xC000013A +#define STATUS_LOCAL_DISCONNECT 0xC000013B +#define STATUS_REMOTE_DISCONNECT 0xC000013C +#define STATUS_REMOTE_RESOURCES 0xC000013D +#define STATUS_LINK_FAILED 0xC000013E +#define STATUS_LINK_TIMEOUT 0xC000013F +#define STATUS_INVALID_CONNECTION 0xC0000140 +#define STATUS_INVALID_ADDRESS 0xC0000141 +#define STATUS_DLL_INIT_FAILED 0xC0000142 +#define STATUS_MISSING_SYSTEMFILE 0xC0000143 +#define STATUS_UNHANDLED_EXCEPTION 0xC0000144 +#define STATUS_APP_INIT_FAILURE 0xC0000145 +#define STATUS_PAGEFILE_CREATE_FAILED 0xC0000146 +#define STATUS_NO_PAGEFILE 0xC0000147 +#define STATUS_INVALID_LEVEL 0xC0000148 +#define STATUS_WRONG_PASSWORD_CORE 0xC0000149 +#define STATUS_ILLEGAL_FLOAT_CONTEXT 0xC000014A +#define STATUS_PIPE_BROKEN 0xC000014B +#define STATUS_REGISTRY_CORRUPT 0xC000014C +#define STATUS_REGISTRY_IO_FAILED 0xC000014D +#define STATUS_NO_EVENT_PAIR 0xC000014E +#define STATUS_UNRECOGNIZED_VOLUME 0xC000014F +#define STATUS_SERIAL_NO_DEVICE_INITED 0xC0000150 +#define STATUS_NO_SUCH_ALIAS 0xC0000151 +#define STATUS_MEMBER_NOT_IN_ALIAS 0xC0000152 +#define STATUS_MEMBER_IN_ALIAS 0xC0000153 +#define STATUS_ALIAS_EXISTS 0xC0000154 +#define STATUS_LOGON_NOT_GRANTED 0xC0000155 +#define STATUS_TOO_MANY_SECRETS 0xC0000156 +#define STATUS_SECRET_TOO_LONG 0xC0000157 +#define STATUS_INTERNAL_DB_ERROR 0xC0000158 +#define STATUS_FULLSCREEN_MODE 0xC0000159 +#define STATUS_TOO_MANY_CONTEXT_IDS 0xC000015A +#define STATUS_LOGON_TYPE_NOT_GRANTED 0xC000015B +#define STATUS_NOT_REGISTRY_FILE 0xC000015C +#define STATUS_NT_CROSS_ENCRYPTION_REQUIRED 0xC000015D +#define STATUS_DOMAIN_CTRLR_CONFIG_ERROR 0xC000015E +#define STATUS_FT_MISSING_MEMBER 0xC000015F +#define STATUS_ILL_FORMED_SERVICE_ENTRY 0xC0000160 +#define STATUS_ILLEGAL_CHARACTER 0xC0000161 +#define STATUS_UNMAPPABLE_CHARACTER 0xC0000162 +#define STATUS_UNDEFINED_CHARACTER 0xC0000163 +#define STATUS_FLOPPY_VOLUME 0xC0000164 +#define STATUS_FLOPPY_ID_MARK_NOT_FOUND 0xC0000165 +#define STATUS_FLOPPY_WRONG_CYLINDER 0xC0000166 +#define STATUS_FLOPPY_UNKNOWN_ERROR 0xC0000167 +#define STATUS_FLOPPY_BAD_REGISTERS 0xC0000168 +#define STATUS_DISK_RECALIBRATE_FAILED 0xC0000169 +#define STATUS_DISK_OPERATION_FAILED 0xC000016A +#define STATUS_DISK_RESET_FAILED 0xC000016B +#define STATUS_SHARED_IRQ_BUSY 0xC000016C +#define STATUS_FT_ORPHANING 0xC000016D +#define STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT 0xC000016E + +#define STATUS_PARTITION_FAILURE 0xC0000172 +#define STATUS_INVALID_BLOCK_LENGTH 0xC0000173 +#define STATUS_DEVICE_NOT_PARTITIONED 0xC0000174 +#define STATUS_UNABLE_TO_LOCK_MEDIA 0xC0000175 +#define STATUS_UNABLE_TO_UNLOAD_MEDIA 0xC0000176 +#define STATUS_EOM_OVERFLOW 0xC0000177 +#define STATUS_NO_MEDIA 0xC0000178 +#define STATUS_NO_SUCH_MEMBER 0xC000017A +#define STATUS_INVALID_MEMBER 0xC000017B +#define STATUS_KEY_DELETED 0xC000017C +#define STATUS_NO_LOG_SPACE 0xC000017D +#define STATUS_TOO_MANY_SIDS 0xC000017E +#define STATUS_LM_CROSS_ENCRYPTION_REQUIRED 0xC000017F +#define STATUS_KEY_HAS_CHILDREN 0xC0000180 +#define STATUS_CHILD_MUST_BE_VOLATILE 0xC0000181 +#define STATUS_DEVICE_CONFIGURATION_ERROR 0xC0000182 +#define STATUS_DRIVER_INTERNAL_ERROR 0xC0000183 +#define STATUS_INVALID_DEVICE_STATE 0xC0000184 +#define STATUS_IO_DEVICE_ERROR 0xC0000185 +#define STATUS_DEVICE_PROTOCOL_ERROR 0xC0000186 +#define STATUS_BACKUP_CONTROLLER 0xC0000187 +#define STATUS_LOG_FILE_FULL 0xC0000188 +#define STATUS_TOO_LATE 0xC0000189 +#define STATUS_NO_TRUST_LSA_SECRET 0xC000018A +#define STATUS_NO_TRUST_SAM_ACCOUNT 0xC000018B +#define STATUS_TRUSTED_DOMAIN_FAILURE 0xC000018C +#define STATUS_TRUSTED_RELATIONSHIP_FAILURE 0xC000018D +#define STATUS_EVENTLOG_FILE_CORRUPT 0xC000018E +#define STATUS_EVENTLOG_CANT_START 0xC000018F +#define STATUS_TRUST_FAILURE 0xC0000190 +#define STATUS_MUTANT_LIMIT_EXCEEDED 0xC0000191 +#define STATUS_NETLOGON_NOT_STARTED 0xC0000192 +#define STATUS_ACCOUNT_EXPIRED 0xC0000193 +#define STATUS_POSSIBLE_DEADLOCK 0xC0000194 +#define STATUS_NETWORK_CREDENTIAL_CONFLICT 0xC0000195 +#define STATUS_REMOTE_SESSION_LIMIT 0xC0000196 +#define STATUS_EVENTLOG_FILE_CHANGED 0xC0000197 +#define STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT 0xC0000198 +#define STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT 0xC0000199 +#define STATUS_NOLOGON_SERVER_TRUST_ACCOUNT 0xC000019A +#define STATUS_DOMAIN_TRUST_INCONSISTENT 0xC000019B +#define STATUS_FS_DRIVER_REQUIRED 0xC000019C +#define STATUS_NO_USER_SESSION_KEY 0xC0000202 +#define STATUS_USER_SESSION_DELETED 0xC0000203 +#define STATUS_RESOURCE_LANG_NOT_FOUND 0xC0000204 +#define STATUS_INSUFF_SERVER_RESOURCES 0xC0000205 +#define STATUS_INVALID_BUFFER_SIZE 0xC0000206 +#define STATUS_INVALID_ADDRESS_COMPONENT 0xC0000207 +#define STATUS_INVALID_ADDRESS_WILDCARD 0xC0000208 +#define STATUS_TOO_MANY_ADDRESSES 0xC0000209 +#define STATUS_ADDRESS_ALREADY_EXISTS 0xC000020A +#define STATUS_ADDRESS_CLOSED 0xC000020B +#define STATUS_CONNECTION_DISCONNECTED 0xC000020C +#define STATUS_CONNECTION_RESET 0xC000020D +#define STATUS_TOO_MANY_NODES 0xC000020E +#define STATUS_TRANSACTION_ABORTED 0xC000020F +#define STATUS_TRANSACTION_TIMED_OUT 0xC0000210 +#define STATUS_TRANSACTION_NO_RELEASE 0xC0000211 +#define STATUS_TRANSACTION_NO_MATCH 0xC0000212 +#define STATUS_TRANSACTION_RESPONDED 0xC0000213 +#define STATUS_TRANSACTION_INVALID_ID 0xC0000214 +#define STATUS_TRANSACTION_INVALID_TYPE 0xC0000215 +#define STATUS_NOT_SERVER_SESSION 0xC0000216 +#define STATUS_NOT_CLIENT_SESSION 0xC0000217 +#define STATUS_CANNOT_LOAD_REGISTRY_FILE 0xC0000218 +#define STATUS_DEBUG_ATTACH_FAILED 0xC0000219 +#define STATUS_SYSTEM_PROCESS_TERMINATED 0xC000021A +#define STATUS_DATA_NOT_ACCEPTED 0xC000021B +#define STATUS_NO_BROWSER_SERVERS_FOUND 0xC000021C +#define STATUS_VDM_HARD_ERROR 0xC000021D +#define STATUS_DRIVER_CANCEL_TIMEOUT 0xC000021E +#define STATUS_REPLY_MESSAGE_MISMATCH 0xC000021F +#define STATUS_MAPPED_ALIGNMENT 0xC0000220 +#define STATUS_IMAGE_CHECKSUM_MISMATCH 0xC0000221 +#define STATUS_LOST_WRITEBEHIND_DATA 0xC0000222 +#define STATUS_CLIENT_SERVER_PARAMETERS_INVALID 0xC0000223 +#define STATUS_PASSWORD_MUST_CHANGE 0xC0000224 +#define STATUS_NOT_FOUND 0xC0000225 +#define STATUS_NOT_TINY_STREAM 0xC0000226 +#define STATUS_RECOVERY_FAILURE 0xC0000227 +#define STATUS_STACK_OVERFLOW_READ 0xC0000228 +#define STATUS_FAIL_CHECK 0xC0000229 +#define STATUS_DUPLICATE_OBJECTID 0xC000022A +#define STATUS_OBJECTID_EXISTS 0xC000022B +#define STATUS_CONVERT_TO_LARGE 0xC000022C +#define STATUS_RETRY 0xC000022D +#define STATUS_FOUND_OUT_OF_SCOPE 0xC000022E +#define STATUS_ALLOCATE_BUCKET 0xC000022F +#define STATUS_PROPSET_NOT_FOUND 0xC0000230 +#define STATUS_MARSHALL_OVERFLOW 0xC0000231 +#define STATUS_INVALID_VARIANT 0xC0000232 +#define STATUS_DOMAIN_CONTROLLER_NOT_FOUND 0xC0000233 +#define STATUS_ACCOUNT_LOCKED_OUT 0xC0000234 +#define STATUS_HANDLE_NOT_CLOSABLE 0xC0000235 +#define STATUS_CONNECTION_REFUSED 0xC0000236 +#define STATUS_GRACEFUL_DISCONNECT 0xC0000237 +#define STATUS_ADDRESS_ALREADY_ASSOCIATED 0xC0000238 +#define STATUS_ADDRESS_NOT_ASSOCIATED 0xC0000239 +#define STATUS_CONNECTION_INVALID 0xC000023A +#define STATUS_CONNECTION_ACTIVE 0xC000023B +#define STATUS_NETWORK_UNREACHABLE 0xC000023C +#define STATUS_HOST_UNREACHABLE 0xC000023D +#define STATUS_PROTOCOL_UNREACHABLE 0xC000023E +#define STATUS_PORT_UNREACHABLE 0xC000023F +#define STATUS_REQUEST_ABORTED 0xC0000240 +#define STATUS_CONNECTION_ABORTED 0xC0000241 +#define STATUS_BAD_COMPRESSION_BUFFER 0xC0000242 +#define STATUS_USER_MAPPED_FILE 0xC0000243 +#define STATUS_AUDIT_FAILED 0xC0000244 +#define STATUS_TIMER_RESOLUTION_NOT_SET 0xC0000245 +#define STATUS_CONNECTION_COUNT_LIMIT 0xC0000246 +#define STATUS_LOGIN_TIME_RESTRICTION 0xC0000247 +#define STATUS_LOGIN_WKSTA_RESTRICTION 0xC0000248 +#define STATUS_IMAGE_MP_UP_MISMATCH 0xC0000249 +#define STATUS_INSUFFICIENT_LOGON_INFO 0xC0000250 +#define STATUS_BAD_DLL_ENTRYPOINT 0xC0000251 +#define STATUS_BAD_SERVICE_ENTRYPOINT 0xC0000252 +#define STATUS_LPC_REPLY_LOST 0xC0000253 +#define STATUS_IP_ADDRESS_CONFLICT1 0xC0000254 +#define STATUS_IP_ADDRESS_CONFLICT2 0xC0000255 +#define STATUS_REGISTRY_QUOTA_LIMIT 0xC0000256 +#define STATUS_PATH_NOT_COVERED 0xC0000257 +#define STATUS_NO_CALLBACK_ACTIVE 0xC0000258 +#define STATUS_LICENSE_QUOTA_EXCEEDED 0xC0000259 +#define STATUS_PWD_TOO_SHORT 0xC000025A +#define STATUS_PWD_TOO_RECENT 0xC000025B +#define STATUS_PWD_HISTORY_CONFLICT 0xC000025C +#define STATUS_PLUGPLAY_NO_DEVICE 0xC000025E +#define STATUS_UNSUPPORTED_COMPRESSION 0xC000025F +#define STATUS_INVALID_HW_PROFILE 0xC0000260 +#define STATUS_INVALID_PLUGPLAY_DEVICE_PATH 0xC0000261 +#define STATUS_DRIVER_ORDINAL_NOT_FOUND 0xC0000262 +#define STATUS_DRIVER_ENTRYPOINT_NOT_FOUND 0xC0000263 +#define STATUS_RESOURCE_NOT_OWNED 0xC0000264 +#define STATUS_TOO_MANY_LINKS 0xC0000265 +#define STATUS_QUOTA_LIST_INCONSISTENT 0xC0000266 +#define STATUS_FILE_IS_OFFLINE 0xC0000267 +#define STATUS_EVALUATION_EXPIRATION 0xC0000268 +#define STATUS_ILLEGAL_DLL_RELOCATION 0xC0000269 +#define STATUS_LICENSE_VIOLATION 0xC000026A +#define STATUS_DLL_INIT_FAILED_LOGOFF 0xC000026B +#define STATUS_DRIVER_UNABLE_TO_LOAD 0xC000026C +#define STATUS_DFS_UNAVAILABLE 0xC000026D +#define STATUS_VOLUME_DISMOUNTED 0xC000026E +#define STATUS_WX86_INTERNAL_ERROR 0xC000026F +#define STATUS_WX86_FLOAT_STACK_CHECK 0xC0000270 +#define STATUS_VALIDATE_CONTINUE 0xC0000271 +#define STATUS_NO_MATCH 0xC0000272 +#define STATUS_NO_MORE_MATCHES 0xC0000273 +#define STATUS_NOT_A_REPARSE_POINT 0xC0000275 +#define STATUS_IO_REPARSE_TAG_INVALID 0xC0000276 +#define STATUS_IO_REPARSE_TAG_MISMATCH 0xC0000277 +#define STATUS_IO_REPARSE_DATA_INVALID 0xC0000278 +#define STATUS_IO_REPARSE_TAG_NOT_HANDLED 0xC0000279 +#define STATUS_REPARSE_POINT_NOT_RESOLVED 0xC0000280 +#define STATUS_DIRECTORY_IS_A_REPARSE_POINT 0xC0000281 +#define STATUS_RANGE_LIST_CONFLICT 0xC0000282 +#define STATUS_SOURCE_ELEMENT_EMPTY 0xC0000283 +#define STATUS_DESTINATION_ELEMENT_FULL 0xC0000284 +#define STATUS_ILLEGAL_ELEMENT_ADDRESS 0xC0000285 +#define STATUS_MAGAZINE_NOT_PRESENT 0xC0000286 +#define STATUS_REINITIALIZATION_NEEDED 0xC0000287 +#define STATUS_ENCRYPTION_FAILED 0xC000028A +#define STATUS_DECRYPTION_FAILED 0xC000028B +#define STATUS_RANGE_NOT_FOUND 0xC000028C +#define STATUS_NO_RECOVERY_POLICY 0xC000028D +#define STATUS_NO_EFS 0xC000028E +#define STATUS_WRONG_EFS 0xC000028F +#define STATUS_NO_USER_KEYS 0xC0000290 +#define STATUS_FILE_NOT_ENCRYPTED 0xC0000291 +#define STATUS_NOT_EXPORT_FORMAT 0xC0000292 +#define STATUS_FILE_ENCRYPTED 0xC0000293 +#define STATUS_WMI_GUID_NOT_FOUND 0xC0000295 +#define STATUS_WMI_INSTANCE_NOT_FOUND 0xC0000296 +#define STATUS_WMI_ITEMID_NOT_FOUND 0xC0000297 +#define STATUS_WMI_TRY_AGAIN 0xC0000298 +#define STATUS_SHARED_POLICY 0xC0000299 +#define STATUS_POLICY_OBJECT_NOT_FOUND 0xC000029A +#define STATUS_POLICY_ONLY_IN_DS 0xC000029B +#define STATUS_VOLUME_NOT_UPGRADED 0xC000029C +#define STATUS_REMOTE_STORAGE_NOT_ACTIVE 0xC000029D +#define STATUS_REMOTE_STORAGE_MEDIA_ERROR 0xC000029E +#define STATUS_NO_TRACKING_SERVICE 0xC000029F +#define STATUS_SERVER_SID_MISMATCH 0xC00002A0 +#define STATUS_DS_NO_ATTRIBUTE_OR_VALUE 0xC00002A1 +#define STATUS_DS_INVALID_ATTRIBUTE_SYNTAX 0xC00002A2 +#define STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED 0xC00002A3 +#define STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS 0xC00002A4 +#define STATUS_DS_BUSY 0xC00002A5 +#define STATUS_DS_UNAVAILABLE 0xC00002A6 +#define STATUS_DS_NO_RIDS_ALLOCATED 0xC00002A7 +#define STATUS_DS_NO_MORE_RIDS 0xC00002A8 +#define STATUS_DS_INCORRECT_ROLE_OWNER 0xC00002A9 +#define STATUS_DS_RIDMGR_INIT_ERROR 0xC00002AA +#define STATUS_DS_OBJ_CLASS_VIOLATION 0xC00002AB +#define STATUS_DS_CANT_ON_NON_LEAF 0xC00002AC +#define STATUS_DS_CANT_ON_RDN 0xC00002AD +#define STATUS_DS_CANT_MOD_OBJ_CLASS 0xC00002AE +#define STATUS_DS_CROSS_DOM_MOVE_FAILED 0xC00002AF +#define STATUS_DS_GC_NOT_AVAILABLE 0xC00002B0 +#define STATUS_DIRECTORY_SERVICE_REQUIRED 0xC00002B1 +#define STATUS_REPARSE_ATTRIBUTE_CONFLICT 0xC00002B2 +#define STATUS_CANT_ENABLE_DENY_ONLY 0xC00002B3 +#define STATUS_FLOAT_MULTIPLE_FAULTS 0xC00002B4 +#define STATUS_FLOAT_MULTIPLE_TRAPS 0xC00002B5 +#define STATUS_DEVICE_REMOVED 0xC00002B6 +#define STATUS_JOURNAL_DELETE_IN_PROGRESS 0xC00002B7 +#define STATUS_JOURNAL_NOT_ACTIVE 0xC00002B8 +#define STATUS_NOINTERFACE 0xC00002B9 +#define STATUS_DS_ADMIN_LIMIT_EXCEEDED 0xC00002C1 +#define STATUS_DRIVER_FAILED_SLEEP 0xC00002C2 +#define STATUS_MUTUAL_AUTHENTICATION_FAILED 0xC00002C3 +#define STATUS_CORRUPT_SYSTEM_FILE 0xC00002C4 +#define STATUS_DATATYPE_MISALIGNMENT_ERROR 0xC00002C5 +#define STATUS_WMI_READ_ONLY 0xC00002C6 +#define STATUS_WMI_SET_FAILURE 0xC00002C7 +#define STATUS_COMMITMENT_MINIMUM 0xC00002C8 +#define STATUS_REG_NAT_CONSUMPTION 0xC00002C9 +#define STATUS_TRANSPORT_FULL 0xC00002CA +#define STATUS_DS_SAM_INIT_FAILURE 0xC00002CB +#define STATUS_ONLY_IF_CONNECTED 0xC00002CC +#define STATUS_DS_SENSITIVE_GROUP_VIOLATION 0xC00002CD +#define STATUS_PNP_RESTART_ENUMERATION 0xC00002CE +#define STATUS_JOURNAL_ENTRY_DELETED 0xC00002CF +#define STATUS_DS_CANT_MOD_PRIMARYGROUPID 0xC00002D0 +#define STATUS_SYSTEM_IMAGE_BAD_SIGNATURE 0xC00002D1 +#define STATUS_PNP_REBOOT_REQUIRED 0xC00002D2 +#define STATUS_POWER_STATE_INVALID 0xC00002D3 +#define STATUS_DS_INVALID_GROUP_TYPE 0xC00002D4 +#define STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN 0xC00002D5 +#define STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN 0xC00002D6 +#define STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER 0xC00002D7 +#define STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER 0xC00002D8 +#define STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER 0xC00002D9 +#define STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER 0xC00002DA +#define STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER 0xC00002DB +#define STATUS_DS_HAVE_PRIMARY_MEMBERS 0xC00002DC +#define STATUS_WMI_NOT_SUPPORTED 0xC00002DD +#define STATUS_INSUFFICIENT_POWER 0xC00002DE +#define STATUS_SAM_NEED_BOOTKEY_PASSWORD 0xC00002DF +#define STATUS_SAM_NEED_BOOTKEY_FLOPPY 0xC00002E0 +#define STATUS_DS_CANT_START 0xC00002E1 +#define STATUS_DS_INIT_FAILURE 0xC00002E2 +#define STATUS_SAM_INIT_FAILURE 0xC00002E3 +#define STATUS_DS_GC_REQUIRED 0xC00002E4 +#define STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY 0xC00002E5 +#define STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS 0xC00002E6 +#define STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED 0xC00002E7 +#define STATUS_MULTIPLE_FAULT_VIOLATION 0xC00002E8 +#define STATUS_CURRENT_DOMAIN_NOT_ALLOWED 0xC00002E9 +#define STATUS_CANNOT_MAKE 0xC00002EA +#define STATUS_SYSTEM_SHUTDOWN 0xC00002EB +#define STATUS_DS_INIT_FAILURE_CONSOLE 0xC00002EC +#define STATUS_DS_SAM_INIT_FAILURE_CONSOLE 0xC00002ED +#define STATUS_UNFINISHED_CONTEXT_DELETED 0xC00002EE +#define STATUS_NO_TGT_REPLY 0xC00002EF +#define STATUS_OBJECTID_NOT_FOUND 0xC00002F0 +#define STATUS_NO_IP_ADDRESSES 0xC00002F1 +#define STATUS_WRONG_CREDENTIAL_HANDLE 0xC00002F2 +#define STATUS_CRYPTO_SYSTEM_INVALID 0xC00002F3 +#define STATUS_MAX_REFERRALS_EXCEEDED 0xC00002F4 +#define STATUS_MUST_BE_KDC 0xC00002F5 +#define STATUS_STRONG_CRYPTO_NOT_SUPPORTED 0xC00002F6 +#define STATUS_TOO_MANY_PRINCIPALS 0xC00002F7 +#define STATUS_NO_PA_DATA 0xC00002F8 +#define STATUS_PKINIT_NAME_MISMATCH 0xC00002F9 +#define STATUS_SMARTCARD_LOGON_REQUIRED 0xC00002FA +#define STATUS_KDC_INVALID_REQUEST 0xC00002FB +#define STATUS_KDC_UNABLE_TO_REFER 0xC00002FC +#define STATUS_KDC_UNKNOWN_ETYPE 0xC00002FD +#define STATUS_SHUTDOWN_IN_PROGRESS 0xC00002FE +#define STATUS_SERVER_SHUTDOWN_IN_PROGRESS 0xC00002FF +#define STATUS_NOT_SUPPORTED_ON_SBS 0xC0000300 +#define STATUS_WMI_GUID_DISCONNECTED 0xC0000301 +#define STATUS_WMI_ALREADY_DISABLED 0xC0000302 +#define STATUS_WMI_ALREADY_ENABLED 0xC0000303 +#define STATUS_MFT_TOO_FRAGMENTED 0xC0000304 +#define STATUS_COPY_PROTECTION_FAILURE 0xC0000305 +#define STATUS_CSS_AUTHENTICATION_FAILURE 0xC0000306 +#define STATUS_CSS_KEY_NOT_PRESENT 0xC0000307 +#define STATUS_CSS_KEY_NOT_ESTABLISHED 0xC0000308 +#define STATUS_CSS_SCRAMBLED_SECTOR 0xC0000309 +#define STATUS_CSS_REGION_MISMATCH 0xC000030A +#define STATUS_CSS_RESETS_EXHAUSTED 0xC000030B +#define STATUS_PKINIT_FAILURE 0xC0000320 +#define STATUS_SMARTCARD_SUBSYSTEM_FAILURE 0xC0000321 +#define STATUS_NO_KERB_KEY 0xC0000322 +#define STATUS_HOST_DOWN 0xC0000350 +#define STATUS_UNSUPPORTED_PREAUTH 0xC0000351 +#define STATUS_EFS_ALG_BLOB_TOO_BIG 0xC0000352 +#define STATUS_PORT_NOT_SET 0xC0000353 +#define STATUS_DEBUGGER_INACTIVE 0xC0000354 +#define STATUS_DS_VERSION_CHECK_FAILURE 0xC0000355 +#define STATUS_AUDITING_DISABLED 0xC0000356 +#define STATUS_PRENT4_MACHINE_ACCOUNT 0xC0000357 +#define STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER 0xC0000358 +#define STATUS_INVALID_IMAGE_WIN_32 0xC0000359 +#define STATUS_INVALID_IMAGE_WIN_64 0xC000035A +#define STATUS_BAD_BINDINGS 0xC000035B +#define STATUS_NETWORK_SESSION_EXPIRED 0xC000035C +#define STATUS_APPHELP_BLOCK 0xC000035D +#define STATUS_ALL_SIDS_FILTERED 0xC000035E +#define STATUS_NOT_SAFE_MODE_DRIVER 0xC000035F +#define STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT 0xC0000361 +#define STATUS_ACCESS_DISABLED_BY_POLICY_PATH 0xC0000362 +#define STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER 0xC0000363 +#define STATUS_ACCESS_DISABLED_BY_POLICY_OTHER 0xC0000364 +#define STATUS_FAILED_DRIVER_ENTRY 0xC0000365 +#define STATUS_DEVICE_ENUMERATION_ERROR 0xC0000366 +#define STATUS_WAIT_FOR_OPLOCK 0x00000367 +#define STATUS_MOUNT_POINT_NOT_RESOLVED 0xC0000368 +#define STATUS_INVALID_DEVICE_OBJECT_PARAMETER 0xC0000369 +#define STATUS_MCA_OCCURED 0xC000036A +#define STATUS_DRIVER_BLOCKED_CRITICAL 0xC000036B +#define STATUS_DRIVER_BLOCKED 0xC000036C +#define STATUS_DRIVER_DATABASE_ERROR 0xC000036D +#define STATUS_SYSTEM_HIVE_TOO_LARGE 0xC000036E +#define STATUS_INVALID_IMPORT_OF_NON_DLL 0xC000036F +#define STATUS_SMARTCARD_WRONG_PIN 0xC0000380 +#define STATUS_SMARTCARD_CARD_BLOCKED 0xC0000381 +#define STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED 0xC0000382 +#define STATUS_SMARTCARD_NO_CARD 0xC0000383 +#define STATUS_SMARTCARD_NO_KEY_CONTAINER 0xC0000384 +#define STATUS_SMARTCARD_NO_CERTIFICATE 0xC0000385 +#define STATUS_SMARTCARD_NO_KEYSET 0xC0000386 +#define STATUS_SMARTCARD_IO_ERROR 0xC0000387 +#define STATUS_DOWNGRADE_DETECTED 0xC0000388 +#define STATUS_SMARTCARD_CERT_REVOKED 0xC0000389 +#define STATUS_ISSUING_CA_UNTRUSTED 0xC000038A +#define STATUS_REVOCATION_OFFLINE_C 0xC000038B +#define STATUS_PKINIT_CLIENT_FAILURE 0xC000038C +#define STATUS_SMARTCARD_CERT_EXPIRED 0xC000038D +#define STATUS_DRIVER_FAILED_PRIOR_UNLOAD 0xC000038E +#define STATUS_SMARTCARD_SILENT_CONTEXT 0xC000038F +#define STATUS_PER_USER_TRUST_QUOTA_EXCEEDED 0xC0000401 +#define STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED 0xC0000402 +#define STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED 0xC0000403 +#define STATUS_DS_NAME_NOT_UNIQUE 0xC0000404 +#define STATUS_DS_DUPLICATE_ID_FOUND 0xC0000405 +#define STATUS_DS_GROUP_CONVERSION_ERROR 0xC0000406 +#define STATUS_VOLSNAP_PREPARE_HIBERNATE 0xC0000407 +#define STATUS_USER2USER_REQUIRED 0xC0000408 +#define STATUS_STACK_BUFFER_OVERRUN 0xC0000409 +#define STATUS_NO_S4U_PROT_SUPPORT 0xC000040A +#define STATUS_CROSSREALM_DELEGATION_FAILURE 0xC000040B +#define STATUS_REVOCATION_OFFLINE_KDC 0xC000040C +#define STATUS_ISSUING_CA_UNTRUSTED_KDC 0xC000040D +#define STATUS_KDC_CERT_EXPIRED 0xC000040E +#define STATUS_KDC_CERT_REVOKED 0xC000040F +#define STATUS_PARAMETER_QUOTA_EXCEEDED 0xC0000410 +#define STATUS_HIBERNATION_FAILURE 0xC0000411 +#define STATUS_DELAY_LOAD_FAILED 0xC0000412 +#define STATUS_AUTHENTICATION_FIREWALL_FAILED 0xC0000413 +#define STATUS_VDM_DISALLOWED 0xC0000414 +#define STATUS_HUNG_DISPLAY_DRIVER_THREAD 0xC0000415 +#define STATUS_WOW_ASSERTION 0xC0009898 + +#define RPC_NT_INVALID_STRING_BINDING 0xC0020001 +#define RPC_NT_WRONG_KIND_OF_BINDING 0xC0020002 +#define RPC_NT_INVALID_BINDING 0xC0020003 +#define RPC_NT_PROTSEQ_NOT_SUPPORTED 0xC0020004 +#define RPC_NT_INVALID_RPC_PROTSEQ 0xC0020005 +#define RPC_NT_INVALID_STRING_UUID 0xC0020006 +#define RPC_NT_INVALID_ENDPOINT_FORMAT 0xC0020007 +#define RPC_NT_INVALID_NET_ADDR 0xC0020008 +#define RPC_NT_NO_ENDPOINT_FOUND 0xC0020009 +#define RPC_NT_INVALID_TIMEOUT 0xC002000A +#define RPC_NT_OBJECT_NOT_FOUND 0xC002000B +#define RPC_NT_ALREADY_REGISTERED 0xC002000C +#define RPC_NT_TYPE_ALREADY_REGISTERED 0xC002000D +#define RPC_NT_ALREADY_LISTENING 0xC002000E +#define RPC_NT_NO_PROTSEQS_REGISTERED 0xC002000F +#define RPC_NT_NOT_LISTENING 0xC0020010 +#define RPC_NT_UNKNOWN_MGR_TYPE 0xC0020011 +#define RPC_NT_UNKNOWN_IF 0xC0020012 +#define RPC_NT_NO_BINDINGS 0xC0020013 +#define RPC_NT_NO_PROTSEQS 0xC0020014 +#define RPC_NT_CANT_CREATE_ENDPOINT 0xC0020015 +#define RPC_NT_OUT_OF_RESOURCES 0xC0020016 +#define RPC_NT_SERVER_UNAVAILABLE 0xC0020017 +#define RPC_NT_SERVER_TOO_BUSY 0xC0020018 +#define RPC_NT_INVALID_NETWORK_OPTIONS 0xC0020019 +#define RPC_NT_NO_CALL_ACTIVE 0xC002001A +#define RPC_NT_CALL_FAILED 0xC002001B +#define RPC_NT_CALL_FAILED_DNE 0xC002001C +#define RPC_NT_PROTOCOL_ERROR 0xC002001D +#define RPC_NT_UNSUPPORTED_TRANS_SYN 0xC002001F +#define RPC_NT_UNSUPPORTED_TYPE 0xC0020021 +#define RPC_NT_INVALID_TAG 0xC0020022 +#define RPC_NT_INVALID_BOUND 0xC0020023 +#define RPC_NT_NO_ENTRY_NAME 0xC0020024 +#define RPC_NT_INVALID_NAME_SYNTAX 0xC0020025 +#define RPC_NT_UNSUPPORTED_NAME_SYNTAX 0xC0020026 +#define RPC_NT_UUID_NO_ADDRESS 0xC0020028 +#define RPC_NT_DUPLICATE_ENDPOINT 0xC0020029 +#define RPC_NT_UNKNOWN_AUTHN_TYPE 0xC002002A +#define RPC_NT_MAX_CALLS_TOO_SMALL 0xC002002B +#define RPC_NT_STRING_TOO_LONG 0xC002002C +#define RPC_NT_PROTSEQ_NOT_FOUND 0xC002002D +#define RPC_NT_PROCNUM_OUT_OF_RANGE 0xC002002E +#define RPC_NT_BINDING_HAS_NO_AUTH 0xC002002F +#define RPC_NT_UNKNOWN_AUTHN_SERVICE 0xC0020030 +#define RPC_NT_UNKNOWN_AUTHN_LEVEL 0xC0020031 +#define RPC_NT_INVALID_AUTH_IDENTITY 0xC0020032 +#define RPC_NT_UNKNOWN_AUTHZ_SERVICE 0xC0020033 +#define EPT_NT_INVALID_ENTRY 0xC0020034 +#define EPT_NT_CANT_PERFORM_OP 0xC0020035 +#define EPT_NT_NOT_REGISTERED 0xC0020036 +#define RPC_NT_NOTHING_TO_EXPORT 0xC0020037 +#define RPC_NT_INCOMPLETE_NAME 0xC0020038 +#define RPC_NT_INVALID_VERS_OPTION 0xC0020039 +#define RPC_NT_NO_MORE_MEMBERS 0xC002003A +#define RPC_NT_NOT_ALL_OBJS_UNEXPORTED 0xC002003B +#define RPC_NT_INTERFACE_NOT_FOUND 0xC002003C +#define RPC_NT_ENTRY_ALREADY_EXISTS 0xC002003D +#define RPC_NT_ENTRY_NOT_FOUND 0xC002003E +#define RPC_NT_NAME_SERVICE_UNAVAILABLE 0xC002003F +#define RPC_NT_INVALID_NAF_ID 0xC0020040 +#define RPC_NT_CANNOT_SUPPORT 0xC0020041 +#define RPC_NT_NO_CONTEXT_AVAILABLE 0xC0020042 +#define RPC_NT_INTERNAL_ERROR 0xC0020043 +#define RPC_NT_ZERO_DIVIDE 0xC0020044 +#define RPC_NT_ADDRESS_ERROR 0xC0020045 +#define RPC_NT_FP_DIV_ZERO 0xC0020046 +#define RPC_NT_FP_UNDERFLOW 0xC0020047 +#define RPC_NT_FP_OVERFLOW 0xC0020048 +#define RPC_NT_CALL_IN_PROGRESS 0xC0020049 +#define RPC_NT_NO_MORE_BINDINGS 0xC002004A +#define RPC_NT_GROUP_MEMBER_NOT_FOUND 0xC002004B +#define EPT_NT_CANT_CREATE 0xC002004C +#define RPC_NT_INVALID_OBJECT 0xC002004D +#define RPC_NT_NO_INTERFACES 0xC002004F +#define RPC_NT_CALL_CANCELLED 0xC0020050 +#define RPC_NT_BINDING_INCOMPLETE 0xC0020051 +#define RPC_NT_COMM_FAILURE 0xC0020052 +#define RPC_NT_UNSUPPORTED_AUTHN_LEVEL 0xC0020053 +#define RPC_NT_NO_PRINC_NAME 0xC0020054 +#define RPC_NT_NOT_RPC_ERROR 0xC0020055 +#define RPC_NT_SEC_PKG_ERROR 0xC0020057 +#define RPC_NT_NOT_CANCELLED 0xC0020058 +#define RPC_NT_INVALID_ASYNC_HANDLE 0xC0020062 +#define RPC_NT_INVALID_ASYNC_CALL 0xC0020063 + +#define RPC_NT_NO_MORE_ENTRIES 0xC0030001 +#define RPC_NT_SS_CHAR_TRANS_OPEN_FAIL 0xC0030002 +#define RPC_NT_SS_CHAR_TRANS_SHORT_FILE 0xC0030003 +#define RPC_NT_SS_IN_NULL_CONTEXT 0xC0030004 +#define RPC_NT_SS_CONTEXT_MISMATCH 0xC0030005 +#define RPC_NT_SS_CONTEXT_DAMAGED 0xC0030006 +#define RPC_NT_SS_HANDLES_MISMATCH 0xC0030007 +#define RPC_NT_SS_CANNOT_GET_CALL_HANDLE 0xC0030008 +#define RPC_NT_NULL_REF_POINTER 0xC0030009 +#define RPC_NT_ENUM_VALUE_OUT_OF_RANGE 0xC003000A +#define RPC_NT_BYTE_COUNT_TOO_SMALL 0xC003000B +#define RPC_NT_BAD_STUB_DATA 0xC003000C +#define RPC_NT_INVALID_ES_ACTION 0xC0030059 +#define RPC_NT_WRONG_ES_VERSION 0xC003005A +#define RPC_NT_WRONG_STUB_VERSION 0xC003005B +#define RPC_NT_INVALID_PIPE_OBJECT 0xC003005C +#define RPC_NT_INVALID_PIPE_OPERATION 0xC003005D +#define RPC_NT_WRONG_PIPE_VERSION 0xC003005E +#define RPC_NT_PIPE_CLOSED 0xC003005F +#define RPC_NT_PIPE_DISCIPLINE_ERROR 0xC0030060 +#define RPC_NT_PIPE_EMPTY 0xC0030061 + +#define STATUS_PNP_BAD_MPS_TABLE 0xC0040035 +#define STATUS_PNP_TRANSLATION_FAILED 0xC0040036 +#define STATUS_PNP_IRQ_TRANSLATION_FAILED 0xC0040037 +#define STATUS_PNP_INVALID_ID 0xC0040038 + +#define STATUS_CTX_WINSTATION_NAME_INVALID 0xC00A0001 +#define STATUS_CTX_INVALID_PD 0xC00A0002 +#define STATUS_CTX_PD_NOT_FOUND 0xC00A0003 +#define STATUS_CTX_CLOSE_PENDING 0xC00A0006 +#define STATUS_CTX_NO_OUTBUF 0xC00A0007 +#define STATUS_CTX_MODEM_INF_NOT_FOUND 0xC00A0008 +#define STATUS_CTX_INVALID_MODEMNAME 0xC00A0009 +#define STATUS_CTX_RESPONSE_ERROR 0xC00A000A +#define STATUS_CTX_MODEM_RESPONSE_TIMEOUT 0xC00A000B +#define STATUS_CTX_MODEM_RESPONSE_NO_CARRIER 0xC00A000C +#define STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE 0xC00A000D +#define STATUS_CTX_MODEM_RESPONSE_BUSY 0xC00A000E +#define STATUS_CTX_MODEM_RESPONSE_VOICE 0xC00A000F +#define STATUS_CTX_TD_ERROR 0xC00A0010 +#define STATUS_CTX_LICENSE_CLIENT_INVALID 0xC00A0012 +#define STATUS_CTX_LICENSE_NOT_AVAILABLE 0xC00A0013 +#define STATUS_CTX_LICENSE_EXPIRED 0xC00A0014 +#define STATUS_CTX_WINSTATION_NOT_FOUND 0xC00A0015 +#define STATUS_CTX_WINSTATION_NAME_COLLISION 0xC00A0016 +#define STATUS_CTX_WINSTATION_BUSY 0xC00A0017 +#define STATUS_CTX_BAD_VIDEO_MODE 0xC00A0018 +#define STATUS_CTX_GRAPHICS_INVALID 0xC00A0022 +#define STATUS_CTX_NOT_CONSOLE 0xC00A0024 +#define STATUS_CTX_CLIENT_QUERY_TIMEOUT 0xC00A0026 +#define STATUS_CTX_CONSOLE_DISCONNECT 0xC00A0027 +#define STATUS_CTX_CONSOLE_CONNECT 0xC00A0028 +#define STATUS_CTX_SHADOW_DENIED 0xC00A002A +#define STATUS_CTX_WINSTATION_ACCESS_DENIED 0xC00A002B +#define STATUS_CTX_INVALID_WD 0xC00A002E +#define STATUS_CTX_WD_NOT_FOUND 0xC00A002F +#define STATUS_CTX_SHADOW_INVALID 0xC00A0030 +#define STATUS_CTX_SHADOW_DISABLED 0xC00A0031 +#define STATUS_RDP_PROTOCOL_ERROR 0xC00A0032 +#define STATUS_CTX_CLIENT_LICENSE_NOT_SET 0xC00A0033 +#define STATUS_CTX_CLIENT_LICENSE_IN_USE 0xC00A0034 +#define STATUS_CTX_SHADOW_ENDED_BY_MODE_CHANGE 0xC00A0035 +#define STATUS_CTX_SHADOW_NOT_RUNNING 0xC00A0036 + +#define STATUS_CLUSTER_INVALID_NODE 0xC0130001 +#define STATUS_CLUSTER_NODE_EXISTS 0xC0130002 +#define STATUS_CLUSTER_JOIN_IN_PROGRESS 0xC0130003 +#define STATUS_CLUSTER_NODE_NOT_FOUND 0xC0130004 +#define STATUS_CLUSTER_LOCAL_NODE_NOT_FOUND 0xC0130005 +#define STATUS_CLUSTER_NETWORK_EXISTS 0xC0130006 +#define STATUS_CLUSTER_NETWORK_NOT_FOUND 0xC0130007 +#define STATUS_CLUSTER_NETINTERFACE_EXISTS 0xC0130008 +#define STATUS_CLUSTER_NETINTERFACE_NOT_FOUND 0xC0130009 +#define STATUS_CLUSTER_INVALID_REQUEST 0xC013000A +#define STATUS_CLUSTER_INVALID_NETWORK_PROVIDER 0xC013000B +#define STATUS_CLUSTER_NODE_DOWN 0xC013000C +#define STATUS_CLUSTER_NODE_UNREACHABLE 0xC013000D +#define STATUS_CLUSTER_NODE_NOT_MEMBER 0xC013000E +#define STATUS_CLUSTER_JOIN_NOT_IN_PROGRESS 0xC013000F +#define STATUS_CLUSTER_INVALID_NETWORK 0xC0130010 +#define STATUS_CLUSTER_NO_NET_ADAPTERS 0xC0130011 +#define STATUS_CLUSTER_NODE_UP 0xC0130012 +#define STATUS_CLUSTER_NODE_PAUSED 0xC0130013 +#define STATUS_CLUSTER_NODE_NOT_PAUSED 0xC0130014 +#define STATUS_CLUSTER_NO_SECURITY_CONTEXT 0xC0130015 +#define STATUS_CLUSTER_NETWORK_NOT_INTERNAL 0xC0130016 +#define STATUS_CLUSTER_POISONED 0xC0130017 + +#define STATUS_SXS_SECTION_NOT_FOUND 0xC0150001 +#define STATUS_SXS_CANT_GEN_ACTCTX 0xC0150002 +#define STATUS_SXS_INVALID_ACTCTXDATA_FORMAT 0xC0150003 +#define STATUS_SXS_ASSEMBLY_NOT_FOUND 0xC0150004 +#define STATUS_SXS_MANIFEST_FORMAT_ERROR 0xC0150005 +#define STATUS_SXS_MANIFEST_PARSE_ERROR 0xC0150006 +#define STATUS_SXS_ACTIVATION_CONTEXT_DISABLED 0xC0150007 +#define STATUS_SXS_KEY_NOT_FOUND 0xC0150008 +#define STATUS_SXS_VERSION_CONFLICT 0xC0150009 +#define STATUS_SXS_WRONG_SECTION_TYPE 0xC015000A +#define STATUS_SXS_THREAD_QUERIES_DISABLED 0xC015000B +#define STATUS_SXS_ASSEMBLY_MISSING 0xC015000C +#define STATUS_SXS_PROCESS_DEFAULT_ALREADY_SET 0xC015000E +#define STATUS_SXS_EARLY_DEACTIVATION 0xC015000F +#define STATUS_SXS_INVALID_DEACTIVATION 0xC0150010 +#define STATUS_SXS_MULTIPLE_DEACTIVATION 0xC0150011 +#define STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY 0xC0150012 +#define STATUS_SXS_PROCESS_TERMINATION_REQUESTED 0xC0150013 +#define STATUS_SXS_CORRUPT_ACTIVATION_STACK 0xC0150014 +#define STATUS_SXS_CORRUPTION 0xC0150015 + +#endif /* WIN32_NO_STATUS */ + +#endif /* __WINE_NTSTATUS_H */ diff --git a/reactos/lib/netapi32/.cvsignore b/reactos/lib/netapi32/.cvsignore new file mode 100644 index 00000000000..7bb1369867e --- /dev/null +++ b/reactos/lib/netapi32/.cvsignore @@ -0,0 +1,6 @@ +Makefile +netapi32.def +netapi32.dll +netapi32.dll.dbg.c +netapi32.spec.c +netapi32.spec.def diff --git a/reactos/lib/netapi32/Makefile.in b/reactos/lib/netapi32/Makefile.in new file mode 100644 index 00000000000..da5963ae906 --- /dev/null +++ b/reactos/lib/netapi32/Makefile.in @@ -0,0 +1,24 @@ +EXTRADEFS = -D_SVRAPI_ +TOPSRCDIR = @top_srcdir@ +TOPOBJDIR = ../.. +SRCDIR = @srcdir@ +VPATH = @srcdir@ +MODULE = netapi32.dll +IMPORTS = iphlpapi ws2_32 advapi32 kernel32 + +C_SRCS = \ + access.c \ + apibuf.c \ + browsr.c \ + nbcmdqueue.c \ + nbnamecache.c \ + nbt.c \ + netapi32.c \ + netbios.c \ + wksta.c + +SUBDIRS = tests + +@MAKE_DLL_RULES@ + +### Dependencies: diff --git a/reactos/lib/netapi32/Makefile.ros-template b/reactos/lib/netapi32/Makefile.ros-template new file mode 100644 index 00000000000..835e3fdbd29 --- /dev/null +++ b/reactos/lib/netapi32/Makefile.ros-template @@ -0,0 +1,21 @@ +# $Id: Makefile.ros-template,v 1.1 2004/02/10 16:57:23 sedwards Exp $ + +TARGET_NAME = netapi32 + +TARGET_OBJECTS = @C_SRCS@ + +TARGET_CFLAGS = @EXTRADEFS@ -D__REACTOS__ + +TARGET_SDKLIBS = @IMPORTS@ libwine.a ntdll.a + +TARGET_BASE = 0x76160000 + +TARGET_RC_SRCS = @RC_SRCS@ +TARGET_RC_BINSRC = @RC_BINSRC@ +TARGET_RC_BINARIES = @RC_BINARIES@ + +default: all + +DEP_OBJECTS = $(TARGET_OBJECTS) + +include $(TOOLS_PATH)/depend.mk diff --git a/reactos/lib/netapi32/access.c b/reactos/lib/netapi32/access.c new file mode 100644 index 00000000000..cebeca8ec11 --- /dev/null +++ b/reactos/lib/netapi32/access.c @@ -0,0 +1,528 @@ +/* + * Copyright 2002 Andriy Palamarchuk + * + * netapi32 access functions + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "lmcons.h" +#include "lmaccess.h" +#include "lmapibuf.h" +#include "lmerr.h" +#include "netapi32_misc.h" +#include "wine/debug.h" +#include "wine/unicode.h" + +WINE_DEFAULT_DEBUG_CHANNEL(netapi32); + +const WCHAR sAdminUserName[] = {'A','d','m','i','n','i','s','t','r','a','t', + 'o','r',0}; +const WCHAR sGuestUserName[] = {'G','u','e','s','t',0}; + +/************************************************************ + * NETAPI_ValidateServername + * + * Validates server name + */ +NET_API_STATUS NETAPI_ValidateServername(LPCWSTR ServerName) +{ + if (ServerName) + { + if (ServerName[0] == 0) + return ERROR_BAD_NETPATH; + else if ( + ((ServerName[0] == '\\') && + (ServerName[1] != '\\')) + || + ((ServerName[0] == '\\') && + (ServerName[1] == '\\') && + (ServerName[2] == 0)) + ) + return ERROR_INVALID_NAME; + } + return NERR_Success; +} + +/************************************************************ + * NETAPI_IsKnownUser + * + * Checks whether the user name indicates current user. + */ +BOOL NETAPI_IsKnownUser(LPCWSTR UserName) +{ + DWORD dwSize = UNLEN + 1; + BOOL Result; + LPWSTR buf; + + if (!lstrcmpW(UserName, sAdminUserName) || + !lstrcmpW(UserName, sGuestUserName)) + return TRUE; + NetApiBufferAllocate(dwSize * sizeof(WCHAR), (LPVOID *) &buf); + Result = GetUserNameW(buf, &dwSize); + + Result = Result && !lstrcmpW(UserName, buf); + NetApiBufferFree(buf); + + return Result; +} + +#define NETAPI_ForceKnownUser(UserName, FailureCode) \ + if (!NETAPI_IsKnownUser(UserName)) \ + { \ + FIXME("Can't find information for user %s\n", \ + debugstr_w(UserName)); \ + return FailureCode; \ + } + +/************************************************************ + * NetUserGetInfo (NETAPI32.@) + */ +NET_API_STATUS WINAPI +NetUserGetInfo(LPCWSTR servername, LPCWSTR username, DWORD level, + LPBYTE* bufptr) +{ + NET_API_STATUS status; + TRACE("(%s, %s, %ld, %p)\n", debugstr_w(servername), debugstr_w(username), + level, bufptr); + status = NETAPI_ValidateServername(servername); + if (status != NERR_Success) + return status; + NETAPI_ForceLocalComputer(servername, NERR_InvalidComputer); + NETAPI_ForceKnownUser(username, NERR_UserNotFound); + + switch (level) + { + case 0: + { + PUSER_INFO_0 ui; + int name_sz; + + name_sz = lstrlenW(username) + 1; + + /* set up buffer */ + NetApiBufferAllocate(sizeof(USER_INFO_0) + name_sz * sizeof(WCHAR), + (LPVOID *) bufptr); + + ui = (PUSER_INFO_0) *bufptr; + ui->usri0_name = (LPWSTR) (*bufptr + sizeof(USER_INFO_0)); + + /* get data */ + lstrcpyW(ui->usri0_name, username); + break; + } + + case 10: + { + PUSER_INFO_10 ui; + PUSER_INFO_0 ui0; + NET_API_STATUS status; + /* sizes of the field buffers in WCHARS */ + int name_sz, comment_sz, usr_comment_sz, full_name_sz; + + comment_sz = 1; + usr_comment_sz = 1; + full_name_sz = 1; + + /* get data */ + status = NetUserGetInfo(servername, username, 0, (LPBYTE *) &ui0); + if (status != NERR_Success) + { + NetApiBufferFree(ui0); + return status; + } + name_sz = lstrlenW(ui0->usri0_name) + 1; + + /* set up buffer */ + NetApiBufferAllocate(sizeof(USER_INFO_10) + + (name_sz + comment_sz + usr_comment_sz + + full_name_sz) * sizeof(WCHAR), + (LPVOID *) bufptr); + ui = (PUSER_INFO_10) *bufptr; + ui->usri10_name = (LPWSTR) (*bufptr + sizeof(USER_INFO_10)); + ui->usri10_comment = (LPWSTR) ( + ((PBYTE) ui->usri10_name) + name_sz * sizeof(WCHAR)); + ui->usri10_usr_comment = (LPWSTR) ( + ((PBYTE) ui->usri10_comment) + comment_sz * sizeof(WCHAR)); + ui->usri10_full_name = (LPWSTR) ( + ((PBYTE) ui->usri10_usr_comment) + usr_comment_sz * sizeof(WCHAR)); + + /* set data */ + lstrcpyW(ui->usri10_name, ui0->usri0_name); + NetApiBufferFree(ui0); + ui->usri10_comment[0] = 0; + ui->usri10_usr_comment[0] = 0; + ui->usri10_full_name[0] = 0; + break; + } + + case 1: + { + static const WCHAR homedirW[] = {'H','O','M','E',0}; + PUSER_INFO_1 ui; + PUSER_INFO_0 ui0; + NET_API_STATUS status; + /* sizes of the field buffers in WCHARS */ + int name_sz, password_sz, home_dir_sz, comment_sz, script_path_sz; + + password_sz = 1; /* not filled out for security reasons for NetUserGetInfo*/ + comment_sz = 1; + script_path_sz = 1; + + /* get data */ + status = NetUserGetInfo(servername, username, 0, (LPBYTE *) &ui0); + if (status != NERR_Success) + { + NetApiBufferFree(ui0); + return status; + } + name_sz = lstrlenW(ui0->usri0_name) + 1; + home_dir_sz = GetEnvironmentVariableW(homedirW, NULL,0); + /* set up buffer */ + NetApiBufferAllocate(sizeof(USER_INFO_1) + + (name_sz + password_sz + home_dir_sz + + comment_sz + script_path_sz) * sizeof(WCHAR), + (LPVOID *) bufptr); + + ui = (PUSER_INFO_1) *bufptr; + ui->usri1_name = (LPWSTR) (ui + 1); + ui->usri1_password = ui->usri1_name + name_sz; + ui->usri1_home_dir = ui->usri1_password + password_sz; + ui->usri1_comment = ui->usri1_home_dir + home_dir_sz; + ui->usri1_script_path = ui->usri1_comment + comment_sz; + /* set data */ + lstrcpyW(ui->usri1_name, ui0->usri0_name); + NetApiBufferFree(ui0); + ui->usri1_password[0] = 0; + ui->usri1_password_age = 0; + ui->usri1_priv = 0; + GetEnvironmentVariableW(homedirW, ui->usri1_home_dir,home_dir_sz); + ui->usri1_comment[0] = 0; + ui->usri1_flags = 0; + ui->usri1_script_path[0] = 0; + break; + } + case 2: + case 3: + case 4: + case 11: + case 20: + case 23: + case 1003: + case 1005: + case 1006: + case 1007: + case 1008: + case 1009: + case 1010: + case 1011: + case 1012: + case 1013: + case 1014: + case 1017: + case 1018: + case 1020: + case 1023: + case 1024: + case 1025: + case 1051: + case 1052: + case 1053: + { + FIXME("Level %ld is not implemented\n", level); + break; + } + default: + ERR("Invalid level %ld is specified\n", level); + return ERROR_INVALID_LEVEL; + } + return NERR_Success; +} + + + +/************************************************************ + * NetUserEnum (NETAPI32.@) + */ +NET_API_STATUS WINAPI +NetUserEnum(LPCWSTR servername, DWORD level, DWORD filter, LPBYTE* bufptr, + DWORD prefmaxlen, LPDWORD entriesread, LPDWORD totalentries, + LPDWORD resume_handle) +{ + FIXME("stub!\n"); + return ERROR_ACCESS_DENIED; +} + +/************************************************************ + * ACCESS_QueryAdminDisplayInformation + * + * Creates a buffer with information for the Admin User + */ +void ACCESS_QueryAdminDisplayInformation(PNET_DISPLAY_USER *buf, PDWORD pdwSize) +{ + const WCHAR sAdminUserName[] = { + 'A','d','m','i','n','i','s','t','r','a','t','o','r',0}; + + /* sizes of the field buffers in WCHARS */ + int name_sz, comment_sz, full_name_sz; + PNET_DISPLAY_USER usr; + + /* set up buffer */ + name_sz = lstrlenW(sAdminUserName); + comment_sz = 1; + full_name_sz = 1; + + *pdwSize = sizeof(NET_DISPLAY_USER); + *pdwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR); + NetApiBufferAllocate(*pdwSize, (LPVOID *) buf); + + usr = *buf; + usr->usri1_name = (LPWSTR) ((PBYTE) usr + sizeof(NET_DISPLAY_USER)); + usr->usri1_comment = (LPWSTR) ( + ((PBYTE) usr->usri1_name) + name_sz * sizeof(WCHAR)); + usr->usri1_full_name = (LPWSTR) ( + ((PBYTE) usr->usri1_comment) + comment_sz * sizeof(WCHAR)); + + /* set data */ + lstrcpyW(usr->usri1_name, sAdminUserName); + usr->usri1_comment[0] = 0; + usr->usri1_flags = UF_SCRIPT | UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD; + usr->usri1_full_name[0] = 0; + usr->usri1_user_id = 500; + usr->usri1_next_index = 0; +} + +/************************************************************ + * ACCESS_QueryGuestDisplayInformation + * + * Creates a buffer with information for the Guest User + */ +void ACCESS_QueryGuestDisplayInformation(PNET_DISPLAY_USER *buf, PDWORD pdwSize) +{ + const WCHAR sGuestUserName[] = { + 'G','u','e','s','t',0 }; + + /* sizes of the field buffers in WCHARS */ + int name_sz, comment_sz, full_name_sz; + PNET_DISPLAY_USER usr; + + /* set up buffer */ + name_sz = lstrlenW(sGuestUserName); + comment_sz = 1; + full_name_sz = 1; + + *pdwSize = sizeof(NET_DISPLAY_USER); + *pdwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR); + NetApiBufferAllocate(*pdwSize, (LPVOID *) buf); + + usr = *buf; + usr->usri1_name = (LPWSTR) ((PBYTE) usr + sizeof(NET_DISPLAY_USER)); + usr->usri1_comment = (LPWSTR) ( + ((PBYTE) usr->usri1_name) + name_sz * sizeof(WCHAR)); + usr->usri1_full_name = (LPWSTR) ( + ((PBYTE) usr->usri1_comment) + comment_sz * sizeof(WCHAR)); + + /* set data */ + lstrcpyW(usr->usri1_name, sGuestUserName); + usr->usri1_comment[0] = 0; + usr->usri1_flags = UF_ACCOUNTDISABLE | UF_SCRIPT | UF_NORMAL_ACCOUNT | + UF_DONT_EXPIRE_PASSWD; + usr->usri1_full_name[0] = 0; + usr->usri1_user_id = 500; + usr->usri1_next_index = 0; +} + +/************************************************************ + * NetQueryDisplayInformation (NETAPI32.@) + * Copies NET_DISPLAY_USER record. + */ +void ACCESS_CopyDisplayUser(PNET_DISPLAY_USER dest, LPWSTR *dest_buf, + PNET_DISPLAY_USER src) +{ + LPWSTR str = *dest_buf; + + src->usri1_name = str; + lstrcpyW(src->usri1_name, dest->usri1_name); + str = (LPWSTR) ( + ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR)); + + src->usri1_comment = str; + lstrcpyW(src->usri1_comment, dest->usri1_comment); + str = (LPWSTR) ( + ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR)); + + src->usri1_flags = dest->usri1_flags; + + src->usri1_full_name = str; + lstrcpyW(src->usri1_full_name, dest->usri1_full_name); + str = (LPWSTR) ( + ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR)); + + src->usri1_user_id = dest->usri1_user_id; + src->usri1_next_index = dest->usri1_next_index; + *dest_buf = str; +} + +/************************************************************ + * NetQueryDisplayInformation (NETAPI32.@) + * + * The buffer structure: + * - array of fixed size record of the level type + * - strings, referenced by the record of the level type + */ +NET_API_STATUS WINAPI +NetQueryDisplayInformation( + LPCWSTR ServerName, DWORD Level, DWORD Index, DWORD EntriesRequested, + DWORD PreferredMaximumLength, PDWORD ReturnedEntryCount, + PVOID *SortedBuffer) +{ + TRACE("(%s, %ld, %ld, %ld, %ld, %p, %p)\n", debugstr_w(ServerName), + Level, Index, EntriesRequested, PreferredMaximumLength, + ReturnedEntryCount, SortedBuffer); + NETAPI_ForceLocalComputer(ServerName, ERROR_ACCESS_DENIED); + switch (Level) + { + case 1: + { + /* current record */ + PNET_DISPLAY_USER inf; + /* current available strings buffer */ + LPWSTR str; + PNET_DISPLAY_USER admin, guest; + DWORD admin_size, guest_size; + LPWSTR name = NULL; + DWORD dwSize; + + /* sizes of the field buffers in WCHARS */ + int name_sz, comment_sz, full_name_sz; + + /* number of the records, returned in SortedBuffer + 3 - for current user, Administrator and Guest users + */ + int records = 3; + + FIXME("Level %ld partially implemented\n", Level); + *ReturnedEntryCount = records; + comment_sz = 1; + full_name_sz = 1; + + /* get data */ + dwSize = UNLEN + 1; + NetApiBufferAllocate(dwSize, (LPVOID *) &name); + if (!GetUserNameW(name, &dwSize)) + { + NetApiBufferFree(name); + return ERROR_ACCESS_DENIED; + } + name_sz = dwSize; + ACCESS_QueryAdminDisplayInformation(&admin, &admin_size); + ACCESS_QueryGuestDisplayInformation(&guest, &guest_size); + + /* set up buffer */ + dwSize = sizeof(NET_DISPLAY_USER) * records; + dwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR); + + NetApiBufferAllocate(dwSize + + admin_size - sizeof(NET_DISPLAY_USER) + + guest_size - sizeof(NET_DISPLAY_USER), + (LPVOID *) SortedBuffer); + inf = (PNET_DISPLAY_USER) *SortedBuffer; + str = (LPWSTR) ((PBYTE) inf + sizeof(NET_DISPLAY_USER) * records); + inf->usri1_name = str; + str = (LPWSTR) ( + ((PBYTE) str) + name_sz * sizeof(WCHAR)); + inf->usri1_comment = str; + str = (LPWSTR) ( + ((PBYTE) str) + comment_sz * sizeof(WCHAR)); + inf->usri1_full_name = str; + str = (LPWSTR) ( + ((PBYTE) str) + full_name_sz * sizeof(WCHAR)); + + /* set data */ + lstrcpyW(inf->usri1_name, name); + NetApiBufferFree(name); + inf->usri1_comment[0] = 0; + inf->usri1_flags = + UF_SCRIPT | UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD; + inf->usri1_full_name[0] = 0; + inf->usri1_user_id = 0; + inf->usri1_next_index = 0; + + inf++; + ACCESS_CopyDisplayUser(admin, &str, inf); + NetApiBufferFree(admin); + + inf++; + ACCESS_CopyDisplayUser(guest, &str, inf); + NetApiBufferFree(guest); + break; + } + + case 2: + case 3: + { + FIXME("Level %ld is not implemented\n", Level); + break; + } + + default: + ERR("Invalid level %ld is specified\n", Level); + return ERROR_INVALID_LEVEL; + } + return NERR_Success; +} + +/************************************************************ + * NetGetDCName (NETAPI32.@) + * + * Return the name of the primary domain controller (PDC) + */ + +NET_API_STATUS WINAPI +NetGetDCName(LPCWSTR servername, LPCWSTR domainname, LPBYTE *bufptr) +{ + FIXME("stub!\n"); + return NERR_DCNotFound; /* say we can't find a domain controller */ +} + + +/************************************************************ + * NetUserModalsGet (NETAPI32.@) + */ +NET_API_STATUS WINAPI NetUserModalsGet(LPCWSTR szServer, DWORD level, LPBYTE *pbuffer) +{ + FIXME("%s %ld %p\n", debugstr_w( szServer ), level, pbuffer ); + return NERR_InternalError; +} + +NET_API_STATUS WINAPI NetLocalGroupAdd( LPCWSTR servername, DWORD level, + LPBYTE buf, LPDWORD parm_err) +{ + FIXME("%s %ld %p %p\n", debugstr_w( servername ), level, buf, parm_err); + return NERR_Success; +} + +NET_API_STATUS WINAPI NetLocalGroupSetMembers( LPCWSTR servername, + LPCWSTR groupname, DWORD level, LPBYTE buf, DWORD totalentries) +{ + FIXME("%s %s %ld %p %ld\n", debugstr_w(servername), debugstr_w(groupname), + level, buf, totalentries); + return NERR_Success; +} diff --git a/reactos/lib/netapi32/apibuf.c b/reactos/lib/netapi32/apibuf.c new file mode 100644 index 00000000000..a115741739d --- /dev/null +++ b/reactos/lib/netapi32/apibuf.c @@ -0,0 +1,102 @@ +/* + * Copyright 2002 Andriy Palamarchuk + * + * Net API buffer calls + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "windef.h" +#include "winbase.h" +#include "lmcons.h" +#include "lmapibuf.h" +#include "lmerr.h" +#include "winerror.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(netapi32); + +extern inline DWORD WINAPI GetLastError(void); +extern inline DWORD WINAPI GetLastError(void) +{ + DWORD ret; + __asm__ __volatile__( ".byte 0x64\n\tmovl 0x34,%0" : "=r" (ret) ); + return ret; +} + +/************************************************************ + * NetApiBufferAllocate (NETAPI32.@) + */ +NET_API_STATUS WINAPI NetApiBufferAllocate(DWORD ByteCount, LPVOID* Buffer) +{ + TRACE("(%ld, %p)\n", ByteCount, Buffer); + *Buffer = HeapAlloc(GetProcessHeap(), 0, ByteCount); + if (*Buffer) + return NERR_Success; + else + return GetLastError(); +} + +/************************************************************ + * NetApiBufferFree (NETAPI32.@) + */ +NET_API_STATUS WINAPI NetApiBufferFree(LPVOID Buffer) +{ + TRACE("(%p)\n", Buffer); + HeapFree(GetProcessHeap(), 0, Buffer); + return NERR_Success; +} + +/************************************************************ + * NetApiBufferReallocate (NETAPI32.@) + */ +NET_API_STATUS WINAPI NetApiBufferReallocate(LPVOID OldBuffer, DWORD NewByteCount, + LPVOID* NewBuffer) +{ + TRACE("(%p, %ld, %p)\n", OldBuffer, NewByteCount, NewBuffer); + if (NewByteCount) + { + *NewBuffer = HeapReAlloc(GetProcessHeap(), 0, OldBuffer, NewByteCount); + return *NewBuffer ? NERR_Success : GetLastError(); + } + else + { + if (!HeapFree(GetProcessHeap(), 0, OldBuffer)) return GetLastError(); + *NewBuffer = 0; + return NERR_Success; + } +} + +/************************************************************ + * NetApiBufferSize (NETAPI32.@) + */ +NET_API_STATUS WINAPI NetApiBufferSize(LPVOID Buffer, LPDWORD ByteCount) +{ + DWORD dw; + + TRACE("(%p, %p)\n", Buffer, ByteCount); + if (Buffer == NULL) + return ERROR_INVALID_PARAMETER; + dw = HeapSize(GetProcessHeap(), 0, Buffer); + TRACE("size: %ld\n", dw); + if (dw != 0xFFFFFFFF) + *ByteCount = dw; + else + *ByteCount = 0; + + return NERR_Success; +} diff --git a/reactos/lib/netapi32/browsr.c b/reactos/lib/netapi32/browsr.c new file mode 100644 index 00000000000..61ad3e32591 --- /dev/null +++ b/reactos/lib/netapi32/browsr.c @@ -0,0 +1,62 @@ +/* + * Copyright 2002 Andriy Palamarchuk + * + * netapi32 browser functions + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "lmcons.h" +#include "lmbrowsr.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(netapi32); + +/************************************************************ + * I_BrowserSetNetlogonState (NETAPI32.@) + */ +NET_API_STATUS I_BrowserSetNetlogonState( + LPWSTR ServerName, LPWSTR DomainName, LPWSTR EmulatedServerName, + DWORD Role) +{ + return ERROR_NOT_SUPPORTED; +} + +/************************************************************ + * I_BrowserQueryEmulatedDomains (NETAPI32.@) + */ +NET_API_STATUS I_BrowserQueryEmulatedDomains(LPWSTR ServerName,PBYTE* blah,PDWORD EntriesRead) +//NET_API_STATUS I_BrowserQueryEmulatedDomains( +// LPWSTR ServerName, PBYTE *EmulatedDomains +// PDWORD EntriesRead) +{ + return ERROR_NOT_SUPPORTED; +} + +/************************************************************ + * NetShareEnum (NETAPI32.@) + */ +NET_API_STATUS WINAPI NetShareEnum( LPWSTR servername, DWORD level, LPBYTE* bufptr, + DWORD prefmaxlen, LPDWORD entriesread, LPDWORD totalentries, LPDWORD resume_handle) +{ + FIXME("%s %ld %p %ld %p %p %p\n", debugstr_w(servername), level, bufptr, + prefmaxlen, entriesread, totalentries, resume_handle); + return ERROR_NOT_SUPPORTED; +} diff --git a/reactos/lib/netapi32/nbcmdqueue.c b/reactos/lib/netapi32/nbcmdqueue.c new file mode 100644 index 00000000000..ef6ad86bc1f --- /dev/null +++ b/reactos/lib/netapi32/nbcmdqueue.c @@ -0,0 +1,199 @@ +/* Copyright (c) 2003 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "config.h" +#include "wine/debug.h" +#include "nbcmdqueue.h" + +WINE_DEFAULT_DEBUG_CHANNEL(netbios); + +struct NBCmdQueue +{ + HANDLE heap; + CRITICAL_SECTION cs; + PNCB head; +}; + +#define CANCEL_EVENT_PTR(ncb) (PHANDLE)((ncb)->ncb_reserve) +#define NEXT_PTR(ncb) (PNCB *)((ncb)->ncb_reserve + sizeof(HANDLE)) + +/* The reserved area of an ncb will be used for the following data: + * - a cancelled flag (BOOL, 4 bytes??) + * - a handle to an event that's set by a cancelled command on completion + * (HANDLE, 4 bytes) + * These members are used in the following way + * - on cancel, set the event member of the reserved field (with create event) + * - NBCmdComplete will delete the ncb from the queue of there's no event; + * otherwise it will set the event and not delete the ncb + * - cancel must lock the queue before finding the ncb in it, and can unlock it + * once it's set the event (and the cancelled flag) + * - NBCmdComplete must lock the queue before attempting to remove the ncb or + * check the event + * - NBCmdQueueCancelAll will lock the queue, and cancel all ncb's in the queue. + * It'll then unlock the queue, and wait on the event in the head of the queue + * until there's no more ncb's in the queue. + * Space optimization: use the handle as a boolean. NULL == 0 => not cancelled. + * Non-NULL == valid handle => cancelled. This allows storing a next pointer + * in the ncb's reserved field as well, avoiding a memory alloc for a new + * command (cool). + */ + +struct NBCmdQueue *NBCmdQueueCreate(HANDLE heap) +{ + struct NBCmdQueue *queue; + + if (heap == NULL) + heap = GetProcessHeap(); + queue = (struct NBCmdQueue *)HeapAlloc(heap, 0, sizeof(struct NBCmdQueue)); + if (queue) + { + queue->heap = heap; + InitializeCriticalSection(&queue->cs); + queue->head = NULL; + } + return queue; +} + +UCHAR NBCmdQueueAdd(struct NBCmdQueue *queue, PNCB ncb) +{ + UCHAR ret; + + TRACE(": queue %p, ncb %p\n", queue, ncb); + + if (!queue) + return NRC_BADDR; + if (!ncb) + return NRC_INVADDRESS; + + *CANCEL_EVENT_PTR(ncb) = NULL; + EnterCriticalSection(&queue->cs); + *NEXT_PTR(ncb) = queue->head; + queue->head = ncb; + ret = NRC_GOODRET; + LeaveCriticalSection(&queue->cs); + TRACE("returning 0x%02x\n", ret); + return ret; +} + +static PNCB *NBCmdQueueFindNBC(struct NBCmdQueue *queue, PNCB ncb) +{ + PNCB *ret; + + if (!queue || !ncb) + ret = NULL; + else + { + ret = &queue->head; + while (ret && *ret != ncb) + ret = NEXT_PTR(*ret); + } + return ret; +} + +UCHAR NBCmdQueueCancel(struct NBCmdQueue *queue, PNCB ncb) +{ + UCHAR ret; + PNCB *spot; + + TRACE(": queue %p, ncb %p\n", queue, ncb); + + if (!queue) + return NRC_BADDR; + if (!ncb) + return NRC_INVADDRESS; + + EnterCriticalSection(&queue->cs); + spot = NBCmdQueueFindNBC(queue, ncb); + if (spot) + { + *CANCEL_EVENT_PTR(*spot) = CreateEventW(NULL, FALSE, FALSE, NULL); + WaitForSingleObject(*CANCEL_EVENT_PTR(*spot), INFINITE); + CloseHandle(*CANCEL_EVENT_PTR(*spot)); + *spot = *NEXT_PTR(*spot); + if (ncb->ncb_retcode == NRC_CMDCAN) + ret = NRC_CMDCAN; + else + ret = NRC_CANOCCR; + } + else + ret = NRC_INVADDRESS; + LeaveCriticalSection(&queue->cs); + TRACE("returning 0x%02x\n", ret); + return ret; +} + +UCHAR NBCmdQueueComplete(struct NBCmdQueue *queue, PNCB ncb, UCHAR retcode) +{ + UCHAR ret; + PNCB *spot; + + TRACE(": queue %p, ncb %p\n", queue, ncb); + + if (!queue) + return NRC_BADDR; + if (!ncb) + return NRC_INVADDRESS; + + EnterCriticalSection(&queue->cs); + spot = NBCmdQueueFindNBC(queue, ncb); + if (spot) + { + if (*CANCEL_EVENT_PTR(*spot)) + SetEvent(*CANCEL_EVENT_PTR(*spot)); + else + *spot = *NEXT_PTR(*spot); + ret = NRC_GOODRET; + } + else + ret = NRC_INVADDRESS; + LeaveCriticalSection(&queue->cs); + TRACE("returning 0x%02x\n", ret); + return ret; +} + +UCHAR NBCmdQueueCancelAll(struct NBCmdQueue *queue) +{ + UCHAR ret; + + TRACE(": queue %p\n", queue); + + if (!queue) + return NRC_BADDR; + + EnterCriticalSection(&queue->cs); + while (queue->head) + { + TRACE(": waiting for ncb %p (command 0x%02x)\n", queue->head, + queue->head->ncb_command); + NBCmdQueueCancel(queue, queue->head); + } + LeaveCriticalSection(&queue->cs); + ret = NRC_GOODRET; + TRACE("returning 0x%02x\n", ret); + return ret; +} + +void NBCmdQueueDestroy(struct NBCmdQueue *queue) +{ + TRACE(": queue %p\n", queue); + + if (queue) + { + NBCmdQueueCancelAll(queue); + DeleteCriticalSection(&queue->cs); + HeapFree(queue->heap, 0, queue); + } +} diff --git a/reactos/lib/netapi32/nbcmdqueue.h b/reactos/lib/netapi32/nbcmdqueue.h new file mode 100644 index 00000000000..f06f95b539e --- /dev/null +++ b/reactos/lib/netapi32/nbcmdqueue.h @@ -0,0 +1,66 @@ +/* Copyright (c) 2003 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __NBCMDQUEUE_H__ +#define __NBCMDQUEUE_H__ + +#include +#include "windef.h" +#include "winbase.h" +#include "nb30.h" + +/* This file defines a queue of pending NetBIOS commands. The queue operations + * are thread safe, with the exception of NBCmdQueueDestroy: ensure no other + * threads are manipulating the queue when calling NBCmdQueueDestroy. + */ + +struct NBCmdQueue; + +/* Allocates a new command queue from heap. */ +struct NBCmdQueue *NBCmdQueueCreate(HANDLE heap); + +/* Adds ncb to queue. Assumes queue is not NULL, and ncb is not already in the + * queue. If ncb is already in the queue, returns NRC_TOOMANY. + */ +UCHAR NBCmdQueueAdd(struct NBCmdQueue *queue, PNCB ncb); + +/* Cancels the given ncb. Blocks until the command completes. Implicitly + * removes ncb from the queue. Assumes queue and ncb are not NULL, and that + * ncb has been added to queue previously. + * Returns NRC_CMDCAN on a successful cancellation, NRC_CMDOCCR if the command + * completed before it could be cancelled, and various other return values for + * different failures. + */ +UCHAR NBCmdQueueCancel(struct NBCmdQueue *queue, PNCB ncb); + +/* Sets the return code of the given ncb, and implicitly removes the command + * from the queue. Assumes queue and ncb are not NULL, and that ncb has been + * added to queue previously. + * Returns NRC_GOODRET on success. + */ +UCHAR NBCmdQueueComplete(struct NBCmdQueue *queue, PNCB ncb, UCHAR retcode); + +/* Cancels all pending commands in the queue (useful for a RESET or a shutdown). + * Returns when all commands have been completed. + */ +UCHAR NBCmdQueueCancelAll(struct NBCmdQueue *queue); + +/* Frees all memory associated with the queue. Blocks until all commands + * pending in the queue have been completed. + */ +void NBCmdQueueDestroy(struct NBCmdQueue *queue); + +#endif /* __NBCMDQUEUE_H__ */ diff --git a/reactos/lib/netapi32/nbnamecache.c b/reactos/lib/netapi32/nbnamecache.c new file mode 100644 index 00000000000..f536e864eb8 --- /dev/null +++ b/reactos/lib/netapi32/nbnamecache.c @@ -0,0 +1,218 @@ +/* Copyright (c) 2003 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This implementation uses a linked list, because I don't have a decent + * hash table implementation handy. This is somewhat inefficient, but it's + * rather more efficient than not having a name cache at all. + */ + +#include "config.h" +#include "wine/port.h" +#include "wine/debug.h" + +#include "nbnamecache.h" + +WINE_DEFAULT_DEBUG_CHANNEL(netbios); + +typedef struct _NBNameCacheNode +{ + DWORD expireTime; + NBNameCacheEntry *entry; + struct _NBNameCacheNode *next; +} NBNameCacheNode; + +struct NBNameCache +{ + HANDLE heap; + CRITICAL_SECTION cs; + DWORD entryExpireTimeMS; + NBNameCacheNode *head; +}; + +/* Unlinks the node pointed to by *prev, and frees any associated memory. + * If that node's next pointed to another node, *prev now points to it. + * Assumes the caller owns cache's lock. + */ +static void NBNameCacheUnlinkNode(struct NBNameCache *cache, + NBNameCacheNode **prev) +{ + if (cache && prev && *prev) + { + NBNameCacheNode *next = (*prev)->next; + + if ((*prev)->entry) + HeapFree(cache->heap, 0, (*prev)->entry); + HeapFree(cache->heap, 0, *prev); + *prev = next; + } +} + +/* Walks the list beginning with cache->head looking for the node with name + * name. If the node is found, returns a pointer to the next pointer of the + * node _prior_ to the found node (or head if head points to it). Thus, if the + * node's all you want, dereference the return value twice. If you want to + * modify the list, modify the referent of the return value. + * While it's at it, deletes nodes whose time has expired (except the node + * you're looking for, of course). + * Returns NULL if the node isn't found. + * Assumes the caller owns cache's lock. + */ +static NBNameCacheNode **NBNameCacheWalk(struct NBNameCache *cache, + const char name[NCBNAMSZ]) +{ + NBNameCacheNode **ret = NULL; + + if (cache && cache->head) + { + NBNameCacheNode **ptr; + + ptr = &cache->head; + while (ptr && *ptr && (*ptr)->entry) + { + if (!memcmp((*ptr)->entry->name, name, NCBNAMSZ - 1)) + ret = ptr; + else + { + if (GetTickCount() > (*ptr)->expireTime) + NBNameCacheUnlinkNode(cache, ptr); + } + if (*ptr) + ptr = &(*ptr)->next; + } + } + return ret; +} + +struct NBNameCache *NBNameCacheCreate(HANDLE heap, DWORD entryExpireTimeMS) +{ + struct NBNameCache *cache; + + + if (!heap) + heap = GetProcessHeap(); + cache = (struct NBNameCache *)HeapAlloc(heap, 0, + sizeof(struct NBNameCache)); + if (cache) + { + cache->heap = heap; + InitializeCriticalSection(&cache->cs); + cache->entryExpireTimeMS = entryExpireTimeMS; + cache->head = NULL; + } + return cache; +} + +BOOL NBNameCacheAddEntry(struct NBNameCache *cache, NBNameCacheEntry *entry) +{ + BOOL ret; + + if (cache && entry) + { + NBNameCacheNode **node; + + EnterCriticalSection(&cache->cs); + node = NBNameCacheWalk(cache, entry->name); + if (node) + { + (*node)->expireTime = GetTickCount() + + cache->entryExpireTimeMS; + HeapFree(cache->heap, 0, (*node)->entry); + (*node)->entry = entry; + ret = TRUE; + } + else + { + NBNameCacheNode *newNode = (NBNameCacheNode *)HeapAlloc( + cache->heap, 0, sizeof(NBNameCacheNode)); + if (newNode) + { + newNode->expireTime = GetTickCount() + + cache->entryExpireTimeMS; + newNode->entry = entry; + newNode->next = cache->head; + cache->head = newNode; + ret = TRUE; + } + else + ret = FALSE; + } + LeaveCriticalSection(&cache->cs); + } + else + ret = FALSE; + return ret; +} + +const NBNameCacheEntry *NBNameCacheFindEntry(struct NBNameCache *cache, + const UCHAR name[NCBNAMSZ]) +{ + const NBNameCacheEntry *ret; + UCHAR printName[NCBNAMSZ]; + + memcpy(printName, name, NCBNAMSZ - 1); + printName[NCBNAMSZ - 1] = '\0'; + if (cache) + { + NBNameCacheNode **node; + + EnterCriticalSection(&cache->cs); + node = NBNameCacheWalk(cache, name); + if (node) + ret = (*node)->entry; + else + ret = NULL; + LeaveCriticalSection(&cache->cs); + } + else + ret = NULL; + return ret; +} + +BOOL NBNameCacheUpdateNBName(struct NBNameCache *cache, + const UCHAR name[NCBNAMSZ], const UCHAR nbname[NCBNAMSZ]) +{ + BOOL ret; + + if (cache) + { + NBNameCacheNode **node; + + EnterCriticalSection(&cache->cs); + node = NBNameCacheWalk(cache, name); + if (node && *node && (*node)->entry) + { + memcpy((*node)->entry->nbname, nbname, NCBNAMSZ); + ret = TRUE; + } + else + ret = FALSE; + LeaveCriticalSection(&cache->cs); + } + else + ret = FALSE; + return ret; +} + +void NBNameCacheDestroy(struct NBNameCache *cache) +{ + if (cache) + { + DeleteCriticalSection(&cache->cs); + while (cache->head) + NBNameCacheUnlinkNode(cache, &cache->head); + HeapFree(cache->heap, 0, cache); + } +} diff --git a/reactos/lib/netapi32/nbnamecache.h b/reactos/lib/netapi32/nbnamecache.h new file mode 100644 index 00000000000..04e366314ee --- /dev/null +++ b/reactos/lib/netapi32/nbnamecache.h @@ -0,0 +1,82 @@ +/* Copyright (c) 2003 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __WINE_NBNAMECACHE_H +#define __WINE_NBNAMECACHE_H + +#include + +#include "windef.h" +#include "winbase.h" +#include "nb30.h" + +struct NBNameCache; + +/* Represents an entry in the name cache. If the NetBIOS name is known, it's + * in nbname. Otherwise, nbname begins with '*'. numAddresses defines the + * number of addresses in addresses. + * Notice that it allows multiple addresses per name, but doesn't explicitly + * allow group names. That's because all names so far are unique; if a use for + * group names comes up, adding a flag here is simple enough. + * Also, only the first NCBNAMSZ - 1 bytes are considered significant. This is + * because a name may have been resolved using DNS, and the suffix byte is + * always truncated for DNS lookups. + */ +typedef struct _NBNameCacheEntry +{ + UCHAR name[NCBNAMSZ]; + UCHAR nbname[NCBNAMSZ]; + DWORD numAddresses; + DWORD addresses[1]; +} NBNameCacheEntry; + +/* Functions that create, manipulate, and destroy a name cache. Thread-safe, + * with the exception of NBNameCacheDestroy--ensure that no other threads are + * manipulating the cache before destoying it. + */ + +/* Allocates a new name cache from heap, and sets the expire time on new + * entries to entryExpireTimeMS after a cache entry is added. + */ +struct NBNameCache *NBNameCacheCreate(HANDLE heap, DWORD entryExpireTimeMS); + +/* Adds an entry to the cache. The entry is assumed to have been allocated + * from the same heap as the name cache; the name cache will own the entry + * from now on. The entry's expire time is initialized at this time to + * entryExpireTimeMS + the current time in MS. If an existing entry with the + * same name was in the cache, the entry is replaced. Returns TRUE on success + * or FALSE on failure. + */ +BOOL NBNameCacheAddEntry(struct NBNameCache *cache, NBNameCacheEntry *entry); + +/* Finds the entry with name name in the cache and returns a pointer to it, or + * NULL if it isn't found. + */ +const NBNameCacheEntry *NBNameCacheFindEntry(struct NBNameCache *cache, + const UCHAR name[NCBNAMSZ]); + +/* If the entry with name name is in the cache, updates its nbname member to + * nbname. The entry's expire time is implicitly updated to entryExpireTimeMS + * + the current time in MS, since getting the NetBIOS name meant validating + * the name and address anyway. + * Returns TRUE on success or FALSE on failure. + */ +BOOL NBNameCacheUpdateNBName(struct NBNameCache *cache, + const UCHAR name[NCBNAMSZ], const UCHAR nbname[NCBNAMSZ]); + +void NBNameCacheDestroy(struct NBNameCache *cache); + +#endif /* ndef __WINE_NBNAMECACHE_H */ diff --git a/reactos/lib/netapi32/nbt.c b/reactos/lib/netapi32/nbt.c new file mode 100644 index 00000000000..3cb6d63ce80 --- /dev/null +++ b/reactos/lib/netapi32/nbt.c @@ -0,0 +1,1535 @@ +/* Copyright (c) 2003 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * I am heavily indebted to Chris Hertel's excellent Implementing CIFS, + * http://ubiqx.org/cifs/ , for whatever understanding I have of NBT. + * I also stole from Mike McCormack's smb.c and netapi32.c, although little of + * that code remains. + * Lack of understanding and bugs are my fault. + * + * FIXME: + * - Of the NetBIOS session functions, only client functions are supported, and + * it's likely they'll be the only functions supported. NBT requires session + * servers to listen on TCP/139. This requires root privilege, and Samba is + * likely to be listening here already. This further restricts NetBIOS + * applications, both explicit users and implicit ones: CreateNamedPipe + * won't actually create a listening pipe, for example, so applications can't + * act as RPC servers using a named pipe protocol binding, DCOM won't be able + * to support callbacks or servers over the named pipe protocol, etc. + * + * - Datagram support is omitted for the same reason. To send a NetBIOS + * datagram, you must include the NetBIOS name by which your application is + * known. This requires you to have registered the name previously, and be + * able to act as a NetBIOS datagram server (listening on UDP/138). + * + * - Name registration functions are omitted for the same reason--registering a + * name requires you to be able to defend it, and this means listening on + * UDP/137. + * Win98 requires you either use your computer's NetBIOS name (with the NULL + * suffix byte) as the calling name when creating a session, or to register + * a new name before creating one: it disallows '*' as the calling name. + * Win2K initially starts with an empty name table, and doesn't allow you to + * use the machine's NetBIOS name (with the NULL suffix byte) as the calling + * name. Although it allows sessions to be created with '*' as the calling + * name, doing so results in timeouts for all receives, because the + * application never gets them. + * So, a well-behaved Netbios application will typically want to register a + * name. I should probably support a do-nothing name list that allows + * NCBADDNAME to add to it, but doesn't actually register the name, or does + * attempt to register it without being able to defend it. + * + * - Name lookups may not behave quite as you'd expect/like if you have + * multiple LANAs. If a name is resolvable through DNS, or if you're using + * WINS, it'll resolve on _any_ LANA. So, a Call will succeed on any LANA as + * well. + * I'm not sure how Windows behaves in this case. I could try to force + * lookups to the correct adapter by using one of the GetPreferred* + * functions, but with the possibility of multiple adapters in the same + * same subnet, there's no guarantee that what IpHlpApi thinks is the + * preferred adapter will actually be a LANA. (It's highly probable because + * this is an unusual configuration, but not guaranteed.) + * + * See also other FIXMEs in the code. + */ + +#include "config.h" +#include + +#include "windef.h" +#include "winbase.h" +#include "winsock2.h" +#include "wine/debug.h" +#include "winreg.h" +#include "iphlpapi.h" + +#include "netbios.h" +#include "nbnamecache.h" + +WINE_DEFAULT_DEBUG_CHANNEL(netbios); + +#define PORT_NBNS 137 +#define PORT_NBDG 138 +#define PORT_NBSS 139 + +#ifndef INADDR_NONE +#define INADDR_NONE ~0UL +#endif + +#define NBR_ADDWORD(p,word) (*(WORD *)(p)) = htons(word) +#define NBR_GETWORD(p) ntohs(*(WORD *)(p)) + +#define MIN_QUERIES 1 +#define MAX_QUERIES 0xffff +#define MIN_QUERY_TIMEOUT 100 +#define MAX_QUERY_TIMEOUT 0xffffffff +#define BCAST_QUERIES 3 +#define BCAST_QUERY_TIMEOUT 750 +#define WINS_QUERIES 3 +#define WINS_QUERY_TIMEOUT 750 +#define MAX_WINS_SERVERS 2 +#define MIN_CACHE_TIMEOUT 60000 +#define CACHE_TIMEOUT 360000 + +#define MAX_NBT_NAME_SZ (NCBNAMSZ * 2 + MAX_DOMAIN_NAME_LEN + 2) +#define SIMPLE_NAME_QUERY_PKT_SIZE 26 + MAX_NBT_NAME_SZ + +#define DEFAULT_NBT_SESSIONS 16 + +#define NBNS_TYPE_NB 0x0020 +#define NBNS_TYPE_NBSTAT 0x0021 +#define NBNS_CLASS_INTERNET 0x00001 +#define NBNS_HEADER_SIZE (sizeof(WORD) * 6) +#define NBNS_RESPONSE_AND_OPCODE 0xf800 +#define NBNS_RESPONSE_AND_QUERY 0x8000 +#define NBNS_REPLYCODE 0x0f + +#define NBSS_HDRSIZE 4 + +#define NBSS_MSG 0x00 +#define NBSS_REQ 0x81 +#define NBSS_ACK 0x82 +#define NBSS_NACK 0x83 +#define NBSS_RETARGET 0x84 +#define NBSS_KEEPALIVE 0x85 + +#define NBSS_ERR_NOT_LISTENING_ON_NAME 0x80 +#define NBSS_ERR_NOT_LISTENING_FOR_CALLER 0x81 +#define NBSS_ERR_BAD_NAME 0x82 +#define NBSS_ERR_INSUFFICIENT_RESOURCES 0x83 + +#define NBSS_EXTENSION 0x01 + +typedef struct _NetBTSession +{ + CRITICAL_SECTION cs; + SOCKET fd; + DWORD bytesPending; +} NetBTSession; + +typedef struct _NetBTAdapter +{ + MIB_IPADDRROW ipr; + WORD nameQueryXID; + struct NBNameCache *nameCache; + DWORD xmit_success; + DWORD recv_success; +} NetBTAdapter; + +static ULONG gTransportID; +static BOOL gEnableDNS; +static DWORD gBCastQueries; +static DWORD gBCastQueryTimeout; +static DWORD gWINSQueries; +static DWORD gWINSQueryTimeout; +static DWORD gWINSServers[MAX_WINS_SERVERS]; +static int gNumWINSServers; +static char gScopeID[MAX_DOMAIN_NAME_LEN]; +static DWORD gCacheTimeout; +static struct NBNameCache *gNameCache; + +/* Converts from a NetBIOS name into a Second Level Encoding-formatted name. + * Assumes p is not NULL and is either NULL terminated or has at most NCBNAMSZ + * bytes, and buffer has at least MAX_NBT_NAME_SZ bytes. Pads with space bytes + * if p is NULL-terminated. Returns the number of bytes stored in buffer. + */ +static int NetBTNameEncode(const UCHAR *p, UCHAR *buffer) +{ + int i,len=0; + + if (!p) return 0; + if (!buffer) return 0; + + buffer[len++] = NCBNAMSZ * 2; + for (i = 0; p[i] && i < NCBNAMSZ; i++) + { + buffer[len++] = ((p[i] & 0xf0) >> 4) + 'A'; + buffer[len++] = (p[i] & 0x0f) + 'A'; + } + while (len < NCBNAMSZ * 2) + { + buffer[len++] = 'C'; + buffer[len++] = 'A'; + } + if (*gScopeID) + { + int scopeIDLen = strlen(gScopeID); + + memcpy(buffer + len, gScopeID, scopeIDLen); + len += scopeIDLen; + } + buffer[len++] = 0; /* add second terminator */ + return len; +} + +/* Creates a NBT name request packet for name in buffer. If broadcast is true, + * creates a broadcast request, otherwise creates a unicast request. + * Returns the number of bytes stored in buffer. + */ +static DWORD NetBTNameReq(const UCHAR name[NCBNAMSZ], WORD xid, WORD qtype, + BOOL broadcast, UCHAR *buffer, int len) +{ + int i = 0; + + if (len < SIMPLE_NAME_QUERY_PKT_SIZE) return 0; + + NBR_ADDWORD(&buffer[i],xid); i+=2; /* transaction */ + if (broadcast) + { + NBR_ADDWORD(&buffer[i],0x0110); /* flags: r=req,op=query,rd=1,b=1 */ + i+=2; + } + else + { + NBR_ADDWORD(&buffer[i],0x0100); /* flags: r=req,op=query,rd=1,b=0 */ + i+=2; + } + NBR_ADDWORD(&buffer[i],0x0001); i+=2; /* one name query */ + NBR_ADDWORD(&buffer[i],0x0000); i+=2; /* zero answers */ + NBR_ADDWORD(&buffer[i],0x0000); i+=2; /* zero authorities */ + NBR_ADDWORD(&buffer[i],0x0000); i+=2; /* zero additional */ + + i += NetBTNameEncode(name, &buffer[i]); + + NBR_ADDWORD(&buffer[i],qtype); i+=2; + NBR_ADDWORD(&buffer[i],NBNS_CLASS_INTERNET); i+=2; + + return i; +} + +/* Sends a name query request for name on fd to destAddr. Sets SO_BROADCAST on + * fd if broadcast is TRUE. Assumes fd is not INVALID_SOCKET, and name is not + * NULL. + * Returns 0 on success, -1 on failure. + */ +static int NetBTSendNameQuery(SOCKET fd, const UCHAR name[NCBNAMSZ], WORD xid, + WORD qtype, DWORD destAddr, BOOL broadcast) +{ + int ret = 0, on = 1; + struct in_addr addr; + + addr.s_addr = destAddr; + TRACE("name %s, dest addr %s\n", name, inet_ntoa(addr)); + + if (broadcast) + ret = setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (PUCHAR)&on, sizeof(on)); + if(ret == 0) + { + WSABUF wsaBuf; + UCHAR buf[SIMPLE_NAME_QUERY_PKT_SIZE]; + struct sockaddr_in sin; + + memset(&sin, 0, sizeof(sin)); + sin.sin_addr.s_addr = destAddr; + sin.sin_family = AF_INET; + sin.sin_port = htons(PORT_NBNS); + + wsaBuf.buf = buf; + wsaBuf.len = NetBTNameReq(name, xid, qtype, broadcast, buf, + sizeof(buf)); + if (wsaBuf.len > 0) + { + DWORD bytesSent; + + ret = WSASendTo(fd, &wsaBuf, 1, &bytesSent, 0, + (struct sockaddr*)&sin, sizeof(sin), NULL, NULL); + if (ret < 0 || bytesSent < wsaBuf.len) + ret = -1; + else + ret = 0; + } + else + ret = -1; + } + return ret; +} + +typedef BOOL (*NetBTAnswerCallback)(void *data, WORD answerCount, + WORD answerIndex, PUCHAR rData, WORD rdLength); + +/* Waits on fd until GetTickCount() returns a value greater than or equal to + * waitUntil for a name service response. If a name response matching xid + * is received, calls answerCallback once for each answer resource record in + * the response. (The callback's answerCount will be the total number of + * answers to expect, and answerIndex will be the 0-based index that's being + * sent this time.) Quits parsing if answerCallback returns FALSE. + * Returns NRC_GOODRET on timeout or a valid response received, something else + * on error. + */ +static UCHAR NetBTWaitForNameResponse(NetBTAdapter *adapter, SOCKET fd, + DWORD waitUntil, NetBTAnswerCallback answerCallback, void *data) +{ + BOOL found = FALSE; + DWORD now; + UCHAR ret = NRC_GOODRET; + + if (!adapter) return NRC_BADDR; + if (fd == INVALID_SOCKET) return NRC_BADDR; + if (!answerCallback) return NRC_BADDR; + + while (!found && ret == NRC_GOODRET && (now = GetTickCount()) < waitUntil) + { + DWORD msToWait = waitUntil - now; + struct fd_set fds; + struct timeval timeout = { msToWait / 1000, msToWait % 1000 }; + int r; + + FD_ZERO(&fds); + FD_SET(fd, &fds); + r = select(fd + 1, &fds, NULL, NULL, &timeout); + if (r < 0) + ret = NRC_SYSTEM; + else if (r == 1) + { + /* FIXME: magic #, is this always enough? */ + UCHAR buffer[256]; + int fromsize; + struct sockaddr_in fromaddr; + WORD respXID, flags, queryCount, answerCount; + WSABUF wsaBuf = { sizeof(buffer), buffer }; + DWORD bytesReceived, recvFlags = 0; + + fromsize = sizeof(fromaddr); + r = WSARecvFrom(fd, &wsaBuf, 1, &bytesReceived, &recvFlags, + (struct sockaddr*)&fromaddr, &fromsize, NULL, NULL); + if(r < 0) + { + ret = NRC_SYSTEM; + break; + } + + if (bytesReceived < NBNS_HEADER_SIZE) + continue; + + respXID = NBR_GETWORD(buffer); + if (adapter->nameQueryXID != respXID) + continue; + + flags = NBR_GETWORD(buffer + 2); + queryCount = NBR_GETWORD(buffer + 4); + answerCount = NBR_GETWORD(buffer + 6); + + /* a reply shouldn't contain a query, ignore bad packet */ + if (queryCount > 0) + continue; + + if ((flags & NBNS_RESPONSE_AND_OPCODE) == NBNS_RESPONSE_AND_QUERY) + { + if ((flags & NBNS_REPLYCODE) != 0) + ret = NRC_NAMERR; + else if ((flags & NBNS_REPLYCODE) == 0 && answerCount > 0) + { + PUCHAR ptr = buffer + NBNS_HEADER_SIZE; + BOOL shouldContinue = TRUE; + WORD answerIndex = 0; + + found = TRUE; + /* decode one answer at a time */ + while (ret == NRC_GOODRET && answerIndex < answerCount && + ptr - buffer < bytesReceived && shouldContinue) + { + WORD rLen; + + /* scan past name */ + for (; ptr[0] && ptr - buffer < bytesReceived; ) + ptr += ptr[0] + 1; + ptr++; + ptr += 2; /* scan past type */ + if (ptr - buffer < bytesReceived && ret == NRC_GOODRET + && NBR_GETWORD(ptr) == NBNS_CLASS_INTERNET) + ptr += sizeof(WORD); + else + ret = NRC_SYSTEM; /* parse error */ + ptr += sizeof(DWORD); /* TTL */ + rLen = NBR_GETWORD(ptr); + rLen = min(rLen, bytesReceived - (ptr - buffer)); + ptr += sizeof(WORD); + shouldContinue = answerCallback(data, answerCount, + answerIndex, ptr, rLen); + ptr += rLen; + answerIndex++; + } + } + } + } + } + TRACE("returning 0x%02x\n", ret); + return ret; +} + +typedef struct _NetBTNameQueryData { + NBNameCacheEntry *cacheEntry; + UCHAR ret; +} NetBTNameQueryData; + +/* Name query callback function for NetBTWaitForNameResponse, creates a cache + * entry on the first answer, adds each address as it's called again (as long + * as there's space). If there's an error that should be propagated as the + * NetBIOS error, modifies queryData's ret member to the proper return code. + */ +static BOOL NetBTFindNameAnswerCallback(void *pVoid, WORD answerCount, + WORD answerIndex, PUCHAR rData, WORD rLen) +{ + NetBTNameQueryData *queryData = (NetBTNameQueryData *)pVoid; + BOOL ret; + + if (queryData) + { + if (queryData->cacheEntry == NULL) + { + queryData->cacheEntry = (NBNameCacheEntry *)HeapAlloc( + GetProcessHeap(), 0, sizeof(NBNameCacheEntry) + + (answerCount - 1) * sizeof(DWORD)); + if (queryData->cacheEntry) + queryData->cacheEntry->numAddresses = 0; + else + { + ret = FALSE; + queryData->ret = NRC_OSRESNOTAV; + } + } + if (rLen == 6 && queryData->cacheEntry && + queryData->cacheEntry->numAddresses < answerCount) + { + queryData->cacheEntry->addresses[queryData->cacheEntry-> + numAddresses++] = *(PDWORD)(rData + 2); + ret = queryData->cacheEntry->numAddresses < answerCount; + } + else + ret = FALSE; + } + else + ret = FALSE; + return ret; +} + +/* Workhorse NetBT name lookup function. Sends a name lookup query for + * ncb->ncb_callname to sendTo, as a broadcast if broadcast is TRUE, using + * adapter->nameQueryXID as the transaction ID. Waits up to timeout + * milliseconds, and retries up to maxQueries times, waiting for a reply. + * If a valid response is received, stores the looked up addresses as a + * NBNameCacheEntry in *cacheEntry. + * Returns NRC_GOODRET on success, though this may not mean the name was + * resolved--check whether *cacheEntry is NULL. + */ +static UCHAR NetBTNameWaitLoop(NetBTAdapter *adapter, SOCKET fd, PNCB ncb, + DWORD sendTo, BOOL broadcast, DWORD timeout, DWORD maxQueries, + NBNameCacheEntry **cacheEntry) +{ + int queries; + NetBTNameQueryData queryData; + + if (!adapter) return NRC_BADDR; + if (fd == INVALID_SOCKET) return NRC_BADDR; + if (!ncb) return NRC_BADDR; + if (!cacheEntry) return NRC_BADDR; + + queryData.cacheEntry = NULL; + queryData.ret = NRC_GOODRET; + for (queries = 0; queryData.cacheEntry == NULL && queries < maxQueries; + queries++) + { + if (!NCB_CANCELLED(ncb)) + { + int r = NetBTSendNameQuery(fd, ncb->ncb_callname, + adapter->nameQueryXID, NBNS_TYPE_NB, sendTo, broadcast); + + if (r == 0) + queryData.ret = NetBTWaitForNameResponse(adapter, fd, + GetTickCount() + timeout, NetBTFindNameAnswerCallback, + &queryData); + else + queryData.ret = NRC_SYSTEM; + } + else + queryData.ret = NRC_CMDCAN; + } + if (queryData.cacheEntry) + { + memcpy(queryData.cacheEntry->name, ncb->ncb_callname, NCBNAMSZ); + memcpy(queryData.cacheEntry->nbname, ncb->ncb_callname, NCBNAMSZ); + } + *cacheEntry = queryData.cacheEntry; + return queryData.ret; +} + +/* Attempts to add cacheEntry to the name cache in *nameCache; if *nameCache + * has not yet been created, creates it, using gCacheTimeout as the cache + * entry timeout. If memory allocation fails, or if NBNameCacheAddEntry fails, + * frees cacheEntry. + * Returns NRC_GOODRET on success, and something else on failure. + */ +static UCHAR NetBTStoreCacheEntry(struct NBNameCache **nameCache, + NBNameCacheEntry *cacheEntry) +{ + UCHAR ret; + + if (!nameCache) return NRC_BADDR; + if (!cacheEntry) return NRC_BADDR; + + if (!*nameCache) + *nameCache = NBNameCacheCreate(GetProcessHeap(), gCacheTimeout); + if (*nameCache) + ret = NBNameCacheAddEntry(*nameCache, cacheEntry) + ? NRC_GOODRET : NRC_OSRESNOTAV; + else + { + HeapFree(GetProcessHeap(), 0, cacheEntry); + ret = NRC_OSRESNOTAV; + } + return ret; +} + +/* Attempts to resolve name using inet_addr(), then gethostbyname() if + * gEnableDNS is TRUE, if the suffix byte is either <00> or <20>. If the name + * can be looked up, returns 0 and stores the looked up addresses as a + * NBNameCacheEntry in *cacheEntry. + * Returns NRC_GOODRET on success, though this may not mean the name was + * resolved--check whether *cacheEntry is NULL. Returns something else on + * error. + */ +static UCHAR NetBTinetResolve(const UCHAR name[NCBNAMSZ], + NBNameCacheEntry **cacheEntry) +{ + UCHAR ret = NRC_GOODRET; + + TRACE("name %s, cacheEntry %p\n", name, cacheEntry); + + if (!name) return NRC_BADDR; + if (!cacheEntry) return NRC_BADDR; + + if (isalnum(name[0]) && (name[NCBNAMSZ - 1] == 0 || + name[NCBNAMSZ - 1] == 0x20)) + { + UCHAR toLookup[NCBNAMSZ]; + int i; + + for (i = 0; i < NCBNAMSZ - 1 && name[i] && name[i] != ' '; i++) + toLookup[i] = name[i]; + toLookup[i] = '\0'; + + if (isdigit(toLookup[0])) + { + unsigned long addr = inet_addr(toLookup); + + if (addr != INADDR_NONE) + { + *cacheEntry = (NBNameCacheEntry *)HeapAlloc(GetProcessHeap(), + 0, sizeof(NBNameCacheEntry)); + if (*cacheEntry) + { + memcpy((*cacheEntry)->name, name, NCBNAMSZ); + memset((*cacheEntry)->nbname, 0, NCBNAMSZ); + (*cacheEntry)->nbname[0] = '*'; + (*cacheEntry)->numAddresses = 1; + (*cacheEntry)->addresses[0] = addr; + } + else + ret = NRC_OSRESNOTAV; + } + } + if (gEnableDNS && ret == NRC_GOODRET && !*cacheEntry) + { + struct hostent *host; + + if ((host = gethostbyname(toLookup)) != NULL) + { + for (i = 0; ret == NRC_GOODRET && host->h_addr_list && + host->h_addr_list[i]; i++) + ; + if (host->h_addr_list && host->h_addr_list[0]) + { + *cacheEntry = (NBNameCacheEntry *)HeapAlloc( + GetProcessHeap(), 0, sizeof(NBNameCacheEntry) + + (i - 1) * sizeof(DWORD)); + if (*cacheEntry) + { + memcpy((*cacheEntry)->name, name, NCBNAMSZ); + memset((*cacheEntry)->nbname, 0, NCBNAMSZ); + (*cacheEntry)->nbname[0] = '*'; + (*cacheEntry)->numAddresses = i; + for (i = 0; i < (*cacheEntry)->numAddresses; i++) + (*cacheEntry)->addresses[i] = + (DWORD)host->h_addr_list[i]; + } + else + ret = NRC_OSRESNOTAV; + } + } + } + } + + TRACE("returning 0x%02x\n", ret); + return ret; +} + +/* Looks up the name in ncb->ncb_callname, first in the name caches (global + * and this adapter's), then using gethostbyname(), next by WINS if configured, + * and finally using broadcast NetBT name resolution. In NBT parlance, this + * makes this an "H-node". Stores an entry in the appropriate name cache for a + * found node, and returns it as *cacheEntry. + * Assumes data, ncb, and cacheEntry are not NULL. + * Returns NRC_GOODRET on success--which doesn't mean the name was resolved, + * just that all name lookup operations completed successfully--and something + * else on failure. *cacheEntry will be NULL if the name was not found. + */ +static UCHAR NetBTInternalFindName(NetBTAdapter *adapter, PNCB ncb, + const NBNameCacheEntry **cacheEntry) +{ + UCHAR ret = NRC_GOODRET; + + TRACE("adapter %p, ncb %p, cacheEntry %p\n", adapter, ncb, cacheEntry); + + if (!cacheEntry) return NRC_BADDR; + *cacheEntry = NULL; + + if (!adapter) return NRC_BADDR; + if (!ncb) return NRC_BADDR; + + if (ncb->ncb_callname[0] == '*') + ret = NRC_NOWILD; + else + { + *cacheEntry = NBNameCacheFindEntry(gNameCache, ncb->ncb_callname); + if (!*cacheEntry) + *cacheEntry = NBNameCacheFindEntry(adapter->nameCache, + ncb->ncb_callname); + if (!*cacheEntry) + { + NBNameCacheEntry *newEntry = NULL; + + ret = NetBTinetResolve(ncb->ncb_callname, &newEntry); + if (ret == NRC_GOODRET && newEntry) + { + ret = NetBTStoreCacheEntry(&gNameCache, newEntry); + if (ret != NRC_GOODRET) + newEntry = NULL; + } + else + { + SOCKET fd = WSASocketA(PF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, + 0, WSA_FLAG_OVERLAPPED); + + if(fd == INVALID_SOCKET) + ret = NRC_OSRESNOTAV; + else + { + int winsNdx; + + adapter->nameQueryXID++; + for (winsNdx = 0; ret == NRC_GOODRET && *cacheEntry == NULL + && winsNdx < gNumWINSServers; winsNdx++) + ret = NetBTNameWaitLoop(adapter, fd, ncb, + gWINSServers[winsNdx], FALSE, gWINSQueryTimeout, + gWINSQueries, &newEntry); + if (ret == NRC_GOODRET && newEntry) + { + ret = NetBTStoreCacheEntry(&gNameCache, newEntry); + if (ret != NRC_GOODRET) + newEntry = NULL; + } + if (ret == NRC_GOODRET && *cacheEntry == NULL) + { + DWORD bcastAddr = + adapter->ipr.dwAddr & adapter->ipr.dwMask; + + if (adapter->ipr.dwBCastAddr) + bcastAddr |= ~adapter->ipr.dwMask; + ret = NetBTNameWaitLoop(adapter, fd, ncb, bcastAddr, + TRUE, gBCastQueryTimeout, gBCastQueries, &newEntry); + if (ret == NRC_GOODRET && newEntry) + { + ret = NetBTStoreCacheEntry(&adapter->nameCache, + newEntry); + if (ret != NRC_GOODRET) + newEntry = NULL; + } + } + closesocket(fd); + } + } + *cacheEntry = newEntry; + } + } + TRACE("returning 0x%02x\n", ret); + return ret; +} + +typedef struct _NetBTNodeQueryData +{ + BOOL gotResponse; + PADAPTER_STATUS astat; + WORD astatLen; +} NetBTNodeQueryData; + +/* Callback function for NetBTAstatRemote, parses the rData for the node + * status and name list of the remote node. Always returns FALSE, since + * there's never more than one answer we care about in a node status response. + */ +static BOOL NetBTNodeStatusAnswerCallback(void *pVoid, WORD answerCount, + WORD answerIndex, PUCHAR rData, WORD rLen) +{ + NetBTNodeQueryData *data = (NetBTNodeQueryData *)pVoid; + + if (data && !data->gotResponse && rData && rLen >= 1) + { + /* num names is first byte; each name is NCBNAMSZ + 2 bytes */ + if (rLen >= rData[0] * (NCBNAMSZ + 2)) + { + WORD i; + PUCHAR src; + PNAME_BUFFER dst; + + data->gotResponse = TRUE; + data->astat->name_count = rData[0]; + for (i = 0, src = rData + 1, + dst = (PNAME_BUFFER)((PUCHAR)data->astat + + sizeof(ADAPTER_STATUS)); + i < data->astat->name_count && src - rData < rLen && + (PUCHAR)dst - (PUCHAR)data->astat < data->astatLen; + i++, dst++, src += NCBNAMSZ + 2) + { + UCHAR flags = *(src + NCBNAMSZ); + + memcpy(dst->name, src, NCBNAMSZ); + /* we won't actually see a registering name in the returned + * response. It's useful to see if no other flags are set; if + * none are, then the name is registered. */ + dst->name_flags = REGISTERING; + if (flags & 0x80) + dst->name_flags |= GROUP_NAME; + if (flags & 0x10) + dst->name_flags |= DEREGISTERED; + if (flags & 0x08) + dst->name_flags |= DUPLICATE; + if (dst->name_flags == REGISTERING) + dst->name_flags = REGISTERED; + } + /* arbitrarily set HW type to Ethernet */ + data->astat->adapter_type = 0xfe; + if (src - rData < rLen) + memcpy(data->astat->adapter_address, src, + min(rLen - (src - rData), 6)); + } + } + return FALSE; +} + +/* This uses the WINS timeout and query values, as they're the + * UCAST_REQ_RETRY_TIMEOUT and UCAST_REQ_RETRY_COUNT according to the RFCs. + */ +static UCHAR NetBTAstatRemote(NetBTAdapter *adapter, PNCB ncb) +{ + UCHAR ret = NRC_GOODRET; + const NBNameCacheEntry *cacheEntry = NULL; + + TRACE("adapter %p, NCB %p\n", adapter, ncb); + + if (!adapter) return NRC_BADDR; + if (!ncb) return NRC_INVADDRESS; + + ret = NetBTInternalFindName(adapter, ncb, &cacheEntry); + if (ret == NRC_GOODRET && cacheEntry) + { + if (cacheEntry->numAddresses > 0) + { + SOCKET fd = WSASocketA(PF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, + WSA_FLAG_OVERLAPPED); + + if(fd == INVALID_SOCKET) + ret = NRC_OSRESNOTAV; + else + { + NetBTNodeQueryData queryData; + DWORD queries; + PADAPTER_STATUS astat = (PADAPTER_STATUS)ncb->ncb_buffer; + + adapter->nameQueryXID++; + astat->name_count = 0; + queryData.gotResponse = FALSE; + queryData.astat = astat; + queryData.astatLen = ncb->ncb_length; + for (queries = 0; !queryData.gotResponse && + queries < gWINSQueries; queries++) + { + if (!NCB_CANCELLED(ncb)) + { + int r = NetBTSendNameQuery(fd, ncb->ncb_callname, + adapter->nameQueryXID, NBNS_TYPE_NBSTAT, + cacheEntry->addresses[0], FALSE); + + if (r == 0) + ret = NetBTWaitForNameResponse(adapter, fd, + GetTickCount() + gWINSQueryTimeout, + NetBTNodeStatusAnswerCallback, &queryData); + else + ret = NRC_SYSTEM; + } + else + ret = NRC_CMDCAN; + } + closesocket(fd); + } + } + else + ret = NRC_CMDTMO; + } + else if (ret == NRC_CMDCAN) + ; /* do nothing, we were cancelled */ + else + ret = NRC_CMDTMO; + TRACE("returning 0x%02x\n", ret); + return ret; +} + +static UCHAR NetBTAstat(void *adapt, PNCB ncb) +{ + NetBTAdapter *adapter = (NetBTAdapter *)adapt; + UCHAR ret; + + TRACE("adapt %p, NCB %p\n", adapt, ncb); + + if (!adapter) return NRC_ENVNOTDEF; + if (!ncb) return NRC_INVADDRESS; + if (!ncb->ncb_buffer) return NRC_BADDR; + if (ncb->ncb_length < sizeof(ADAPTER_STATUS)) return NRC_BUFLEN; + + if (ncb->ncb_callname[0] == '*') + { + DWORD physAddrLen; + MIB_IFROW ifRow; + PADAPTER_STATUS astat = (PADAPTER_STATUS)ncb->ncb_buffer; + + memset(astat, 0, sizeof(ADAPTER_STATUS)); + astat->rev_major = 3; + ifRow.dwIndex = adapter->ipr.dwIndex; + if (GetIfEntry(&ifRow) != NO_ERROR) + ret = NRC_BRIDGE; + else + { + physAddrLen = min(ifRow.dwPhysAddrLen, 6); + if (physAddrLen > 0) + memcpy(astat->adapter_address, ifRow.bPhysAddr, physAddrLen); + /* doubt anyone cares, but why not.. */ + if (ifRow.dwType == MIB_IF_TYPE_TOKENRING) + astat->adapter_type = 0xff; + else + astat->adapter_type = 0xfe; /* for Ethernet */ + astat->max_sess_pkt_size = 0xffff; + astat->xmit_success = adapter->xmit_success; + astat->recv_success = adapter->recv_success; + } + ret = NRC_GOODRET; + } + else + ret = NetBTAstatRemote(adapter, ncb); + TRACE("returning 0x%02x\n", ret); + return ret; +} + +static UCHAR NetBTFindName(void *adapt, PNCB ncb) +{ + NetBTAdapter *adapter = (NetBTAdapter *)adapt; + UCHAR ret; + const NBNameCacheEntry *cacheEntry = NULL; + PFIND_NAME_HEADER foundName; + + TRACE("adapt %p, NCB %p\n", adapt, ncb); + + if (!adapter) return NRC_ENVNOTDEF; + if (!ncb) return NRC_INVADDRESS; + if (!ncb->ncb_buffer) return NRC_BADDR; + if (ncb->ncb_length < sizeof(FIND_NAME_HEADER)) return NRC_BUFLEN; + + foundName = (PFIND_NAME_HEADER)ncb->ncb_buffer; + memset(foundName, 0, sizeof(FIND_NAME_HEADER)); + + ret = NetBTInternalFindName(adapter, ncb, &cacheEntry); + if (ret == NRC_GOODRET) + { + if (cacheEntry) + { + DWORD spaceFor = min((ncb->ncb_length - sizeof(FIND_NAME_HEADER)) / + sizeof(FIND_NAME_BUFFER), cacheEntry->numAddresses); + DWORD ndx; + + for (ndx = 0; ndx < spaceFor; ndx++) + { + PFIND_NAME_BUFFER findNameBuffer; + + findNameBuffer = + (PFIND_NAME_BUFFER)((PUCHAR)foundName + + sizeof(FIND_NAME_HEADER) + foundName->node_count * + sizeof(FIND_NAME_BUFFER)); + memset(findNameBuffer->destination_addr, 0, 2); + memcpy(findNameBuffer->destination_addr + 2, + &adapter->ipr.dwAddr, sizeof(DWORD)); + memset(findNameBuffer->source_addr, 0, 2); + memcpy(findNameBuffer->source_addr + 2, + &cacheEntry->addresses[ndx], sizeof(DWORD)); + foundName->node_count++; + } + if (spaceFor < cacheEntry->numAddresses) + ret = NRC_BUFLEN; + } + else + ret = NRC_CMDTMO; + } + TRACE("returning 0x%02x\n", ret); + return ret; +} + +static UCHAR NetBTSessionReq(SOCKET fd, const UCHAR *calledName, + const UCHAR *callingName) +{ + UCHAR buffer[NBSS_HDRSIZE + MAX_DOMAIN_NAME_LEN * 2], ret; + int len = 0, r; + DWORD bytesSent, bytesReceived, recvFlags = 0; + WSABUF wsaBuf; + + buffer[0] = NBSS_REQ; + buffer[1] = 0; + + len += NetBTNameEncode(calledName, &buffer[NBSS_HDRSIZE]); + len += NetBTNameEncode(callingName, &buffer[NBSS_HDRSIZE + len]); + + NBR_ADDWORD(&buffer[2], len); + + wsaBuf.len = len + NBSS_HDRSIZE; + wsaBuf.buf = buffer; + + r = WSASend(fd, &wsaBuf, 1, &bytesSent, 0, NULL, NULL); + if(r < 0 || bytesSent < len + NBSS_HDRSIZE) + { + ERR("send failed\n"); + return NRC_SABORT; + } + + /* I've already set the recv timeout on this socket (if it supports it), so + * just block. Hopefully we'll always receive the session acknowledgement + * within one timeout. + */ + wsaBuf.len = NBSS_HDRSIZE + 1; + r = WSARecv(fd, &wsaBuf, 1, &bytesReceived, &recvFlags, NULL, NULL); + if (r < 0 || bytesReceived < NBSS_HDRSIZE) + ret = NRC_SABORT; + else if (buffer[0] == NBSS_NACK) + { + if (r == NBSS_HDRSIZE + 1) + { + switch (buffer[NBSS_HDRSIZE]) + { + case NBSS_ERR_INSUFFICIENT_RESOURCES: + ret = NRC_REMTFUL; + break; + default: + ret = NRC_NOCALL; + } + } + else + ret = NRC_NOCALL; + } + else if (buffer[0] == NBSS_RETARGET) + { + FIXME("Got a session retarget, can't deal\n"); + ret = NRC_NOCALL; + } + else if (buffer[0] == NBSS_ACK) + ret = NRC_GOODRET; + else + ret = NRC_SYSTEM; + + TRACE("returning 0x%02x\n", ret); + return ret; +} + +static UCHAR NetBTCall(void *adapt, PNCB ncb, void **sess) +{ + NetBTAdapter *adapter = (NetBTAdapter *)adapt; + UCHAR ret; + const NBNameCacheEntry *cacheEntry = NULL; + + TRACE("adapt %p, ncb %p\n", adapt, ncb); + + if (!adapter) return NRC_ENVNOTDEF; + if (!ncb) return NRC_INVADDRESS; + if (!sess) return NRC_BADDR; + + ret = NetBTInternalFindName(adapter, ncb, &cacheEntry); + if (ret == NRC_GOODRET) + { + if (cacheEntry && cacheEntry->numAddresses > 0) + { + SOCKET fd; + + fd = WSASocketA(PF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, + WSA_FLAG_OVERLAPPED); + if (fd != INVALID_SOCKET) + { + DWORD timeout; + struct sockaddr_in sin; + + if (ncb->ncb_rto > 0) + { + timeout = ncb->ncb_rto * 500; + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (PUCHAR)&timeout, + sizeof(timeout)); + } + if (ncb->ncb_rto > 0) + { + timeout = ncb->ncb_sto * 500; + setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (PUCHAR)&timeout, + sizeof(timeout)); + } + + memset(&sin, 0, sizeof(sin)); + memcpy(&sin.sin_addr, &cacheEntry->addresses[0], + sizeof(sin.sin_addr)); + sin.sin_family = AF_INET; + sin.sin_port = htons(PORT_NBSS); + /* FIXME: use nonblocking mode for the socket, check the + * cancel flag periodically + */ + if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) + == SOCKET_ERROR) + ret = NRC_CMDTMO; + else + { + static UCHAR fakedCalledName[] = "*SMBSERVER"; + const UCHAR *calledParty = cacheEntry->nbname[0] == '*' + ? fakedCalledName : cacheEntry->nbname; + + ret = NetBTSessionReq(fd, calledParty, ncb->ncb_name); + if (ret != NRC_GOODRET && calledParty[0] == '*') + { + FIXME("NBT session to \"*SMBSERVER\" refused,\n"); + FIXME("should try finding name using ASTAT\n"); + } + } + if (ret != NRC_GOODRET) + closesocket(fd); + else + { + NetBTSession *session = (NetBTSession *)HeapAlloc( + GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(NetBTSession)); + + if (session) + { + session->fd = fd; + InitializeCriticalSection(&session->cs); + *sess = session; + } + else + { + ret = NRC_OSRESNOTAV; + closesocket(fd); + } + } + } + else + ret = NRC_OSRESNOTAV; + } + else + ret = NRC_NAMERR; + } + TRACE("returning 0x%02x\n", ret); + return ret; +} + +/* Notice that I don't protect against multiple thread access to NetBTSend. + * This is because I don't update any data in the adapter, and I only make a + * single call to WSASend, which I assume to act atomically (not interleaving + * data from other threads). + * I don't lock, because I only depend on the fd being valid, and this won't be + * true until a session setup is completed. + */ +static UCHAR NetBTSend(void *adapt, void *sess, PNCB ncb) +{ + NetBTAdapter *adapter = (NetBTAdapter *)adapt; + NetBTSession *session = (NetBTSession *)sess; + UCHAR buffer[NBSS_HDRSIZE], ret; + int r; + WSABUF wsaBufs[2]; + DWORD bytesSent; + + TRACE("adapt %p, session %p, NCB %p\n", adapt, session, ncb); + + if (!adapter) return NRC_ENVNOTDEF; + if (!ncb) return NRC_INVADDRESS; + if (!ncb->ncb_buffer) return NRC_BADDR; + if (!session) return NRC_SNUMOUT; + if (session->fd == INVALID_SOCKET) return NRC_SNUMOUT; + + buffer[0] = NBSS_MSG; + buffer[1] = 0; + NBR_ADDWORD(&buffer[2], ncb->ncb_length); + + wsaBufs[0].len = NBSS_HDRSIZE; + wsaBufs[0].buf = buffer; + wsaBufs[1].len = ncb->ncb_length; + wsaBufs[1].buf = ncb->ncb_buffer; + + r = WSASend(session->fd, wsaBufs, sizeof(wsaBufs) / sizeof(wsaBufs[0]), + &bytesSent, 0, NULL, NULL); + if (r == SOCKET_ERROR) + { + NetBIOSHangupSession(ncb); + ret = NRC_SABORT; + } + else if (bytesSent < NBSS_HDRSIZE + ncb->ncb_length) + { + FIXME("Only sent %ld bytes (of %d), hanging up session\n", bytesSent, + NBSS_HDRSIZE + ncb->ncb_length); + NetBIOSHangupSession(ncb); + ret = NRC_SABORT; + } + else + { + ret = NRC_GOODRET; + adapter->xmit_success++; + } + TRACE("returning 0x%02x\n", ret); + return ret; +} + +static UCHAR NetBTRecv(void *adapt, void *sess, PNCB ncb) +{ + NetBTAdapter *adapter = (NetBTAdapter *)adapt; + NetBTSession *session = (NetBTSession *)sess; + UCHAR buffer[NBSS_HDRSIZE], ret; + int r; + WSABUF wsaBufs[2]; + DWORD bufferCount, bytesReceived, flags; + + TRACE("adapt %p, session %p, NCB %p\n", adapt, session, ncb); + + if (!adapter) return NRC_ENVNOTDEF; + if (!ncb) return NRC_BADDR; + if (!ncb->ncb_buffer) return NRC_BADDR; + if (!session) return NRC_SNUMOUT; + if (session->fd == INVALID_SOCKET) return NRC_SNUMOUT; + + EnterCriticalSection(&session->cs); + bufferCount = 0; + if (session->bytesPending == 0) + { + bufferCount++; + wsaBufs[0].len = NBSS_HDRSIZE; + wsaBufs[0].buf = buffer; + } + wsaBufs[bufferCount].len = ncb->ncb_length; + wsaBufs[bufferCount].buf = ncb->ncb_buffer; + bufferCount++; + + flags = 0; + /* FIXME: should poll a bit so I can check the cancel flag */ + r = WSARecv(session->fd, wsaBufs, bufferCount, &bytesReceived, &flags, + NULL, NULL); + if (r == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) + { + LeaveCriticalSection(&session->cs); + ERR("Receive error, WSAGetLastError() returns %d\n", WSAGetLastError()); + NetBIOSHangupSession(ncb); + ret = NRC_SABORT; + } + else if (NCB_CANCELLED(ncb)) + { + LeaveCriticalSection(&session->cs); + ret = NRC_CMDCAN; + } + else + { + if (bufferCount == 2) + { + if (buffer[0] == NBSS_KEEPALIVE) + { + LeaveCriticalSection(&session->cs); + FIXME("Oops, received a session keepalive and lost my place\n"); + /* need to read another session header until we get a session + * message header. */ + NetBIOSHangupSession(ncb); + ret = NRC_SABORT; + } + else if (buffer[0] != NBSS_MSG) + { + LeaveCriticalSection(&session->cs); + FIXME("Received unexpected session msg type %d\n", buffer[0]); + NetBIOSHangupSession(ncb); + ret = NRC_SABORT; + } + else + { + if (buffer[1] & NBSS_EXTENSION) + { + LeaveCriticalSection(&session->cs); + FIXME("Received a message that's too long for my taste\n"); + NetBIOSHangupSession(ncb); + ret = NRC_SABORT; + } + else + { + session->bytesPending = NBSS_HDRSIZE + + NBR_GETWORD(&buffer[2]) - bytesReceived; + ncb->ncb_length = bytesReceived - NBSS_HDRSIZE; + LeaveCriticalSection(&session->cs); + } + } + } + else + { + if (bytesReceived < session->bytesPending) + session->bytesPending -= bytesReceived; + else + session->bytesPending = 0; + LeaveCriticalSection(&session->cs); + ncb->ncb_length = bytesReceived; + } + if (session->bytesPending > 0) + ret = NRC_INCOMP; + else + { + ret = NRC_GOODRET; + adapter->recv_success++; + } + } + TRACE("returning 0x%02x\n", ret); + return ret; +} + +static UCHAR NetBTHangup(void *adapt, void *sess) +{ + NetBTSession *session = (NetBTSession *)sess; + + TRACE("adapt %p, session %p\n", adapt, session); + + if (!session) return NRC_SNUMOUT; + + /* I don't lock the session, because NetBTRecv knows not to decrement + * past 0, so if a receive completes after this it should still deal. + */ + closesocket(session->fd); + session->fd = INVALID_SOCKET; + session->bytesPending = 0; + DeleteCriticalSection(&session->cs); + HeapFree(GetProcessHeap(), 0, session); + + return NRC_GOODRET; +} + +static void NetBTCleanupAdapter(void *adapt) +{ + TRACE("adapt %p\n", adapt); + if (adapt) + { + NetBTAdapter *adapter = (NetBTAdapter *)adapt; + + if (adapter->nameCache) + NBNameCacheDestroy(adapter->nameCache); + HeapFree(GetProcessHeap(), 0, adapt); + } +} + +static void NetBTCleanup(void) +{ + TRACE("\n"); + if (gNameCache) + { + NBNameCacheDestroy(gNameCache); + gNameCache = NULL; + } +} + +static UCHAR NetBTRegisterAdapter(PMIB_IPADDRROW ipRow) +{ + UCHAR ret; + NetBTAdapter *adapter; + + if (!ipRow) return NRC_BADDR; + + adapter = (NetBTAdapter *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(NetBTAdapter)); + if (adapter) + { + memcpy(&adapter->ipr, ipRow, sizeof(MIB_IPADDRROW)); + if (!NetBIOSRegisterAdapter(gTransportID, ipRow->dwIndex, adapter)) + { + NetBTCleanupAdapter(adapter); + ret = NRC_SYSTEM; + } + else + ret = NRC_GOODRET; + } + else + ret = NRC_OSRESNOTAV; + return ret; +} + +/* Callback for NetBIOS adapter enumeration. Assumes closure is a pointer to + * a MIB_IPADDRTABLE containing all the IP adapters needed to be added to the + * NetBIOS adapter table. For each callback, checks if the passed-in adapt + * has an entry in the table; if so, this adapter was enumerated previously, + * and it's enabled. As a flag, the table's dwAddr entry is changed to + * INADDR_LOOPBACK, since this is an invalid address for a NetBT adapter. + * The NetBTEnum function will add any remaining adapters from the + * MIB_IPADDRTABLE to the NetBIOS adapter table. + */ +static BOOL NetBTEnumCallback(UCHAR totalLANAs, UCHAR lanaIndex, + ULONG transport, const NetBIOSAdapterImpl *data, void *closure) +{ + BOOL ret; + PMIB_IPADDRTABLE table = (PMIB_IPADDRTABLE)closure; + + if (table && data) + { + DWORD ndx; + + ret = FALSE; + for (ndx = 0; !ret && ndx < table->dwNumEntries; ndx++) + { + const NetBTAdapter *adapter = (const NetBTAdapter *)data->data; + + if (table->table[ndx].dwIndex == adapter->ipr.dwIndex) + { + NetBIOSEnableAdapter(data->lana); + table->table[ndx].dwAddr = INADDR_LOOPBACK; + ret = TRUE; + } + } + } + else + ret = FALSE; + return ret; +} + +/* Enumerates adapters by: + * - retrieving the IP address table for the local machine + * - eliminating loopback addresses from the table + * - eliminating redundant addresses, that is, multiple addresses on the same + * subnet + * Calls NetBIOSEnumAdapters, passing the resulting table as the callback + * data. The callback reenables each adapter that's already in the NetBIOS + * table. After NetBIOSEnumAdapters returns, this function adds any remaining + * adapters to the NetBIOS table. + */ +static UCHAR NetBTEnum(void) +{ + UCHAR ret; + DWORD size = 0; + + TRACE("\n"); + + if (GetIpAddrTable(NULL, &size, FALSE) == ERROR_INSUFFICIENT_BUFFER) + { + PMIB_IPADDRTABLE ipAddrs, coalesceTable = NULL; + DWORD numIPAddrs = (size - sizeof(MIB_IPADDRTABLE)) / + sizeof(MIB_IPADDRROW) + 1; + + ipAddrs = (PMIB_IPADDRTABLE)HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, size); + if (ipAddrs) + coalesceTable = (PMIB_IPADDRTABLE)HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, sizeof(MIB_IPADDRTABLE) + + (min(numIPAddrs, MAX_LANA + 1) - 1) * sizeof(MIB_IPADDRROW)); + if (ipAddrs && coalesceTable) + { + if (GetIpAddrTable(ipAddrs, &size, FALSE) == ERROR_SUCCESS) + { + DWORD ndx; + + for (ndx = 0; ndx < ipAddrs->dwNumEntries; ndx++) + { + if ((ipAddrs->table[ndx].dwAddr & + ipAddrs->table[ndx].dwMask) != + htonl((INADDR_LOOPBACK & IN_CLASSA_NET))) + { + BOOL newNetwork = TRUE; + DWORD innerIndex; + + /* make sure we don't have more than one entry + * for a subnet */ + for (innerIndex = 0; newNetwork && + innerIndex < coalesceTable->dwNumEntries; innerIndex++) + if ((ipAddrs->table[ndx].dwAddr & + ipAddrs->table[ndx].dwMask) == + (coalesceTable->table[innerIndex].dwAddr + & coalesceTable->table[innerIndex].dwMask)) + newNetwork = FALSE; + + if (newNetwork) + memcpy(&coalesceTable->table[ + coalesceTable->dwNumEntries++], + &ipAddrs->table[ndx], sizeof(MIB_IPADDRROW)); + } + } + + NetBIOSEnumAdapters(gTransportID, NetBTEnumCallback, + coalesceTable); + ret = NRC_GOODRET; + for (ndx = 0; ret == NRC_GOODRET && + ndx < coalesceTable->dwNumEntries; ndx++) + if (coalesceTable->table[ndx].dwAddr != INADDR_LOOPBACK) + ret = NetBTRegisterAdapter(&coalesceTable->table[ndx]); + } + else + ret = NRC_SYSTEM; + HeapFree(GetProcessHeap(), 0, ipAddrs); + HeapFree(GetProcessHeap(), 0, coalesceTable); + } + else + ret = NRC_OSRESNOTAV; + } + else + ret = NRC_SYSTEM; + TRACE("returning 0x%02x\n", ret); + return ret; +} + +/* Initializes global variables and registers the NetBT transport */ +void NetBTInit(void) +{ + HKEY hKey; + NetBIOSTransport transport; + LONG ret; + + TRACE("\n"); + + gEnableDNS = TRUE; + gBCastQueries = BCAST_QUERIES; + gBCastQueryTimeout = BCAST_QUERY_TIMEOUT; + gWINSQueries = WINS_QUERIES; + gWINSQueryTimeout = WINS_QUERY_TIMEOUT; + gNumWINSServers = 0; + memset(gWINSServers, 0, sizeof(gWINSServers)); + gScopeID[0] = '\0'; + gCacheTimeout = CACHE_TIMEOUT; + + /* Try to open the Win9x NetBT configuration key */ + ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP", 0, KEY_READ, &hKey); + /* If that fails, try the WinNT NetBT configuration key */ + if (ret != ERROR_SUCCESS) + ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Services\\NetBT\\Parameters", 0, + KEY_READ, &hKey); + if (ret == ERROR_SUCCESS) + { + DWORD dword, size; + + size = sizeof(dword); + if (RegQueryValueExA(hKey, "EnableDNS", NULL, NULL, + (LPBYTE)&dword, &size) == ERROR_SUCCESS) + gEnableDNS = dword; + size = sizeof(dword); + if (RegQueryValueExA(hKey, "BcastNameQueryCount", NULL, NULL, + (LPBYTE)&dword, &size) == ERROR_SUCCESS && dword >= MIN_QUERIES + && dword <= MAX_QUERIES) + gBCastQueries = dword; + size = sizeof(dword); + if (RegQueryValueExA(hKey, "BcastNameQueryTimeout", NULL, NULL, + (LPBYTE)&dword, &size) == ERROR_SUCCESS && dword >= MIN_QUERY_TIMEOUT + && dword <= MAX_QUERY_TIMEOUT) + gBCastQueryTimeout = dword; + size = sizeof(dword); + if (RegQueryValueExA(hKey, "NameSrvQueryCount", NULL, NULL, + (LPBYTE)&dword, &size) == ERROR_SUCCESS && dword >= MIN_QUERIES + && dword <= MAX_QUERIES) + gWINSQueries = dword; + size = sizeof(dword); + if (RegQueryValueExA(hKey, "NameSrvQueryTimeout", NULL, NULL, + (LPBYTE)&dword, &size) == ERROR_SUCCESS && dword >= MIN_QUERY_TIMEOUT + && dword <= MAX_QUERY_TIMEOUT) + gWINSQueryTimeout = dword; + size = MAX_DOMAIN_NAME_LEN - 1; + if (RegQueryValueExA(hKey, "ScopeID", NULL, NULL, gScopeID + 1, &size) + == ERROR_SUCCESS) + { + /* convert into L2-encoded version, suitable for use by + NetBTNameEncode */ + char *ptr, *lenPtr; + + for (ptr = gScopeID + 1; *ptr && + ptr - gScopeID < MAX_DOMAIN_NAME_LEN; ) + { + for (lenPtr = ptr - 1, *lenPtr = 0; *ptr && *ptr != '.' && + ptr - gScopeID < MAX_DOMAIN_NAME_LEN; ptr++) + *lenPtr += 1; + ptr++; + } + } + if (RegQueryValueExA(hKey, "CacheTimeout", NULL, NULL, + (LPBYTE)&dword, &size) == ERROR_SUCCESS && dword >= MIN_CACHE_TIMEOUT) + gCacheTimeout = dword; + RegCloseKey(hKey); + } + /* WINE-specific NetBT registry settings. Because our adapter naming is + * different than MS', we can't do per-adapter WINS configuration in the + * same place. Just do a global WINS configuration instead. + */ + if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, + "Software\\Wine\\Wine\\Config\\Network", 0, KEY_READ, &hKey) + == ERROR_SUCCESS) + { + static const char *nsValueNames[] = { "WinsServer", "BackupWinsServer" }; + char nsString[16]; + DWORD size, ndx; + + for (ndx = 0; ndx < sizeof(nsValueNames) / sizeof(nsValueNames[0]); + ndx++) + { + size = sizeof(nsString) / sizeof(char); + if (RegQueryValueExA(hKey, nsValueNames[ndx], NULL, NULL, + (LPBYTE)nsString, &size) == ERROR_SUCCESS) + { + unsigned long addr = inet_addr(nsString); + + if (addr != INADDR_NONE && gNumWINSServers < MAX_WINS_SERVERS) + gWINSServers[gNumWINSServers++] = addr; + } + } + RegCloseKey(hKey); + } + + transport.enumerate = NetBTEnum; + transport.astat = NetBTAstat; + transport.findName = NetBTFindName; + transport.call = NetBTCall; + transport.send = NetBTSend; + transport.recv = NetBTRecv; + transport.hangup = NetBTHangup; + transport.cleanupAdapter = NetBTCleanupAdapter; + transport.cleanup = NetBTCleanup; + memcpy(&gTransportID, TRANSPORT_NBT, sizeof(ULONG)); + NetBIOSRegisterTransport(gTransportID, &transport); +} diff --git a/reactos/lib/netapi32/netapi32.c b/reactos/lib/netapi32/netapi32.c new file mode 100644 index 00000000000..a249a01def7 --- /dev/null +++ b/reactos/lib/netapi32/netapi32.c @@ -0,0 +1,79 @@ +/* Copyright 2001 Mike McCormack + * Copyright 2003 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "wine/debug.h" +#include "netbios.h" + +WINE_DEFAULT_DEBUG_CHANNEL(netbios); + +HMODULE NETAPI32_hModule = 0; + +BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + TRACE("%p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved); + + switch (fdwReason) { + case DLL_PROCESS_ATTACH: + { + DisableThreadLibraryCalls(hinstDLL); + NETAPI32_hModule = hinstDLL; + NetBIOSInit(); + NetBTInit(); + break; + } + case DLL_PROCESS_DETACH: + { + NetBIOSShutdown(); + break; + } + } + + return TRUE; +} + +NET_API_STATUS WINAPI NetServerEnum( + LPCWSTR servername, + DWORD level, + LPBYTE* bufptr, + DWORD prefmaxlen, + LPDWORD entriesread, + LPDWORD totalentries, + DWORD servertype, + LPCWSTR domain, + LPDWORD resume_handle +) +{ + FIXME("Stub (%p, %ld %p %ld %p %p %ld %s %p)\n",servername, level, bufptr, + prefmaxlen, entriesread, totalentries, servertype, debugstr_w(domain), resume_handle); + + return ERROR_NO_BROWSER_SERVERS_FOUND; +} + + +/************************************************************ + * NetStatisticsGet (NETAPI32.@) + */ +NET_API_STATUS WINAPI NetStatisticsGet(LPWSTR server, LPWSTR service, + DWORD level, DWORD options, + PBYTE *bufptr) +{ + TRACE("(%p, %p, %ld, %ld, %p)\n", server, service, level, options, bufptr); + return NERR_InternalError; +} diff --git a/reactos/lib/netapi32/netapi32.rc b/reactos/lib/netapi32/netapi32.rc new file mode 100644 index 00000000000..e218c3c1910 --- /dev/null +++ b/reactos/lib/netapi32/netapi32.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "WINE IMM32 API Client DLL\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "imm32\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "imm32.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/reactos/lib/netapi32/netapi32.spec b/reactos/lib/netapi32/netapi32.spec new file mode 100644 index 00000000000..513019ac5d2 --- /dev/null +++ b/reactos/lib/netapi32/netapi32.spec @@ -0,0 +1,274 @@ +@ stub I_BrowserDebugCall +@ stub I_BrowserDebugTrace +@ stdcall I_BrowserQueryEmulatedDomains(wstr ptr ptr) +@ stub I_BrowserQueryOtherDomains +@ stub I_BrowserQueryStatistics +@ stub I_BrowserResetNetlogonState +@ stub I_BrowserResetStatistics +@ stub I_BrowserServerEnum +@ stdcall I_BrowserSetNetlogonState(wstr wstr wstr long) +@ stub I_NetAccountDeltas +@ stub I_NetAccountSync +@ stub I_NetDatabaseDeltas +@ stub I_NetDatabaseRedo +@ stub I_NetDatabaseSync +@ stub I_NetDatabaseSync2 +@ stub I_NetDfsCreateExitPoint +@ stub I_NetDfsCreateLocalPartition +@ stub I_NetDfsDeleteExitPoint +@ stub I_NetDfsDeleteLocalPartition +@ stub I_NetDfsFixLocalVolume +@ stub I_NetDfsGetVersion +@ stub I_NetDfsIsThisADomainName +@ stub I_NetDfsModifyPrefix +@ stub I_NetDfsSetLocalVolumeState +@ stub I_NetDfsSetServerInfo +@ stub I_NetGetDCList +@ stub I_NetListCanonicalize +@ stub I_NetListTraverse +@ stub I_NetLogonControl +@ stub I_NetLogonControl2 +@ stub I_NetLogonSamLogoff +@ stub I_NetLogonSamLogon +@ stub I_NetLogonUasLogoff +@ stub I_NetLogonUasLogon +@ stub I_NetNameCanonicalize +@ stub I_NetNameCompare +@ stub I_NetNameValidate +@ stub I_NetPathCanonicalize +@ stub I_NetPathCompare +@ stub I_NetPathType +@ stub I_NetServerAuthenticate +@ stub I_NetServerAuthenticate2 +@ stub I_NetServerPasswordSet +@ stub I_NetServerReqChallenge +@ stub I_NetServerSetServiceBits +@ stub I_NetServerSetServiceBitsEx +@ stub NetAlertRaise +@ stub NetAlertRaiseEx +@ stdcall NetApiBufferAllocate(long ptr) +@ stdcall NetApiBufferFree(ptr) +@ stdcall NetApiBufferReallocate(ptr long ptr) +@ stdcall NetApiBufferSize(ptr ptr) +@ stub NetAuditClear +@ stub NetAuditRead +@ stub NetAuditWrite +@ stub NetBrowserStatisticsGet +@ stub NetConfigGet +@ stub NetConfigGetAll +@ stub NetConfigSet +@ stub NetConnectionEnum +@ stub NetDfsAdd +@ stub NetDfsEnum +@ stub NetDfsGetInfo +@ stub NetDfsManagerGetConfigInfo +@ stub NetDfsMove +@ stub NetDfsRemove +@ stub NetDfsRename +@ stub NetDfsSetInfo +@ stub NetEnumerateTrustedDomains +@ stub NetErrorLogClear +@ stub NetErrorLogRead +@ stub NetErrorLogWrite +@ stub NetFileClose +@ stub NetFileEnum +@ stub NetFileGetInfo +@ stub NetGetAnyDCName +@ stdcall NetGetDCName(wstr wstr ptr) +@ stub NetGetDisplayInformationIndex +@ stub NetGroupAdd +@ stub NetGroupAddUser +@ stub NetGroupDel +@ stub NetGroupDelUser +@ stub NetGroupEnum +@ stub NetGroupGetInfo +@ stub NetGroupGetUsers +@ stub NetGroupSetInfo +@ stub NetGroupSetUsers +@ stdcall NetLocalGroupAdd(wstr long ptr ptr) +@ stub NetLocalGroupAddMember +@ stub NetLocalGroupAddMembers +@ stub NetLocalGroupDel +@ stub NetLocalGroupDelMember +@ stub NetLocalGroupDelMembers +@ stub NetLocalGroupEnum +@ stub NetLocalGroupGetInfo +@ stub NetLocalGroupGetMembers +@ stub NetLocalGroupSetInfo +@ stdcall NetLocalGroupSetMembers(wstr wstr long ptr ptr) +@ stub NetMessageBufferSend +@ stub NetMessageNameAdd +@ stub NetMessageNameDel +@ stub NetMessageNameEnum +@ stub NetMessageNameGetInfo +@ stdcall NetQueryDisplayInformation(wstr long long long long ptr ptr) +@ stub NetRemoteComputerSupports +@ stub NetRemoteTOD +@ stub NetReplExportDirAdd +@ stub NetReplExportDirDel +@ stub NetReplExportDirEnum +@ stub NetReplExportDirGetInfo +@ stub NetReplExportDirLock +@ stub NetReplExportDirSetInfo +@ stub NetReplExportDirUnlock +@ stub NetReplGetInfo +@ stub NetReplImportDirAdd +@ stub NetReplImportDirDel +@ stub NetReplImportDirEnum +@ stub NetReplImportDirGetInfo +@ stub NetReplImportDirLock +@ stub NetReplImportDirUnlock +@ stub NetReplSetInfo +@ stub NetRplAdapterAdd +@ stub NetRplAdapterDel +@ stub NetRplAdapterEnum +@ stub NetRplBootAdd +@ stub NetRplBootDel +@ stub NetRplBootEnum +@ stub NetRplClose +@ stub NetRplConfigAdd +@ stub NetRplConfigDel +@ stub NetRplConfigEnum +@ stub NetRplGetInfo +@ stub NetRplOpen +@ stub NetRplProfileAdd +@ stub NetRplProfileClone +@ stub NetRplProfileDel +@ stub NetRplProfileEnum +@ stub NetRplProfileGetInfo +@ stub NetRplProfileSetInfo +@ stub NetRplSetInfo +@ stub NetRplSetSecurity +@ stub NetRplVendorAdd +@ stub NetRplVendorDel +@ stub NetRplVendorEnum +@ stub NetRplWkstaAdd +@ stub NetRplWkstaClone +@ stub NetRplWkstaDel +@ stub NetRplWkstaEnum +@ stub NetRplWkstaGetInfo +@ stub NetRplWkstaSetInfo +@ stub NetScheduleJobAdd +@ stub NetScheduleJobDel +@ stub NetScheduleJobEnum +@ stub NetScheduleJobGetInfo +@ stub NetServerComputerNameAdd +@ stub NetServerComputerNameDel +@ stub NetServerDiskEnum +@ stdcall NetServerEnum(wstr long ptr long ptr ptr long wstr ptr) +@ stub NetServerEnumEx +@ stub NetServerGetInfo +@ stub NetServerSetInfo +@ stub NetServerTransportAdd +@ stub NetServerTransportAddEx +@ stub NetServerTransportDel +@ stub NetServerTransportEnum +@ stub NetServiceControl +@ stub NetServiceEnum +@ stub NetServiceGetInfo +@ stub NetServiceInstall +@ stub NetSessionDel +@ stub NetSessionEnum +@ stub NetSessionGetInfo +@ stub NetShareAdd +@ stub NetShareCheck +@ stub NetShareDel +@ stub NetShareDelSticky +@ stdcall NetShareEnum(wstr long ptr long ptr ptr ptr) +@ stub NetShareEnumSticky +@ stub NetShareGetInfo +@ stub NetShareSetInfo +@ stdcall NetStatisticsGet(wstr wstr long long ptr) +@ stub NetUseAdd +@ stub NetUseDel +@ stub NetUseEnum +@ stub NetUseGetInfo +@ stub NetUserAdd +@ stub NetUserChangePassword +@ stub NetUserDel +@ stdcall NetUserEnum(wstr long long ptr long ptr ptr ptr) +@ stub NetUserGetGroups +@ stdcall NetUserGetInfo(wstr wstr long ptr) +@ stub NetUserGetLocalGroups +@ stdcall NetUserModalsGet(wstr long ptr) +@ stub NetUserModalsSet +@ stub NetUserSetGroups +@ stub NetUserSetInfo +@ stdcall NetWkstaGetInfo(wstr long ptr) +@ stub NetWkstaSetInfo +@ stub NetWkstaTransportAdd +@ stub NetWkstaTransportDel +@ stdcall NetWkstaTransportEnum (wstr long ptr long ptr ptr ptr) +@ stub NetWkstaUserEnum +@ stdcall NetWkstaUserGetInfo(wstr long ptr) +@ stub NetWkstaUserSetInfo +@ stdcall NetapipBufferAllocate(long ptr) NetApiBufferAllocate +@ stdcall Netbios(ptr) +@ stub NetpAccessCheck +@ stub NetpAccessCheckAndAudit +@ stub NetpAllocConfigName +@ stub NetpAllocStrFromStr +@ stub NetpAllocStrFromWStr +@ stub NetpAllocTStrFromString +@ stub NetpAllocWStrFromStr +@ stub NetpAllocWStrFromWStr +@ stub NetpApiStatusToNtStatus +@ stub NetpAssertFailed +@ stub NetpCloseConfigData +@ stub NetpCopyStringToBuffer +@ stub NetpCreateSecurityObject +@ stub NetpDbgDisplayServerInfo +@ stub NetpDbgPrint +@ stdcall NetpDeleteSecurityObject(long) ntdll.RtlDeleteSecurityObject +@ stdcall NetpGetComputerName(ptr) +@ stub NetpGetConfigBool +@ stub NetpGetConfigDword +@ stub NetpGetConfigTStrArray +@ stub NetpGetConfigValue +@ stub NetpGetDomainName +@ stub NetpGetFileSecurity +@ stub NetpGetPrivilege +@ stub NetpHexDump +@ stdcall NetpInitOemString(ptr str) ntdll.RtlInitAnsiString +@ stub NetpIsRemote +@ stub NetpIsUncComputerNameValid +@ stub NetpLocalTimeZoneOffset +@ stub NetpLogonPutUnicodeString +@ stub NetpNetBiosAddName +@ stub NetpNetBiosCall +@ stub NetpNetBiosDelName +@ stub NetpNetBiosGetAdapterNumbers +@ stub NetpNetBiosHangup +@ stub NetpNetBiosReceive +@ stub NetpNetBiosReset +@ stub NetpNetBiosSend +@ stub NetpNetBiosStatusToApiStatus +@ stub NetpNtStatusToApiStatus +@ stub NetpOpenConfigData +@ stub NetpPackString +@ stub NetpReleasePrivilege +@ stub NetpSetConfigBool +@ stub NetpSetConfigDword +@ stub NetpSetConfigTStrArray +@ stub NetpSetFileSecurity +@ stub NetpSmbCheck +@ stub NetpStringToNetBiosName +@ stub NetpTStrArrayEntryCount +@ stub NetpwNameCanonicalize +@ stub NetpwNameCompare +@ stub NetpwNameValidate +@ stub NetpwPathCanonicalize +@ stub NetpwPathCompare +@ stub NetpwPathType +@ stub NlBindingAddServerToCache +@ stub NlBindingRemoveServerFromCache +@ stub NlBindingSetAuthInfo +@ stub RxNetAccessAdd +@ stub RxNetAccessDel +@ stub RxNetAccessEnum +@ stub RxNetAccessGetInfo +@ stub RxNetAccessGetUserPerms +@ stub RxNetAccessSetInfo +@ stub RxNetServerEnum +@ stub RxNetUserPasswordSet +@ stub RxRemoteApi diff --git a/reactos/lib/netapi32/netapi32_misc.h b/reactos/lib/netapi32/netapi32_misc.h new file mode 100644 index 00000000000..92cbc26d07a --- /dev/null +++ b/reactos/lib/netapi32/netapi32_misc.h @@ -0,0 +1,35 @@ +/* + * Copyright 2002 Andriy Palamarchuk + * + * netapi32 internal functions. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, writ +e to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WINE_NETAPI32_MISC_H +#define __WINE_NETAPI32_MISC_H + +extern BOOL NETAPI_IsLocalComputer(LPCWSTR ServerName); + +#define NETAPI_ForceLocalComputer(ServerName, FailureCode) \ + if (!NETAPI_IsLocalComputer(ServerName)) \ + { \ + FIXME("Action Implemented for local computer only. " \ + "Requested for server %s\n", debugstr_w(ServerName)); \ + return FailureCode; \ + } + +#endif diff --git a/reactos/lib/netapi32/netbios.c b/reactos/lib/netapi32/netbios.c new file mode 100644 index 00000000000..b0793bf27e0 --- /dev/null +++ b/reactos/lib/netapi32/netbios.c @@ -0,0 +1,846 @@ +/* Copyright (c) 2003 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "config.h" +#include "wine/debug.h" +#include "nbcmdqueue.h" +#include "netbios.h" + +WINE_DEFAULT_DEBUG_CHANNEL(netbios); + +/* This file provides a NetBIOS emulator that implements the NetBIOS interface, + * including thread safety and asynchronous call support. The protocol + * implementation is separate, with blocking (synchronous) functions. + */ + +#define ADAPTERS_INCR 8 +#define DEFAULT_NUM_SESSIONS 16 + +typedef struct _NetBIOSTransportTableEntry +{ + ULONG id; + NetBIOSTransport transport; +} NetBIOSTransportTableEntry; + +typedef struct _NetBIOSSession +{ + BOOL inUse; + UCHAR state; + UCHAR local_name[NCBNAMSZ]; + UCHAR remote_name[NCBNAMSZ]; + void *data; +} NetBIOSSession; + +/* This struct needs a little explanation, unfortunately. enabled is only + * used by nbInternalEnum (see). If transport_id is not 0 and transport + * is not NULL, the adapter is considered valid. (transport is a pointer to + * an entry in a NetBIOSTransportTableEntry.) data has data for the callers of + * NetBIOSEnumAdapters to be able to see. The lana is repeated there, even + * though I don't use it internally--it's for transports to use reenabling + * adapters using NetBIOSEnableAdapter. + */ +typedef struct _NetBIOSAdapter +{ + BOOL enabled; + BOOL shuttingDown; + ULONG resetting; + ULONG transport_id; + NetBIOSTransport *transport; + NetBIOSAdapterImpl impl; + struct NBCmdQueue *cmdQueue; + CRITICAL_SECTION cs; + DWORD sessionsLen; + NetBIOSSession *sessions; +} NetBIOSAdapter; + +typedef struct _NetBIOSAdapterTable { + CRITICAL_SECTION cs; + BOOL enumerated; + BOOL enumerating; + UCHAR tableSize; + NetBIOSAdapter *table; +} NetBIOSAdapterTable; + +/* Just enough space for NBT right now */ +static NetBIOSTransportTableEntry gTransports[1]; +static UCHAR gNumTransports = 0; +static NetBIOSAdapterTable gNBTable; + +static UCHAR nbResizeAdapterTable(UCHAR newSize) +{ + UCHAR ret; + + if (gNBTable.table) + gNBTable.table = (NetBIOSAdapter *)HeapReAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, gNBTable.table, + newSize * sizeof(NetBIOSAdapter)); + else + gNBTable.table = (NetBIOSAdapter *)HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, newSize * sizeof(NetBIOSAdapter)); + if (gNBTable.table) + { + gNBTable.tableSize = newSize; + ret = NRC_GOODRET; + } + else + ret = NRC_OSRESNOTAV; + return ret; +} + +void NetBIOSInit(void) +{ + memset(&gNBTable, 0, sizeof(gNBTable)); + InitializeCriticalSection(&gNBTable.cs); +} + +void NetBIOSShutdown(void) +{ + UCHAR i; + + EnterCriticalSection(&gNBTable.cs); + for (i = 0; i < gNBTable.tableSize; i++) + { + if (gNBTable.table[i].transport && + gNBTable.table[i].transport->cleanupAdapter) + gNBTable.table[i].transport->cleanupAdapter( + gNBTable.table[i].impl.data); + } + for (i = 0; i < gNumTransports; i++) + if (gTransports[i].transport.cleanup) + gTransports[i].transport.cleanup(); + LeaveCriticalSection(&gNBTable.cs); + DeleteCriticalSection(&gNBTable.cs); + HeapFree(GetProcessHeap(), 0, gNBTable.table); +} + +BOOL NetBIOSRegisterTransport(ULONG id, NetBIOSTransport *transport) +{ + BOOL ret; + + TRACE(": transport 0x%08lx, p %p\n", id, transport); + if (!transport) + ret = FALSE; + else if (gNumTransports >= sizeof(gTransports) / sizeof(gTransports[0])) + { + FIXME("You tried to add %d transports, but I only have space for %d\n", + gNumTransports + 1, sizeof(gTransports) / sizeof(gTransports[0])); + ret = FALSE; + } + else + { + UCHAR i; + + ret = FALSE; + for (i = 0; !ret && i < gNumTransports; i++) + { + if (gTransports[i].id == id) + { + WARN("Replacing NetBIOS transport ID %ld\n", id); + memcpy(&gTransports[i].transport, transport, + sizeof(NetBIOSTransport)); + ret = TRUE; + } + } + if (!ret) + { + gTransports[gNumTransports].id = id; + memcpy(&gTransports[gNumTransports].transport, transport, + sizeof(NetBIOSTransport)); + gNumTransports++; + ret = TRUE; + } + } + TRACE("returning %d\n", ret); + return ret; +} + +/* In this, I acquire the table lock to make sure no one else is modifying it. + * This is _probably_ overkill since it should only be called during the + * context of a NetBIOSEnum call, but just to be safe.. + */ +BOOL NetBIOSRegisterAdapter(ULONG transport, DWORD ifIndex, void *data) +{ + BOOL ret; + UCHAR i; + + TRACE(": transport 0x%08lx, ifIndex 0x%08lx, data %p\n", transport, ifIndex, + data); + for (i = 0; i < gNumTransports && gTransports[i].id != transport; i++) + ; + if (gTransports[i].id == transport) + { + NetBIOSTransport *transportPtr = &gTransports[i].transport; + + TRACE(": found transport %p for id 0x%08lx\n", transportPtr, transport); + + EnterCriticalSection(&gNBTable.cs); + ret = FALSE; + for (i = 0; i < gNBTable.tableSize && + gNBTable.table[i].transport != 0; i++) + ; + if (i == gNBTable.tableSize && gNBTable.tableSize < MAX_LANA + 1) + { + UCHAR newSize; + + if (gNBTable.tableSize < (MAX_LANA + 1) - ADAPTERS_INCR) + newSize = gNBTable.tableSize + ADAPTERS_INCR; + else + newSize = MAX_LANA + 1; + nbResizeAdapterTable(newSize); + } + if (i < gNBTable.tableSize && gNBTable.table[i].transport == 0) + { + TRACE(": registering as LANA %d\n", i); + gNBTable.table[i].transport_id = transport; + gNBTable.table[i].transport = transportPtr; + gNBTable.table[i].impl.lana = i; + gNBTable.table[i].impl.ifIndex = ifIndex; + gNBTable.table[i].impl.data = data; + gNBTable.table[i].cmdQueue = NBCmdQueueCreate(GetProcessHeap()); + InitializeCriticalSection(&gNBTable.table[i].cs); + gNBTable.table[i].enabled = TRUE; + ret = TRUE; + } + LeaveCriticalSection(&gNBTable.cs); + } + else + ret = FALSE; + TRACE("returning %d\n", ret); + return ret; +} + +/* In this, I acquire the table lock to make sure no one else is modifying it. + * This is _probably_ overkill since it should only be called during the + * context of a NetBIOSEnum call, but just to be safe.. + */ +void NetBIOSEnableAdapter(UCHAR lana) +{ + TRACE(": %d\n", lana); + if (lana < gNBTable.tableSize) + { + EnterCriticalSection(&gNBTable.cs); + if (gNBTable.table[lana].transport != 0) + gNBTable.table[lana].enabled = TRUE; + LeaveCriticalSection(&gNBTable.cs); + } +} + +static void nbShutdownAdapter(NetBIOSAdapter *adapter) +{ + if (adapter) + { + adapter->shuttingDown = TRUE; + NBCmdQueueCancelAll(adapter->cmdQueue); + if (adapter->transport->cleanupAdapter) + adapter->transport->cleanupAdapter(adapter->impl.data); + NBCmdQueueDestroy(adapter->cmdQueue); + DeleteCriticalSection(&adapter->cs); + memset(adapter, 0, sizeof(NetBIOSAdapter)); + } +} + +static void nbInternalEnum(void) +{ + UCHAR i; + + EnterCriticalSection(&gNBTable.cs); + TRACE("before mark\n"); + /* mark: */ + for (i = 0; i < gNBTable.tableSize; i++) + if (gNBTable.table[i].enabled && gNBTable.table[i].transport != 0) + gNBTable.table[i].enabled = FALSE; + + TRACE("marked, before store, %d transports\n", gNumTransports); + /* store adapters: */ + for (i = 0; i < gNumTransports; i++) + if (gTransports[i].transport.enumerate) + gTransports[i].transport.enumerate(); + + TRACE("before sweep\n"); + /* sweep: */ + for (i = 0; i < gNBTable.tableSize; i++) + if (!gNBTable.table[i].enabled && gNBTable.table[i].transport != 0) + nbShutdownAdapter(&gNBTable.table[i]); + gNBTable.enumerated = TRUE; + LeaveCriticalSection(&gNBTable.cs); +} + +UCHAR NetBIOSNumAdapters(void) +{ + UCHAR ret, i; + + if (!gNBTable.enumerated) + nbInternalEnum(); + for (i = 0, ret = 0; i < gNBTable.tableSize; i++) + if (gNBTable.table[i].transport != 0) + ret++; + return ret; +} + +void NetBIOSEnumAdapters(ULONG transport, NetBIOSEnumAdaptersCallback cb, + void *closure) +{ + TRACE("transport 0x%08lx, callback %p, closure %p\n", transport, cb, + closure); + if (cb) + { + BOOL enumAll = memcmp(&transport, ALL_TRANSPORTS, sizeof(ULONG)) == 0; + UCHAR i, numLANAs = 0; + + EnterCriticalSection(&gNBTable.cs); + if (!gNBTable.enumerating) + { + gNBTable.enumerating = TRUE; + nbInternalEnum(); + gNBTable.enumerating = FALSE; + } + for (i = 0; i < gNBTable.tableSize; i++) + if (enumAll || gNBTable.table[i].transport_id == transport) + numLANAs++; + if (numLANAs > 0) + { + UCHAR lanaIndex = 0; + + for (i = 0; i < gNBTable.tableSize; i++) + if (gNBTable.table[i].transport_id != 0 && + (enumAll || gNBTable.table[i].transport_id == transport)) + cb(numLANAs, lanaIndex++, gNBTable.table[i].transport_id, + &gNBTable.table[i].impl, closure); + } + LeaveCriticalSection(&gNBTable.cs); + } +} + +static NetBIOSAdapter *nbGetAdapter(UCHAR lana) +{ + NetBIOSAdapter *ret = NULL; + + TRACE(": lana %d, num allocated adapters %d\n", lana, gNBTable.tableSize); + if (lana < gNBTable.tableSize && gNBTable.table[lana].transport_id != 0 + && gNBTable.table[lana].transport) + ret = &gNBTable.table[lana]; + TRACE("returning %p\n", ret); + return ret; +} + +static UCHAR nbEnum(PNCB ncb) +{ + PLANA_ENUM lanas = (PLANA_ENUM)ncb->ncb_buffer; + UCHAR i, ret; + + TRACE(": ncb %p\n", ncb); + + if (!lanas) + ret = NRC_BUFLEN; + else if (ncb->ncb_length < sizeof(LANA_ENUM)) + ret = NRC_BUFLEN; + else + { + nbInternalEnum(); + lanas->length = 0; + for (i = 0; i < gNBTable.tableSize; i++) + if (gNBTable.table[i].transport) + { + lanas->length++; + lanas->lana[i] = i; + } + ret = NRC_GOODRET; + } + TRACE("returning 0x%02x\n", ret); + return ret; +} + +static UCHAR nbInternalHangup(NetBIOSAdapter *adapter, NetBIOSSession *session); + +static UCHAR nbCancel(NetBIOSAdapter *adapter, PNCB ncb) +{ + UCHAR ret; + + TRACE(": adapter %p, ncb %p\n", adapter, ncb); + + if (!adapter) return NRC_BRIDGE; + if (!ncb) return NRC_INVADDRESS; + + switch (ncb->ncb_command & 0x7f) + { + case NCBCANCEL: + case NCBADDNAME: + case NCBADDGRNAME: + case NCBDELNAME: + case NCBRESET: + case NCBSSTAT: + ret = NRC_CANCEL; + break; + + /* NCBCALL, NCBCHAINSEND/NCBSEND, NCBHANGUP all close the associated + * session if cancelled */ + case NCBCALL: + case NCBSEND: + case NCBCHAINSEND: + case NCBSENDNA: + case NCBCHAINSENDNA: + case NCBHANGUP: + { + if (ncb->ncb_lsn >= adapter->sessionsLen) + ret = NRC_SNUMOUT; + else if (!adapter->sessions[ncb->ncb_lsn].inUse) + ret = NRC_SNUMOUT; + else + { + ret = NBCmdQueueCancel(adapter->cmdQueue, ncb); + if (ret == NRC_CMDCAN || ret == NRC_CANOCCR) + nbInternalHangup(adapter, &adapter->sessions[ncb->ncb_lsn]); + } + break; + } + + default: + ret = NBCmdQueueCancel(adapter->cmdQueue, ncb); + } + TRACE("returning 0x%02x\n", ret); + return ret; +} + +/* Resizes adapter to contain space for at least sessionsLen sessions. + * If allocating more space for sessions, sets the adapter's sessionsLen to + * sessionsLen. If the adapter's sessionsLen was already at least sessionsLen, + * does nothing. Does not modify existing sessions. Assumes the adapter is + * locked. + * Returns NRC_GOODRET on success, and something else on failure. + */ +static UCHAR nbResizeAdapter(NetBIOSAdapter *adapter, UCHAR sessionsLen) +{ + UCHAR ret = NRC_GOODRET; + + if (adapter && adapter->sessionsLen < sessionsLen) + { + NetBIOSSession *newSessions; + + if (adapter->sessions) + newSessions = (NetBIOSSession *)HeapReAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, adapter->sessions, sessionsLen * + sizeof(NetBIOSSession)); + else + newSessions = (NetBIOSSession *)HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, sessionsLen * sizeof(NetBIOSSession)); + if (newSessions) + { + adapter->sessions = newSessions; + adapter->sessionsLen = sessionsLen; + } + else + ret = NRC_OSRESNOTAV; + } + return ret; +} + +static UCHAR nbReset(NetBIOSAdapter *adapter, PNCB ncb) +{ + UCHAR ret; + + TRACE(": adapter %p, ncb %p\n", adapter, ncb); + + if (!adapter) return NRC_BRIDGE; + if (!ncb) return NRC_INVADDRESS; + + if (InterlockedIncrement(&adapter->resetting) == 1) + { + UCHAR i, resizeTo; + + NBCmdQueueCancelAll(adapter->cmdQueue); + + EnterCriticalSection(&adapter->cs); + for (i = 0; i < adapter->sessionsLen; i++) + if (adapter->sessions[i].inUse) + nbInternalHangup(adapter, &adapter->sessions[i]); + if (!ncb->ncb_lsn) + resizeTo = ncb->ncb_callname[0] == 0 ? DEFAULT_NUM_SESSIONS : + ncb->ncb_callname[0]; + else if (adapter->sessionsLen == 0) + resizeTo = DEFAULT_NUM_SESSIONS; + else + resizeTo = 0; + if (resizeTo > 0) + ret = nbResizeAdapter(adapter, resizeTo); + else + ret = NRC_GOODRET; + LeaveCriticalSection(&adapter->cs); + } + else + ret = NRC_TOOMANY; + InterlockedDecrement(&adapter->resetting); + TRACE("returning 0x%02x\n", ret); + return ret; +} + +static UCHAR nbSStat(NetBIOSAdapter *adapter, PNCB ncb) +{ + UCHAR ret, i, spaceFor; + PSESSION_HEADER sstat; + + TRACE(": adapter %p, NCB %p\n", adapter, ncb); + + if (!adapter) return NRC_BADDR; + if (adapter->sessionsLen == 0) return NRC_ENVNOTDEF; + if (!ncb) return NRC_INVADDRESS; + if (!ncb->ncb_buffer) return NRC_BADDR; + if (ncb->ncb_length < sizeof(SESSION_HEADER)) return NRC_BUFLEN; + + sstat = (PSESSION_HEADER)ncb->ncb_buffer; + ret = NRC_GOODRET; + memset(sstat, 0, sizeof(SESSION_HEADER)); + spaceFor = (ncb->ncb_length - sizeof(SESSION_HEADER)) / + sizeof(SESSION_BUFFER); + EnterCriticalSection(&adapter->cs); + for (i = 0; ret == NRC_GOODRET && i < adapter->sessionsLen; i++) + { + if (adapter->sessions[i].inUse && (ncb->ncb_name[0] == '*' || + !memcmp(ncb->ncb_name, adapter->sessions[i].local_name, NCBNAMSZ))) + { + if (sstat->num_sess < spaceFor) + { + PSESSION_BUFFER buf; + + buf = (PSESSION_BUFFER)((PUCHAR)sstat + sizeof(SESSION_HEADER) + + sstat->num_sess * sizeof(SESSION_BUFFER)); + buf->lsn = i; + buf->state = adapter->sessions[i].state; + memcpy(buf->local_name, adapter->sessions[i].local_name, + NCBNAMSZ); + memcpy(buf->remote_name, adapter->sessions[i].remote_name, + NCBNAMSZ); + buf->rcvs_outstanding = buf->sends_outstanding = 0; + sstat->num_sess++; + } + else + ret = NRC_BUFLEN; + } + } + LeaveCriticalSection(&adapter->cs); + + TRACE("returning 0x%02x\n", ret); + return ret; +} + +static UCHAR nbCall(NetBIOSAdapter *adapter, PNCB ncb) +{ + UCHAR ret, i; + + TRACE(": adapter %p, NCB %p\n", adapter, ncb); + + if (!adapter) return NRC_BRIDGE; + if (adapter->sessionsLen == 0) return NRC_ENVNOTDEF; + if (!adapter->transport->call) return NRC_ILLCMD; + if (!ncb) return NRC_INVADDRESS; + + EnterCriticalSection(&adapter->cs); + for (i = 0; i < adapter->sessionsLen && adapter->sessions[i].inUse; i++) + ; + if (i < adapter->sessionsLen) + { + adapter->sessions[i].inUse = TRUE; + adapter->sessions[i].state = CALL_PENDING; + memcpy(adapter->sessions[i].local_name, ncb->ncb_name, NCBNAMSZ); + memcpy(adapter->sessions[i].remote_name, ncb->ncb_callname, NCBNAMSZ); + ret = NRC_GOODRET; + } + else + ret = NRC_LOCTFUL; + LeaveCriticalSection(&adapter->cs); + + if (ret == NRC_GOODRET) + { + ret = adapter->transport->call(adapter->impl.data, ncb, + &adapter->sessions[i].data); + if (ret == NRC_GOODRET) + { + ncb->ncb_lsn = i; + adapter->sessions[i].state = SESSION_ESTABLISHED; + } + else + { + adapter->sessions[i].inUse = FALSE; + adapter->sessions[i].state = 0; + } + } + TRACE("returning 0x%02x\n", ret); + return ret; +} + +static UCHAR nbSend(NetBIOSAdapter *adapter, PNCB ncb) +{ + UCHAR ret; + NetBIOSSession *session; + + if (!adapter) return NRC_BRIDGE; + if (!adapter->transport->send) return NRC_ILLCMD; + if (!ncb) return NRC_INVADDRESS; + if (ncb->ncb_lsn >= adapter->sessionsLen) return NRC_SNUMOUT; + if (!adapter->sessions[ncb->ncb_lsn].inUse) return NRC_SNUMOUT; + if (!ncb->ncb_buffer) return NRC_BADDR; + + session = &adapter->sessions[ncb->ncb_lsn]; + if (session->state != SESSION_ESTABLISHED) + ret = NRC_SNUMOUT; + else + ret = adapter->transport->send(adapter->impl.data, session->data, ncb); + return ret; +} + +static UCHAR nbRecv(NetBIOSAdapter *adapter, PNCB ncb) +{ + UCHAR ret; + NetBIOSSession *session; + + if (!adapter) return NRC_BRIDGE; + if (!adapter->transport->recv) return NRC_ILLCMD; + if (!ncb) return NRC_INVADDRESS; + if (ncb->ncb_lsn >= adapter->sessionsLen) return NRC_SNUMOUT; + if (!adapter->sessions[ncb->ncb_lsn].inUse) return NRC_SNUMOUT; + if (!ncb->ncb_buffer) return NRC_BADDR; + + session = &adapter->sessions[ncb->ncb_lsn]; + if (session->state != SESSION_ESTABLISHED) + ret = NRC_SNUMOUT; + else + ret = adapter->transport->recv(adapter->impl.data, session->data, ncb); + return ret; +} + +static UCHAR nbInternalHangup(NetBIOSAdapter *adapter, NetBIOSSession *session) +{ + UCHAR ret; + + if (!adapter) return NRC_BRIDGE; + if (!session) return NRC_SNUMOUT; + + if (adapter->transport->hangup) + ret = adapter->transport->hangup(adapter->impl.data, session->data); + else + ret = NRC_ILLCMD; + EnterCriticalSection(&adapter->cs); + memset(session, 0, sizeof(NetBIOSSession)); + LeaveCriticalSection(&adapter->cs); + return NRC_GOODRET; +} + +static UCHAR nbHangup(NetBIOSAdapter *adapter, PNCB ncb) +{ + UCHAR ret; + NetBIOSSession *session; + + if (!adapter) return NRC_BRIDGE; + if (!ncb) return NRC_INVADDRESS; + if (ncb->ncb_lsn >= adapter->sessionsLen) return NRC_SNUMOUT; + if (!adapter->sessions[ncb->ncb_lsn].inUse) return NRC_SNUMOUT; + + session = &adapter->sessions[ncb->ncb_lsn]; + if (session->state != SESSION_ESTABLISHED) + ret = NRC_SNUMOUT; + else + { + session->state = HANGUP_PENDING; + ret = nbInternalHangup(adapter, session); + } + return ret; +} + +void NetBIOSHangupSession(PNCB ncb) +{ + NetBIOSAdapter *adapter; + + if (!ncb) return; + + adapter = nbGetAdapter(ncb->ncb_lana_num); + if (adapter) + { + if (ncb->ncb_lsn < adapter->sessionsLen && + adapter->sessions[ncb->ncb_lsn].inUse) + nbHangup(adapter, ncb); + } +} + +static UCHAR nbAStat(NetBIOSAdapter *adapter, PNCB ncb) +{ + UCHAR ret; + + if (!adapter) return NRC_BRIDGE; + if (!adapter->transport->astat) return NRC_ILLCMD; + if (!ncb) return NRC_INVADDRESS; + if (!ncb->ncb_buffer) return NRC_BADDR; + if (ncb->ncb_length < sizeof(ADAPTER_STATUS)) return NRC_BUFLEN; + + ret = adapter->transport->astat(adapter->impl.data, ncb); + if (ncb->ncb_callname[0] == '*') + { + PADAPTER_STATUS astat = (PADAPTER_STATUS)ncb->ncb_buffer; + + astat->max_sess = astat->max_cfg_sess = adapter->sessionsLen; + } + return ret; +} + +static UCHAR nbDispatch(NetBIOSAdapter *adapter, PNCB ncb) +{ + UCHAR ret, cmd; + + TRACE(": adapter %p, ncb %p\n", adapter, ncb); + + if (!adapter) return NRC_BRIDGE; + if (!ncb) return NRC_INVADDRESS; + + cmd = ncb->ncb_command & 0x7f; + if (cmd == NCBRESET) + ret = nbReset(adapter, ncb); + else + { + ret = NBCmdQueueAdd(adapter->cmdQueue, ncb); + if (ret == NRC_GOODRET) + { + switch (cmd) + { + case NCBCALL: + ret = nbCall(adapter, ncb); + break; + + /* WinNT doesn't chain sends, it always sends immediately. + * Doubt there's any real significance to the NA variants. + */ + case NCBSEND: + case NCBSENDNA: + case NCBCHAINSEND: + case NCBCHAINSENDNA: + ret = nbSend(adapter, ncb); + break; + + case NCBRECV: + ret = nbRecv(adapter, ncb); + break; + + case NCBHANGUP: + ret = nbHangup(adapter, ncb); + break; + + case NCBASTAT: + ret = nbAStat(adapter, ncb); + break; + + case NCBFINDNAME: + if (adapter->transport->findName) + ret = adapter->transport->findName(adapter->impl.data, + ncb); + else + ret = NRC_ILLCMD; + break; + + default: + FIXME("(%p): command code 0x%02x\n", ncb, ncb->ncb_command); + ret = NRC_ILLCMD; + } + NBCmdQueueComplete(adapter->cmdQueue, ncb, ret); + } + } + TRACE("returning 0x%02x\n", ret); + return ret; +} + +static DWORD WINAPI nbCmdThread(LPVOID lpVoid) +{ + PNCB ncb = (PNCB)lpVoid; + + if (ncb) + { + UCHAR ret; + NetBIOSAdapter *adapter = nbGetAdapter(ncb->ncb_lana_num); + + if (adapter) + ret = nbDispatch(adapter, ncb); + else + ret = NRC_BRIDGE; + ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret; + if (ncb->ncb_post) + ncb->ncb_post(ncb); + else if (ncb->ncb_event) + SetEvent(ncb->ncb_event); + } + return 0; +} + +UCHAR WINAPI Netbios(PNCB ncb) +{ + UCHAR ret, cmd; + + TRACE("ncb = %p\n", ncb); + + if (!ncb) return NRC_INVADDRESS; + + TRACE("ncb_command 0x%02x, ncb_lana_num %d, ncb_buffer %p, ncb_length %d\n", + ncb->ncb_command, ncb->ncb_lana_num, ncb->ncb_buffer, ncb->ncb_length); + cmd = ncb->ncb_command & 0x7f; + + if (cmd == NCBENUM) + ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret = nbEnum(ncb); + else + { + NetBIOSAdapter *adapter = nbGetAdapter(ncb->ncb_lana_num); + + if (!adapter) + ret = NRC_BRIDGE; + else + { + if (adapter->shuttingDown) + ret = NRC_IFBUSY; + else if (adapter->resetting) + ret = NRC_TOOMANY; + else + { + /* non-asynch commands first */ + if (cmd == NCBCANCEL) + ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret = + nbCancel(adapter, ncb); + else if (cmd == NCBSSTAT) + ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret = + nbSStat(adapter, ncb); + else + { + if (ncb->ncb_command & ASYNCH) + { + HANDLE thread = CreateThread(NULL, 0, nbCmdThread, ncb, + CREATE_SUSPENDED, NULL); + + if (thread != NULL) + { + ncb->ncb_retcode = ncb->ncb_cmd_cplt = NRC_PENDING; + if (ncb->ncb_event) + ResetEvent(ncb->ncb_event); + ResumeThread(thread); + CloseHandle(thread); + ret = NRC_GOODRET; + } + else + ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret = + NRC_OSRESNOTAV; + } + else + ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret = + nbDispatch(adapter, ncb); + } + } + } + } + TRACE("returning 0x%02x\n", ret); + return ret; +} diff --git a/reactos/lib/netapi32/netbios.h b/reactos/lib/netapi32/netbios.h new file mode 100644 index 00000000000..0130aaf701e --- /dev/null +++ b/reactos/lib/netapi32/netbios.h @@ -0,0 +1,183 @@ +/* Copyright (c) 2003 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __WINE_NETBIOS_H__ +#define __WINE_NETBIOS_H__ + +#include +#include "windef.h" +#include "winbase.h" +#include "lm.h" +#include "nb30.h" + +/* This file describes the interface WINE's NetBIOS implementation uses to + * interact with a transport implementation (where a transport might be + * NetBIOS-over-TCP/IP (aka NetBT, NBT), NetBIOS-over-IPX, etc.) + */ + +/** + * Public functions + */ + +void NetBIOSInit(void); +void NetBIOSShutdown(void); + +struct _NetBIOSTransport; + +/* A transport should register itself during its init function (see below) with + * a unique id (the transport_id of ACTION_HEADER, for example) and an + * implementation. Returns TRUE on success, and FALSE on failure. + */ +BOOL NetBIOSRegisterTransport(ULONG id, struct _NetBIOSTransport *transport); + +/* Registers an adapter with the given transport and ifIndex with NetBIOS. + * ifIndex is an interface index usable by the IpHlpApi. ifIndex is not + * required to be unique, but is required so that NetWkstaTransportEnum can use + * GetIfEntry to get the name and hardware address of the adapter. + * Returns TRUE on success, FALSE on failure. + * FIXME: need functions for retrieving the name and hardware index, rather + * than assuming a correlation with IpHlpApi. + */ +BOOL NetBIOSRegisterAdapter(ULONG transport, DWORD ifIndex, void *adapter); + +/* During enumeration, all adapters from your transport are disabled + * internally. If an adapter is still valid, reenable it with this function. + * Adapters you don't enable will have their transport's NetBIOSCleanupAdapter + * function (see below) called on them, and will be removed from the table. + * (This is to deal with lack of plug-and-play--sorry.) + */ +void NetBIOSEnableAdapter(UCHAR lana); + +/* Gets a quick count of the number of NetBIOS adapters. Not guaranteed not + * to change from one call to the next, depending on what's been enumerated + * lately. See also NetBIOSEnumAdapters. + */ +UCHAR NetBIOSNumAdapters(void); + +typedef struct _NetBIOSAdapterImpl { + UCHAR lana; + DWORD ifIndex; + void *data; +} NetBIOSAdapterImpl; + +typedef BOOL (*NetBIOSEnumAdaptersCallback)(UCHAR totalLANAs, UCHAR lanaIndex, + ULONG transport, const NetBIOSAdapterImpl *data, void *closure); + +/* Enumerates all NetBIOS adapters for the transport transport, or for all + * transports if transport is ALL_TRANSPORTS. Your callback will be called + * once for every enumerated adapter, with a count of how many adapters have + * been enumerated, a 0-based index relative to that count, the adapter's + * transport, and its ifIndex. + * Your callback should return FALSE if it no longer wishes to be called. + */ +void NetBIOSEnumAdapters(ULONG transport, NetBIOSEnumAdaptersCallback cb, + void *closure); + +/* Hangs up the session identified in the NCB; the NCB need not be a NCBHANGUP. + * Will result in the transport's hangup function being called, so release any + * locks you own before calling to avoid deadlock. + * This function is intended for use by a transport, if the session is closed + * by some error in the transport layer. + */ +void NetBIOSHangupSession(PNCB ncb); + +/** + * Functions a transport implementation must implement + */ + +/* This function is called to ask a transport implementation to enumerate any + * LANAs into the NetBIOS adapter table by: + * - calling NetBIOSRegisterAdapter for any new adapters + * - calling NetBIOSEnableAdapter for any existing adapters + * NetBIOSEnumAdapters (see) may be of use to determine which adapters already + * exist. + * A transport can assume no other thread is modifying the NetBIOS adapter + * table during the lifetime of its NetBIOSEnum function (and, therefore, that + * this function won't be called reentrantly). + */ +typedef UCHAR (*NetBIOSEnum)(void); + +/* A cleanup function for a transport. This is the last function called on a + * transport. + */ +typedef void (*NetBIOSCleanup)(void); + +/* Adapter functions */ + +/* Functions with direct mappings to the Netbios interface. These functions + * are expected to be synchronous, although the first four bytes of the + * reserved member of the ncb are a cancel flag. A long-running function + * should check whether this is not FALSE from time to time (see the + * NCB_CANCELLED macro), and return NRC_CMDCAN if it's been cancelled. (The + * remainder of the NCB's reserved field is, well, reserved.) + */ + +/* Used to see whether the pointer to an NCB has been cancelled. The NetBIOS + * interface designates certain functions as non-cancellable functions, but I + * use this flag for all NCBs. Support it if you can. + * FIXME: this isn't enough, need to support an EVENT or some such, because + * some calls (recv) will block indefinitely, so a reset, shutdown, etc. will + * never occur. + */ +#define NCB_CANCELLED(pncb) *(PBOOL)((pncb)->ncb_reserve) + +typedef UCHAR (*NetBIOSAstat)(void *adapter, PNCB ncb); +typedef UCHAR (*NetBIOSFindName)(void *adapter, PNCB ncb); + +/* Functions to support the session service */ + +/* Implement to support the NCBCALL command. If you need data stored for the + * session, return it in *session. You can clean it up in your NetBIOSHangup + * function (see). + */ +typedef UCHAR (*NetBIOSCall)(void *adapter, PNCB ncb, void **session); +typedef UCHAR (*NetBIOSSend)(void *adapter, void *session, PNCB ncb); +typedef UCHAR (*NetBIOSRecv)(void *adapter, void *session, PNCB ncb); +typedef UCHAR (*NetBIOSHangup)(void *adapter, void *session); + +/* The last function called on an adapter; it is not called reentrantly, and + * no new calls will be made on the adapter once this has been entered. Clean + * up any resources allocated for the adapter here. + */ +typedef void (*NetBIOSCleanupAdapter)(void *adapter); + +typedef struct _NetBIOSTransport +{ + NetBIOSEnum enumerate; + NetBIOSAstat astat; + NetBIOSFindName findName; + NetBIOSCall call; + NetBIOSSend send; + NetBIOSRecv recv; + NetBIOSHangup hangup; + NetBIOSCleanupAdapter cleanupAdapter; + NetBIOSCleanup cleanup; +} NetBIOSTransport; + +/* Transport-specific functions. When adding a transport, add a call to its + * init function in netapi32's DllMain. The transport can do any global + * initialization it needs here. It should call NetBIOSRegisterTransport to + * register itself with NetBIOS. + */ + +/* NetBIOS-over-TCP/IP (NetBT) functions */ + +/* Not defined by MS, so make my own private define: */ +#define TRANSPORT_NBT "MNBT" + +void NetBTInit(void); + +#endif /* ndef __WINE_NETBIOS_H__ */ diff --git a/reactos/lib/netapi32/stubs.c b/reactos/lib/netapi32/stubs.c new file mode 100644 index 00000000000..5d5f2a8c7fe --- /dev/null +++ b/reactos/lib/netapi32/stubs.c @@ -0,0 +1,64 @@ +/* + * Copyright 2002 Andriy Palamarchuk + * + * Net API buffer calls + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "wine/port.h" + +#include + +#include "windef.h" +#include "winbase.h" +#include "lmcons.h" +#include "lmapibuf.h" +#include "lmerr.h" +#include "winerror.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(netapi32); + +/************************************************************ + * NetApiBufferFree (NETAPI32.@) + */ +NET_API_STATUS WINAPI NetApiBufferFree(LPVOID Buffer) +{ + FIXME("(%p)\n", Buffer); + return NERR_Success; +} + +/************************************************************ + * NetUserGetInfo (NETAPI32.@) + */ +NET_API_STATUS WINAPI +NetUserGetInfo(LPCWSTR servername, LPCWSTR username, DWORD level, + LPBYTE* bufptr) +{ + FIXME("(%s, %s, %ld, %p)\n", debugstr_w(servername), debugstr_w(username), + level, bufptr); + return NERR_Success; +} + +/************************************************************ + * NetWkstaUserGetInfo (NETAPI32.@) + */ +NET_API_STATUS NetWkstaUserGetInfo(LPWSTR reserved, DWORD level, + LPBYTE* bufptr) +{ + return NERR_Success; +} diff --git a/reactos/lib/netapi32/wksta.c b/reactos/lib/netapi32/wksta.c new file mode 100644 index 00000000000..8a0ebf36ced --- /dev/null +++ b/reactos/lib/netapi32/wksta.c @@ -0,0 +1,520 @@ +/* Copyright 2002 Andriy Palamarchuk + * Copyright (c) 2003 Juan Lang + * + * netapi32 user functions + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include "windef.h" +#include "winbase.h" +#include "winsock2.h" +#include "nb30.h" +#include "lmcons.h" +#include "lmapibuf.h" +#include "lmerr.h" +#include "lmwksta.h" +#include "iphlpapi.h" +#include "winerror.h" +#include "ntstatus.h" +#include "winreg.h" +#include "ntsecapi.h" +#include "netbios.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(netapi32); + +/************************************************************ + * NETAPI_IsLocalComputer + * + * Checks whether the server name indicates local machine. + */ +BOOL NETAPI_IsLocalComputer(LPCWSTR ServerName) +{ + if (!ServerName) + { + return TRUE; + } + else + { + DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1; + BOOL Result; + LPWSTR buf; + + NetApiBufferAllocate(dwSize * sizeof(WCHAR), (LPVOID *) &buf); + Result = GetComputerNameW(buf, &dwSize); + if (Result && (ServerName[0] == '\\') && (ServerName[1] == '\\')) + ServerName += 2; + Result = Result && !lstrcmpW(ServerName, buf); + NetApiBufferFree(buf); + + return Result; + } +} + +static void wprint_mac(WCHAR* buffer, int len, PMIB_IFROW ifRow) +{ + int i; + unsigned char val; + + if (!buffer) + return; + if (len < 1) + return; + if (!ifRow) + { + *buffer = '\0'; + return; + } + + for (i = 0; i < ifRow->dwPhysAddrLen && 2 * i < len; i++) + { + val = ifRow->bPhysAddr[i]; + if ((val >>4) >9) + buffer[2*i] = (WCHAR)((val >>4) + 'A' - 10); + else + buffer[2*i] = (WCHAR)((val >>4) + '0'); + if ((val & 0xf ) >9) + buffer[2*i+1] = (WCHAR)((val & 0xf) + 'A' - 10); + else + buffer[2*i+1] = (WCHAR)((val & 0xf) + '0'); + } + buffer[2*i]=(WCHAR)0; +} + +/* Theoretically this could be too short, except that MS defines + * MAX_ADAPTER_NAME as 128, and MAX_INTERFACE_NAME_LEN as 256, and both + * represent a count of WCHARs, so even with an extroardinarily long header + * this will be plenty + */ +#define MAX_TRANSPORT_NAME MAX_INTERFACE_NAME_LEN +#define MAX_TRANSPORT_ADDR 13 + +#define NBT_TRANSPORT_NAME_HEADER "\\Device\\NetBT_Tcpip_" +#define UNKNOWN_TRANSPORT_NAME_HEADER "\\Device\\UnknownTransport_" + +static void wprint_name(WCHAR *buffer, int len, ULONG transport, + PMIB_IFROW ifRow) +{ + WCHAR *ptr1, *ptr2; + const char *name; + + if (!buffer) + return; + if (!ifRow) + { + *buffer = '\0'; + return; + } + + if (!memcmp(&transport, TRANSPORT_NBT, sizeof(ULONG))) + name = NBT_TRANSPORT_NAME_HEADER; + else + name = UNKNOWN_TRANSPORT_NAME_HEADER; + + for (ptr1 = buffer; *name && ptr1 < buffer + len; ptr1++, name++) + *ptr1 = *name; + for (ptr2 = ifRow->wszName; *ptr2 && ptr1 < buffer + len; ptr1++, ptr2++) + *ptr1 = *ptr2; + *ptr1 = '\0'; +} + +struct WkstaTransportEnumData +{ + UCHAR n_adapt; + UCHAR n_read; + DWORD prefmaxlen; + LPBYTE *pbuf; + NET_API_STATUS ret; +}; + +static BOOL WkstaEnumAdaptersCallback(UCHAR totalLANAs, UCHAR lanaIndex, + ULONG transport, const NetBIOSAdapterImpl *data, void *closure) +{ + BOOL ret; + struct WkstaTransportEnumData *enumData = (struct WkstaTransportEnumData *) + closure; + + if (enumData && enumData->pbuf) + { + if (lanaIndex == 0) + { + DWORD toAllocate; + + enumData->n_adapt = totalLANAs; + enumData->n_read = 0; + + toAllocate = totalLANAs * (sizeof(WKSTA_TRANSPORT_INFO_0) + + MAX_TRANSPORT_NAME * sizeof(WCHAR) + + MAX_TRANSPORT_ADDR * sizeof(WCHAR)); + if (enumData->prefmaxlen != MAX_PREFERRED_LENGTH) + toAllocate = enumData->prefmaxlen; + NetApiBufferAllocate(toAllocate, (LPVOID *)enumData->pbuf); + } + if (*(enumData->pbuf)) + { + UCHAR spaceFor; + + if (enumData->prefmaxlen == MAX_PREFERRED_LENGTH) + spaceFor = totalLANAs; + else + spaceFor = enumData->prefmaxlen / + (sizeof(WKSTA_TRANSPORT_INFO_0) + (MAX_TRANSPORT_NAME + + MAX_TRANSPORT_ADDR) * sizeof(WCHAR)); + if (enumData->n_read < spaceFor) + { + PWKSTA_TRANSPORT_INFO_0 ti; + LPWSTR transport_name, transport_addr; + MIB_IFROW ifRow; + + ti = (PWKSTA_TRANSPORT_INFO_0)(*(enumData->pbuf) + + enumData->n_read * sizeof(WKSTA_TRANSPORT_INFO_0)); + transport_name = (LPWSTR)(*(enumData->pbuf) + + totalLANAs * sizeof(WKSTA_TRANSPORT_INFO_0) + + enumData->n_read * MAX_TRANSPORT_NAME * sizeof(WCHAR)); + transport_addr = (LPWSTR)(*(enumData->pbuf) + + totalLANAs * (sizeof(WKSTA_TRANSPORT_INFO_0) + + MAX_TRANSPORT_NAME * sizeof(WCHAR)) + + enumData->n_read * MAX_TRANSPORT_ADDR * sizeof(WCHAR)); + + ifRow.dwIndex = data->ifIndex; + GetIfEntry(&ifRow); + ti->wkti0_quality_of_service = 0; + ti->wkti0_number_of_vcs = 0; + ti->wkti0_transport_name = transport_name; + wprint_name(ti->wkti0_transport_name, MAX_TRANSPORT_NAME, + transport, &ifRow); + ti->wkti0_transport_address = transport_addr; + wprint_mac(ti->wkti0_transport_address, MAX_TRANSPORT_ADDR, + &ifRow); + if (!memcmp(&transport, TRANSPORT_NBT, sizeof(ULONG))) + ti->wkti0_wan_ish = TRUE; + else + ti->wkti0_wan_ish = FALSE; + TRACE("%d of %d:ti at %p\n", lanaIndex, totalLANAs, ti); + TRACE("transport_name at %p %s\n", + ti->wkti0_transport_name, + debugstr_w(ti->wkti0_transport_name)); + TRACE("transport_address at %p %s\n", + ti->wkti0_transport_address, + debugstr_w(ti->wkti0_transport_address)); + enumData->n_read++; + enumData->ret = NERR_Success; + ret = TRUE; + } + else + { + enumData->ret = ERROR_MORE_DATA; + ret = FALSE; + } + } + else + { + enumData->ret = ERROR_OUTOFMEMORY; + ret = FALSE; + } + } + else + ret = FALSE; + return ret; +} + +NET_API_STATUS WINAPI +NetWkstaTransportEnum(LPWSTR ServerName, DWORD level, PBYTE* pbuf, + DWORD prefmaxlen, LPDWORD read_entries, + PDWORD total_entries, PDWORD hresume) +{ + NET_API_STATUS ret; + + TRACE(":%s, 0x%08lx, %p, 0x%08lx, %p, %p, %p\n", debugstr_w(ServerName), + level, pbuf, prefmaxlen, read_entries, total_entries,hresume); + if (!NETAPI_IsLocalComputer(ServerName)) + { + FIXME(":not implemented for non-local computers\n"); + ret = ERROR_INVALID_LEVEL; + } + else + { + if (hresume && *hresume) + { + FIXME(":resume handle not implemented\n"); + return ERROR_INVALID_LEVEL; + } + + switch (level) + { + case 0: /* transport info */ + { + ULONG allTransports; + struct WkstaTransportEnumData enumData; + + if (NetBIOSNumAdapters() == 0) + return ERROR_NETWORK_UNREACHABLE; + if (!read_entries) + return STATUS_ACCESS_VIOLATION; + if (!total_entries || !pbuf) + return RPC_X_NULL_REF_POINTER; + + enumData.prefmaxlen = prefmaxlen; + enumData.pbuf = pbuf; + memcpy(&allTransports, ALL_TRANSPORTS, sizeof(ULONG)); + NetBIOSEnumAdapters(allTransports, WkstaEnumAdaptersCallback, + &enumData); + *read_entries = enumData.n_read; + *total_entries = enumData.n_adapt; + if (hresume) *hresume= 0; + ret = enumData.ret; + break; + } + default: + ERR("Invalid level %ld is specified\n", level); + ret = ERROR_INVALID_LEVEL; + } + } + return ret; +} + + +/************************************************************ + * NetWkstaUserGetInfo (NETAPI32.@) + */ +NET_API_STATUS WINAPI NetWkstaUserGetInfo(LPWSTR reserved, DWORD level, + PBYTE* bufptr) +{ + TRACE("(%s, %ld, %p)\n", debugstr_w(reserved), level, bufptr); + switch (level) + { + case 0: + { + PWKSTA_USER_INFO_0 ui; + DWORD dwSize = UNLEN + 1; + + /* set up buffer */ + NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_0) + dwSize * sizeof(WCHAR), + (LPVOID *) bufptr); + + ui = (PWKSTA_USER_INFO_0) *bufptr; + ui->wkui0_username = (LPWSTR) (*bufptr + sizeof(WKSTA_USER_INFO_0)); + + /* get data */ + if (!GetUserNameW(ui->wkui0_username, &dwSize)) + { + NetApiBufferFree(ui); + return ERROR_NOT_ENOUGH_MEMORY; + } + else + NetApiBufferReallocate( + *bufptr, sizeof(WKSTA_USER_INFO_0) + + (lstrlenW(ui->wkui0_username) + 1) * sizeof(WCHAR), + (LPVOID *) bufptr); + break; + } + + case 1: + { + PWKSTA_USER_INFO_1 ui; + PWKSTA_USER_INFO_0 ui0; + DWORD dwSize; + LSA_OBJECT_ATTRIBUTES ObjectAttributes; + LSA_HANDLE PolicyHandle; + PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo; + NTSTATUS NtStatus; + + /* sizes of the field buffers in WCHARS */ + int username_sz, logon_domain_sz, oth_domains_sz, logon_server_sz; + + FIXME("Level 1 processing is partially implemented\n"); + oth_domains_sz = 1; + logon_server_sz = 1; + + /* get some information first to estimate size of the buffer */ + ui0 = NULL; + NetWkstaUserGetInfo(NULL, 0, (PBYTE *) &ui0); + username_sz = lstrlenW(ui0->wkui0_username) + 1; + + ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes)); + NtStatus = LsaOpenPolicy(NULL, &ObjectAttributes, + POLICY_VIEW_LOCAL_INFORMATION, + &PolicyHandle); + if (NtStatus != STATUS_SUCCESS) + { + ERR("LsaOpenPolicyFailed with NT status %lx\n", + LsaNtStatusToWinError(NtStatus)); + NetApiBufferFree(ui0); + return ERROR_NOT_ENOUGH_MEMORY; + } + LsaQueryInformationPolicy(PolicyHandle, PolicyAccountDomainInformation, + (PVOID*) &DomainInfo); + logon_domain_sz = lstrlenW(DomainInfo->DomainName.Buffer) + 1; + LsaClose(PolicyHandle); + + /* set up buffer */ + NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1) + + (username_sz + logon_domain_sz + + oth_domains_sz + logon_server_sz) * sizeof(WCHAR), + (LPVOID *) bufptr); + ui = (WKSTA_USER_INFO_1 *) *bufptr; + ui->wkui1_username = (LPWSTR) (*bufptr + sizeof(WKSTA_USER_INFO_1)); + ui->wkui1_logon_domain = (LPWSTR) ( + ((PBYTE) ui->wkui1_username) + username_sz * sizeof(WCHAR)); + ui->wkui1_oth_domains = (LPWSTR) ( + ((PBYTE) ui->wkui1_logon_domain) + + logon_domain_sz * sizeof(WCHAR)); + ui->wkui1_logon_server = (LPWSTR) ( + ((PBYTE) ui->wkui1_oth_domains) + + oth_domains_sz * sizeof(WCHAR)); + + /* get data */ + dwSize = username_sz; + lstrcpyW(ui->wkui1_username, ui0->wkui0_username); + NetApiBufferFree(ui0); + + lstrcpynW(ui->wkui1_logon_domain, DomainInfo->DomainName.Buffer, + logon_domain_sz); + LsaFreeMemory(DomainInfo); + + /* FIXME. Not implemented. Populated with empty strings */ + ui->wkui1_oth_domains[0] = 0; + ui->wkui1_logon_server[0] = 0; + break; + } + case 1101: + { + PWKSTA_USER_INFO_1101 ui; + DWORD dwSize = 1; + + FIXME("Stub. Level 1101 processing is not implemented\n"); + /* FIXME see also wkui1_oth_domains for level 1 */ + + /* set up buffer */ + NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1101) + dwSize * sizeof(WCHAR), + (LPVOID *) bufptr); + + ui = (PWKSTA_USER_INFO_1101) *bufptr; + ui->wkui1101_oth_domains = (LPWSTR)(ui + 1); + + /* get data */ + ui->wkui1101_oth_domains[0] = 0; + break; + } + default: + ERR("Invalid level %ld is specified\n", level); + return ERROR_INVALID_LEVEL; + } + return NERR_Success; +} + +/************************************************************ + * NetpGetComputerName (NETAPI32.@) + */ +NET_API_STATUS WINAPI NetpGetComputerName(LPWSTR *Buffer) +{ + DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1; + + TRACE("(%p)\n", Buffer); + NetApiBufferAllocate(dwSize * sizeof(WCHAR), (LPVOID *) Buffer); + if (GetComputerNameW(*Buffer, &dwSize)) + { + NetApiBufferReallocate( + *Buffer, dwSize * sizeof(WCHAR), + (LPVOID *) Buffer); + return NERR_Success; + } + else + { + NetApiBufferFree(*Buffer); + return ERROR_NOT_ENOUGH_MEMORY; + } +} + +NET_API_STATUS WINAPI NetWkstaGetInfo( LPWSTR servername, DWORD level, + LPBYTE* bufptr) +{ + NET_API_STATUS ret; + + TRACE("%p %ld %p\n", debugstr_w( servername ), level, bufptr ); + if (servername) + { + FIXME("remote computers not supported\n"); + return ERROR_INVALID_LEVEL; + } + if (!bufptr) return ERROR_INVALID_PARAMETER; + + switch (level) + { + case 100: + { + DWORD computerNameLen, domainNameLen, size; + WCHAR computerName[MAX_COMPUTERNAME_LENGTH + 1]; + LSA_OBJECT_ATTRIBUTES ObjectAttributes; + LSA_HANDLE PolicyHandle; + NTSTATUS NtStatus; + + computerNameLen = MAX_COMPUTERNAME_LENGTH + 1; + GetComputerNameW(computerName, &computerNameLen); + computerNameLen++; /* include NULL terminator */ + + ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes)); + NtStatus = LsaOpenPolicy(NULL, &ObjectAttributes, + POLICY_VIEW_LOCAL_INFORMATION, &PolicyHandle); + if (NtStatus != STATUS_SUCCESS) + ret = LsaNtStatusToWinError(NtStatus); + else + { + PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo; + + LsaQueryInformationPolicy(PolicyHandle, + PolicyAccountDomainInformation, (PVOID*)&DomainInfo); + domainNameLen = lstrlenW(DomainInfo->DomainName.Buffer) + 1; + size = sizeof(WKSTA_INFO_100) + computerNameLen * sizeof(WCHAR) + + domainNameLen * sizeof(WCHAR); + ret = NetApiBufferAllocate(size, (LPVOID *)bufptr); + if (ret == NERR_Success) + { + PWKSTA_INFO_100 info = (PWKSTA_INFO_100)*bufptr; + OSVERSIONINFOW verInfo; + + info->wki100_platform_id = PLATFORM_ID_NT; + info->wki100_computername = (LPWSTR)(*bufptr + + sizeof(WKSTA_INFO_100)); + memcpy(info->wki100_computername, computerName, + computerNameLen * sizeof(WCHAR)); + info->wki100_langroup = (LPWSTR)(*bufptr + + sizeof(WKSTA_INFO_100) + computerNameLen * sizeof(WCHAR)); + memcpy(info->wki100_langroup, DomainInfo->DomainName.Buffer, + domainNameLen * sizeof(WCHAR)); + memset(&verInfo, 0, sizeof(verInfo)); + verInfo.dwOSVersionInfoSize = sizeof(verInfo); + GetVersionExW(&verInfo); + info->wki100_ver_major = verInfo.dwMajorVersion; + info->wki100_ver_minor = verInfo.dwMinorVersion; + } + LsaFreeMemory(DomainInfo); + LsaClose(PolicyHandle); + } + break; + } + + default: + FIXME("level %ld unimplemented\n", level); + ret = ERROR_INVALID_LEVEL; + } + return ret; +}