_Undocumented Windows NT and the NetWare Core Protocol_ by Sven B. Schreiber Listing One ;============================================================================== ; > ebx - request record ; < ebx - request record ; edi - input buffer ; eax - status code ; c - set if error ;------------------------------------------------------------------------------ CreateNcpPackets: mov ecx,4 ;get input buffer size cmp word ptr [ebx.rr_RequestCode],-1 adc ecx,[ebx.rr_RequestBufferSize] add ecx,2 mov edx,4 ;get output buffer size add edx,[ebx.rr_ReplyBufferSize] add edx,2 mov eax,ecx add eax,edx ;compute temporary buffer size add eax,IO_STATUS_BLOCK_ push ebx push ecx push edx Win32 LocalAlloc,\ ;allocate temporary buffer LMEM_FIXED+LMEM_ZEROINIT,\ eax mov edi,eax pop edx pop ecx pop ebx mov [ebx.rr_MemoryHandle],edi ;save memory handle cmp edi,NULL ;allocation error? mov eax,STATUS_NO_MEMORY stc jz CreateNcpPackets1 lea edi,[edi+4] ;set input buffer size sub ecx,4+2 mov [edi-4],ecx mov [ebx.rr_InBufferAddress],edi ;set input buffer address lea edi,[edi+ecx+2+4] ;set output buffer size sub edx,4+2 mov [edi-4],edx mov [ebx.rr_OutBufferAddress],edi ;set output buffer address mov edi,[ebx.rr_InBufferAddress] ;load input buffer address cmp word ptr [ebx.rr_RequestCode],-1 ;skip subfunction byte if any adc edi,0 mov eax,STATUS_SUCCESS ;ok clc CreateNcpPackets1: ret ;============================================================================== ; > ebx - request record ; edi - end of input buffer ; ecx - connection handle ; < ebx - request record ; esi - output buffer ; eax - status code ; c - set if error ;------------------------------------------------------------------------------ SendNcpRequest: push ebx mov eax,[ebx.rr_RequestCode] ;load request code mov esi,[ebx.rr_InBufferAddress] ;load input buffer address sub edi,esi ;update input buffer size mov [esi-4],edi mov edi,[ebx.rr_OutBufferAddress] ;load output buffer address mov ebx,[edi-4] ;get i/o status block address lea ebx,[edi+ebx+2] cmp ax,-1 ;subfunction code included? jnb SendNcpRequest1 mov [esi],al ;set subfunction code SendNcpRequest1: shr eax,16 ;make device control code shl eax,2 or eax,DEVICE_NWRDR_NCP push edi push ebx Win32 NtFsControlFile,\ ;send request [ecx.ch_Handle],\ NULL,\ NULL,\ NULL,\ ebx,\ eax,\ esi,\ [esi-4],\ edi,\ [edi-4] pop ebx pop edi mov esi,edi ;load output buffer address cmp eax,STATUS_SUCCESS ;error? jnz SendNcpRequest2 mov eax,[ebx.io_Status] ;load i/o status code SendNcpRequest2: cmp eax,STATUS_SUCCESS ;error? stc jnz SendNcpRequest3 mov ecx,[ebx.io_Information] ;update output buffer size mov [esi-4],ecx clc ;ok SendNcpRequest3: pop ebx ret ;============================================================================== ; > ebx - request record ; esi - end of output buffer ; eax - status code ; < ebx - request record ; eax - status code ; c - set if error ;------------------------------------------------------------------------------ DestroyNcpPackets: cmp eax,STATUS_SUCCESS ;previous error? jnz DestroyNcpPackets1 mov edi,[ebx.rr_OutBufferAddress] ;get number of bytes processed sub esi,edi cmp [edi-4],esi ;missing data? jnb DestroyNcpPackets1 mov eax,STATUS_DATA_ERROR DestroyNcpPackets1: mov edi,NULL ;load/clear memory handle xchg edi,[ebx.rr_MemoryHandle] push eax push ebx Win32 LocalFree,\ ;deallocate temporary buffer edi pop ebx pop eax cmp eax,STATUS_SUCCESS ;error? stc jnz DestroyNcpPackets2 clc ;ok DestroyNcpPackets2: ret Listing Two ;============================================================================== ; > dArg01 - connection handle ; dArg02 - date/time buffer ; < eax - completion code ; c - set if error ;------------------------------------------------------------------------------ NWGetFileServerDateAndTime: ApiPrologue mov ebx,NcpGetFileServerDateAndTime ;create ncp packets call CreateNcpPackets jb NWGetFileServerDateAndTime2 mov ecx,dArg01 ;send ncp request call SendNcpRequest jb NWGetFileServerDateAndTime1 mov edi,dArg02 ;copy date/time mov ecx,NWDATE_TIME_ call CopyDataBlock NWGetFileServerDateAndTime1: call DestroyNcpPackets ;destroy ncp packets NWGetFileServerDateAndTime2: call GetCompletionCode ;get netware completion code ApiEpilogue 2 Listing Three NcpGetFileServerDateAndTime: REQUEST_RECORD {NCP_GET_FILE_SERVER_DATE_AND_TIME,\ 0, NWDATE_TIME_} Table 1: NetWare API Function Name NT 3.51 NT 4.00 Win 95 NWAddTrusteeToDirectory() X X NWAllocPermanentDirectoryHandle() X X X NWAllocTemporaryDirectoryHandle() X X X NWAttachToFileServer() X X X NWChangeObjectPassword() X NWCheckConsolePrivileges() X X X NWDeallocateDirectoryHandle() X X X NWDetachFromFileServer() X X X NWGetFileServerDateAndTime() X X NWGetFileServerVersionInfo() X X X NWGetInternetAddress() X X X NWGetObjectName() X X X NWGetVolumeInfoWithHandle() X X X NWGetVolumeInfoWithNumber() X X X NWGetVolumeName() X X X NWGetVolumeNumber() X NWIsObjectInSet() X X X NWLoginToFileServer() X X X NWLogoutFromFileServer() X X X NWReadPropertyValue() X X X NWScanObject() X X X NWScanProperty() X X X Table 2: Code Purpose Params Contents / Types b Copy BYTE 1 Immediate data (bits 0..7) c Copy C string 1 Pointer to string C Copy C string to buffer 2 Pointer to string, Buffer size (bits 0..15) d Copy DWORD (swap bytes) 1 Immediate data p Copy Pascal string to C string 1 Pointer to string r Copy data record 2 Pointer to record, Number of bytes (bits 0..15) u Copy UNICODE_STRING to Pascal OEM string 1 Pointer to UNICODE_STRING U Copy UNICODE_STRING to Pascal OEM string (convert to uppercase) 1 Pointer to UNICODE_STRING w Copy WORD (swap bytes) 1 Immediate data (bits 0..15) _ Zero fill 1 Number of bytes (bits 0..15) - Write NULL BYTE - - = Write NULL WORD - - | Separator for request/reply parameters - - Table 3: Code Purpose Params Contents/Types b Copy BYTE 1 Immediate data (bits 0..7) c Copy C string 1 Pointer to string C Copy C string to buffer 2 Pointer to string, Buffer size (bits 0..15) d Copy DWORD (swap bytes) 1 Immediate data p Copy Pascal string to C string 1 Pointer to string r Copy data record 2 Pointer to record, Number of bytes (bits 0..15) w Copy WORD (swap bytes) 1 Immediate data (bits 0..15) W Copy WORD array (swap bytes) 2 Pointer to count (WORD), Pointer to array _ Skip 1 Number of bytes (bits 0..15) | Separator for request/reply parameters - - Table 4: NetWare API Function Name Purpose NWAttachToFileServer() Open a server connection NWCRequest() Send a fragmented NCP request NWCRequestSingle() Send an unfragmented NCP request NWDetachFromFileServer() Close a server connection NWGetConnectionInformation() Request info on a connection NWGetConnectionNumber() Obtain the server-assigned connection number NWGetFileServerDateAndTime() Get current date and time NWGetFileServerUTCTime() Get current UTC date and time in packed format NWGetFileServerVersionInfo() Get information on a server NWGetInetAddr() Get the Internet address of a server NWGetLoginPasswordKey() Request a password key for a server login NWGetObjectID() Convert an object name to an object ID number NWGetObjectName() Convert an object ID number to the corresponding name NWGetVolumeName() Enumerate server volume names NWLoginToFileServer() Login to a server, using an encrypted password NWLogoutFromFileServer() Logout from a server NWLongSwap() Reverse byte ordering of a DWORD variable NWWordSwap() Reverse byte ordering of a WORD variable NwlibEncrypt() Encrypt login data NwlibEncryptPassword() Encrypt a login password NwlibGetCompletionCode() Convert NT status code to NetWare completion code NwlibGetLoginKey() Request a login key for password encryption NwlibGetPasswordKey() Convert a hashed password to a login key NwlibLoginObject() Non-encrypted server login NwlibLoginObjectEncrypted() Encrypted server login NwlibLoginUserObject() Non-encrypted server login for a user-type object NwlibUTCTimeToDateAndTime() Convert packed time to NetWare time structure Figure 1: NTSTATUS NwlibMakeNcp( IN HANDLE hDevice, IN DWORD dwIoControlCode, IN DWORD nInBufferSize, IN DWORD nOutBufferSize, IN LPSTR lpParameterControl, IN , OUT ) Figure 2: NTSTATUS NtOpenFile( OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG ShareAccess, IN ULONG CreateOptions); Figure 3: NTSTATUS NtClose( IN HANDLE Handle); Figure 4: NTSTATUS NtFsControlFile( IN HANDLE hDevice, IN HANDLE hEvent, DWORD reserved, IN LPOVERLAPPED lpOverlapped, OUT PIO_STATUS_BLOCK IoStatusBlock, IN DWORD dwIoControlCode, IN LPVOID lpInBuffer, IN DWORD nInBufferSize, OUT LPVOID lpOutBuffer, IN DWORD nOutBufferSize); Figure 5: NWCCODE NWCRequest( IN NWCONN_HANDLE hConnection, IN BYTE nNcpFunctionNumber, IN DWORD nRequestFragmentCount, IN LPVOID lpRequestFragmentList, IN DWORD nReplyFragmentCount, OUT LPVOID lpReplyFragmentList, DWORD reserved Figure 6: NWCCODE NWCRequestSingle( IN NWCONN_HANDLE hConnection, IN BYTE nNcpFunctionNumber, IN LPVOID lpRequestPacket, IN DWORD nRequestPacketSize, OUT LPVOID lpReplyPacket, IN DWORD nReplyPacketSize, DWORD reserved