Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1010 lines
32 KiB

/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
utils.c
Abstract:
Grab bag of functions used by the web dav mini-redir client service.
Author:
Andy Herron (andyhe) 29-Mar-1999
Environment:
User Mode - Win32
Revision History:
--*/
#include "pch.h"
#pragma hdrstop
#include <ntumrefl.h>
#include <usrmddav.h>
#include "global.h"
//
// These tables translate wininet codes to the closest ntstatus codes. There are
// two because there are some errors in wininet which come from ftp and gopher
// which are not relevant to us.
//
typedef struct tagHTTP_TO_NTSTATUS_MAPPING {
DWORD dwHttpError;
NTSTATUS Status;
} HTTP_TO_NTSTATUS_MAPPING;
typedef struct tagWIN32_TO_NTSTATUS_MAPPING {
DWORD dwWin32Error;
NTSTATUS NtStatus;
} WIN32_TO_NTSTATUS_MAPPING;
HTTP_TO_NTSTATUS_MAPPING rgHttpToNtstatus1[] = {
ERROR_INTERNET_OUT_OF_HANDLES ,STATUS_INSUFFICIENT_RESOURCES // (INTERNET_ERROR_BASE + 1)
,ERROR_INTERNET_TIMEOUT ,STATUS_BAD_NETWORK_PATH // (INTERNET_ERROR_BASE + 2)
,ERROR_INTERNET_EXTENDED_ERROR ,STATUS_UNSUCCESSFUL // (INTERNET_ERROR_BASE + 3)
,ERROR_INTERNET_INTERNAL_ERROR ,STATUS_INTERNAL_ERROR // (INTERNET_ERROR_BASE + 4)
,ERROR_INTERNET_INVALID_URL ,STATUS_OBJECT_NAME_INVALID // (INTERNET_ERROR_BASE + 5)
,ERROR_INTERNET_UNRECOGNIZED_SCHEME ,STATUS_OBJECT_NAME_INVALID // (INTERNET_ERROR_BASE + 6)
,ERROR_INTERNET_NAME_NOT_RESOLVED ,STATUS_BAD_NETWORK_PATH // (INTERNET_ERROR_BASE + 7)
,ERROR_INTERNET_PROTOCOL_NOT_FOUND ,STATUS_OBJECT_TYPE_MISMATCH // (INTERNET_ERROR_BASE + 8)
,ERROR_INTERNET_INVALID_OPTION ,STATUS_INVALID_PARAMETER // (INTERNET_ERROR_BASE + 9)
,ERROR_INTERNET_BAD_OPTION_LENGTH ,STATUS_INVALID_PARAMETER // (INTERNET_ERROR_BASE + 10)
,ERROR_INTERNET_OPTION_NOT_SETTABLE ,STATUS_INVALID_PARAMETER // (INTERNET_ERROR_BASE + 11)
,ERROR_INTERNET_SHUTDOWN ,STATUS_UNSUCCESSFUL // (INTERNET_ERROR_BASE + 12)
,ERROR_INTERNET_INCORRECT_USER_NAME ,STATUS_LOGON_FAILURE // (INTERNET_ERROR_BASE + 13)
,ERROR_INTERNET_INCORRECT_PASSWORD ,STATUS_LOGON_FAILURE // (INTERNET_ERROR_BASE + 14)
,ERROR_INTERNET_LOGIN_FAILURE ,STATUS_LOGON_FAILURE // (INTERNET_ERROR_BASE + 15)
,ERROR_INTERNET_INVALID_OPERATION ,STATUS_INVALID_DEVICE_REQUEST // (INTERNET_ERROR_BASE + 16)
,ERROR_INTERNET_OPERATION_CANCELLED ,STATUS_CANCELLED // (INTERNET_ERROR_BASE + 17)
,ERROR_INTERNET_INCORRECT_HANDLE_TYPE ,STATUS_INVALID_HANDLE // (INTERNET_ERROR_BASE + 18)
,ERROR_INTERNET_INCORRECT_HANDLE_STATE ,STATUS_INVALID_HANDLE // (INTERNET_ERROR_BASE + 19)
,ERROR_INTERNET_NOT_PROXY_REQUEST ,STATUS_INVALID_PARAMETER // (INTERNET_ERROR_BASE + 20)
,ERROR_INTERNET_REGISTRY_VALUE_NOT_FOUND ,STATUS_OBJECT_NAME_NOT_FOUND // (INTERNET_ERROR_BASE + 21)
,ERROR_INTERNET_BAD_REGISTRY_PARAMETER ,STATUS_INVALID_PARAMETER // (INTERNET_ERROR_BASE + 22)
,ERROR_INTERNET_NO_DIRECT_ACCESS ,STATUS_UNSUCCESSFUL // (INTERNET_ERROR_BASE + 23)
,ERROR_INTERNET_NO_CONTEXT ,STATUS_UNSUCCESSFUL // (INTERNET_ERROR_BASE + 24)
,ERROR_INTERNET_NO_CALLBACK ,STATUS_UNSUCCESSFUL // (INTERNET_ERROR_BASE + 25)
,ERROR_INTERNET_REQUEST_PENDING ,STATUS_PENDING // (INTERNET_ERROR_BASE + 26)
,ERROR_INTERNET_INCORRECT_FORMAT ,STATUS_INVALID_NETWORK_RESPONSE // (INTERNET_ERROR_BASE + 27)
,ERROR_INTERNET_ITEM_NOT_FOUND ,STATUS_OBJECT_PATH_NOT_FOUND // (INTERNET_ERROR_BASE + 28)
,ERROR_INTERNET_CANNOT_CONNECT ,STATUS_BAD_NETWORK_PATH // (INTERNET_ERROR_BASE + 29)
,ERROR_INTERNET_CONNECTION_ABORTED ,STATUS_REQUEST_ABORTED // (INTERNET_ERROR_BASE + 30)
,ERROR_INTERNET_CONNECTION_RESET ,STATUS_CONNECTION_RESET // (INTERNET_ERROR_BASE + 31)
,ERROR_INTERNET_FORCE_RETRY ,STATUS_RETRY // (INTERNET_ERROR_BASE + 32)
,ERROR_INTERNET_INVALID_PROXY_REQUEST ,STATUS_INVALID_PARAMETER // (INTERNET_ERROR_BASE + 33)
,ERROR_INTERNET_NEED_UI ,STATUS_ACCESS_DENIED // (INTERNET_ERROR_BASE + 34)
};
HTTP_TO_NTSTATUS_MAPPING rgHttpToNtstatus2[] = {
ERROR_HTTP_HEADER_NOT_FOUND ,STATUS_INVALID_NETWORK_RESPONSE // (INTERNET_ERROR_BASE + 150)
,ERROR_HTTP_DOWNLEVEL_SERVER ,STATUS_INVALID_NETWORK_RESPONSE // (INTERNET_ERROR_BASE + 151)
,ERROR_HTTP_INVALID_SERVER_RESPONSE ,STATUS_INVALID_NETWORK_RESPONSE // (INTERNET_ERROR_BASE + 152)
,ERROR_HTTP_INVALID_HEADER ,STATUS_INVALID_NETWORK_RESPONSE // (INTERNET_ERROR_BASE + 153)
,ERROR_HTTP_INVALID_QUERY_REQUEST ,STATUS_INVALID_PARAMETER // (INTERNET_ERROR_BASE + 154)
,ERROR_HTTP_HEADER_ALREADY_EXISTS ,STATUS_INVALID_PARAMETER // (INTERNET_ERROR_BASE + 155)
,ERROR_HTTP_REDIRECT_FAILED ,STATUS_HOST_UNREACHABLE // (INTERNET_ERROR_BASE + 156)
,ERROR_INTERNET_SECURITY_CHANNEL_ERROR ,STATUS_INTERNAL_ERROR // (INTERNET_ERROR_BASE + 157)
,ERROR_INTERNET_UNABLE_TO_CACHE_FILE ,STATUS_INTERNAL_ERROR // (INTERNET_ERROR_BASE + 158)
,ERROR_INTERNET_TCPIP_NOT_INSTALLED ,STATUS_INTERNAL_ERROR // (INTERNET_ERROR_BASE + 159)
,ERROR_HTTP_NOT_REDIRECTED ,STATUS_INTERNAL_ERROR // (INTERNET_ERROR_BASE + 160)
,ERROR_HTTP_COOKIE_NEEDS_CONFIRMATION ,STATUS_INTERNAL_ERROR // (INTERNET_ERROR_BASE + 161)
,ERROR_HTTP_COOKIE_DECLINED ,STATUS_INTERNAL_ERROR // (INTERNET_ERROR_BASE + 162)
,ERROR_INTERNET_DISCONNECTED ,STATUS_CONNECTION_DISCONNECTED // (INTERNET_ERROR_BASE + 163)
,ERROR_INTERNET_SERVER_UNREACHABLE ,STATUS_HOST_UNREACHABLE // (INTERNET_ERROR_BASE + 164)
,ERROR_INTERNET_PROXY_SERVER_UNREACHABLE ,STATUS_HOST_UNREACHABLE // (INTERNET_ERROR_BASE + 165)
,ERROR_INTERNET_BAD_AUTO_PROXY_SCRIPT ,STATUS_DEVICE_CONFIGURATION_ERROR// (INTERNET_ERROR_BASE + 166)
,ERROR_INTERNET_UNABLE_TO_DOWNLOAD_SCRIPT ,STATUS_INTERNAL_ERROR // (INTERNET_ERROR_BASE + 167)
,ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION ,STATUS_NETWORK_SESSION_EXPIRED // (INTERNET_ERROR_BASE + 168)
,ERROR_INTERNET_SEC_INVALID_CERT ,STATUS_ACCESS_DENIED // (INTERNET_ERROR_BASE + 169)
,ERROR_INTERNET_SEC_CERT_REVOKED ,STATUS_ACCESS_DENIED // (INTERNET_ERROR_BASE + 170)
};
WIN32_TO_NTSTATUS_MAPPING rgWin32ToNtStatus [] = {
ERROR_SUCCESS, STATUS_SUCCESS // 0L
,ERROR_INVALID_FUNCTION, STATUS_NOT_IMPLEMENTED // 1L
,ERROR_FILE_NOT_FOUND, STATUS_OBJECT_NAME_NOT_FOUND // 2L
,ERROR_PATH_NOT_FOUND, STATUS_OBJECT_PATH_NOT_FOUND // 3L
,ERROR_TOO_MANY_OPEN_FILES, STATUS_TOO_MANY_OPENED_FILES // 4L
,ERROR_ACCESS_DENIED, STATUS_ACCESS_DENIED // 5L
,ERROR_INVALID_HANDLE, STATUS_INVALID_HANDLE // 6L
,ERROR_ARENA_TRASHED, STATUS_UNSUCCESSFUL // 7L
,ERROR_NOT_ENOUGH_MEMORY, STATUS_INSUFFICIENT_RESOURCES // 8L
,ERROR_INVALID_BLOCK, STATUS_UNSUCCESSFUL // 9L
,ERROR_BAD_ENVIRONMENT, STATUS_UNSUCCESSFUL // 10L
,ERROR_BAD_FORMAT, STATUS_UNSUCCESSFUL // 11L
,ERROR_INVALID_ACCESS, STATUS_UNSUCCESSFUL // 12L
,ERROR_INVALID_DATA, STATUS_UNSUCCESSFUL // 13L
,ERROR_OUTOFMEMORY, STATUS_UNSUCCESSFUL // 14L
,ERROR_INVALID_DRIVE, STATUS_UNSUCCESSFUL // 15L
,ERROR_CURRENT_DIRECTORY, STATUS_UNSUCCESSFUL // 16L
,ERROR_NOT_SAME_DEVICE, STATUS_UNSUCCESSFUL // 17L
,ERROR_NO_MORE_FILES, STATUS_UNSUCCESSFUL // 18L
,ERROR_WRITE_PROTECT, STATUS_UNSUCCESSFUL // 19L
,ERROR_BAD_UNIT, STATUS_UNSUCCESSFUL // 20L
,ERROR_NOT_READY, STATUS_UNSUCCESSFUL // 21L
,ERROR_BAD_COMMAND, STATUS_UNSUCCESSFUL // 22L
,ERROR_CRC, STATUS_UNSUCCESSFUL // 23L
,ERROR_BAD_LENGTH, STATUS_UNSUCCESSFUL // 24L
,ERROR_SEEK, STATUS_UNSUCCESSFUL // 25L
,ERROR_NOT_DOS_DISK, STATUS_UNSUCCESSFUL // 26L
,ERROR_SECTOR_NOT_FOUND, STATUS_UNSUCCESSFUL // 27L
,ERROR_OUT_OF_PAPER, STATUS_UNSUCCESSFUL // 28L
,ERROR_WRITE_FAULT, STATUS_UNSUCCESSFUL // 29L
,ERROR_READ_FAULT, STATUS_UNSUCCESSFUL // 30L
,ERROR_GEN_FAILURE, STATUS_UNSUCCESSFUL // 31L
,ERROR_SHARING_VIOLATION, STATUS_SHARING_VIOLATION // 32L
,ERROR_LOCK_VIOLATION, STATUS_LOCK_NOT_GRANTED // 33L
,ERROR_WRONG_DISK, STATUS_UNSUCCESSFUL // 34L
,0,0 // 35L
,ERROR_SHARING_BUFFER_EXCEEDED, STATUS_UNSUCCESSFUL // 36L
,0,0 // 37L
,ERROR_HANDLE_EOF, STATUS_END_OF_FILE // 38L
,ERROR_HANDLE_DISK_FULL, STATUS_UNSUCCESSFUL // 39L
};
//
// Implementation of functions begins here.
//
DWORD
ReadDWord(
HKEY KeyHandle,
LPTSTR lpValueName,
DWORD DefaultValue
)
/*++
Routine Description:
Read a DWORD value from the registry. If there is a problem then
return the default value.
Arguments:
KeyHandle - Handle of the key (value) being read.
lpValueName - The value name.
DefaultValue - The default value to return, if the name does not exists as
a value of the key handle.
Return Value:
Win32 error status.
--*/
{
DWORD Value;
DWORD ValueSize = sizeof(Value);
DWORD ValueType;
if ((KeyHandle) &&
(RegQueryValueEx(KeyHandle,
lpValueName,
0,
&ValueType,
(PUCHAR)&Value,
&ValueSize ) == ERROR_SUCCESS )) {
return Value;
} else {
return DefaultValue;
}
}
VOID
UpdateServiceStatus (
DWORD dwState
)
/*++
Routine Description:
This routines updates the service status.
Arguments:
dwState - The state the service has to be updated to.
Return Value:
none.
--*/
{
if (g_registeredService) {
ASSERT (g_hStatus);
g_status.dwCurrentState = dwState;
SetServiceStatus(g_hStatus, &g_status);
} else {
g_status.dwCurrentState = dwState;
}
}
NET_API_STATUS
WsLoadRedir(
VOID
)
/*++
Routine Description:
This loads, starts, and configures the kernel mini-redir. If the redir
is already loaded or started, it is not a fatal error.
Arguments:
none.
Return Value:
Win32 error status.
--*/
{
NET_API_STATUS err = ERROR_SUCCESS;
NTSTATUS NtStatus = STATUS_SUCCESS;
UNICODE_STRING DeviceName;
IO_STATUS_BLOCK IoStatusBlock;
OBJECT_ATTRIBUTES ObjectAttributes;
BOOL driverAlreadyLoaded = FALSE;
err = WsLoadDriver(DAVCLIENT_DRIVER);
if (err == ERROR_SERVICE_ALREADY_RUNNING) {
driverAlreadyLoaded = TRUE;
err = ERROR_SUCCESS;
}
if (err != ERROR_SUCCESS) {
DavPrint((DEBUG_ERRORS,
"WsLoadRedir/WsLoadDriver: Error Val = %08lx.\n", err));
return err;
}
//
// Open the redirector device.
//
RtlInitUnicodeString(&(DeviceName), DD_DAV_DEVICE_NAME_U);
InitializeObjectAttributes(&(ObjectAttributes),
&(DeviceName),
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
NtStatus = NtOpenFile(&(DavRedirDeviceHandle),
SYNCHRONIZE,
&(ObjectAttributes),
&(IoStatusBlock),
FILE_SHARE_VALID_FLAGS,
FILE_SYNCHRONOUS_IO_NONALERT);
if (NtStatus != STATUS_SUCCESS) {
DavPrint((DEBUG_ERRORS, "WsLoadRedir/NtOpenFile: Error Val = %08lx\n", NtStatus));
DavRedirDeviceHandle = INVALID_HANDLE_VALUE;
return RtlNtStatusToDosError(NtStatus);
}
return ERROR_SUCCESS;
}
NET_API_STATUS
WsUnloadRedir(
VOID
)
/*++
Routine Description:
This routine unloads the DAV driver. Calls the NtUnloadDriver function.
Arguments:
none.
Return Value:
Win32 error status.
--*/
{
LPWSTR DriverRegistryName;
ULONG Privileges[1], DriverRegistryNameLength;
UNICODE_STRING DriverRegistryString;
NET_API_STATUS Status;
NTSTATUS ntstatus = STATUS_SUCCESS;
DriverRegistryNameLength = sizeof(SERVICE_REGISTRY_KEY);
DriverRegistryNameLength += sizeof(DAVCLIENT_DRIVER);
//
// We need to make the DriverRegistryNameLength a multiple of 8. This is
// because DavAllocateMemory calls DebugAlloc which does some stuff which
// requires this. The equation below does this.
//
DriverRegistryNameLength = ( ( ( DriverRegistryNameLength + 7 ) / 8 ) * 8 );
DriverRegistryName = (LPWSTR) DavAllocateMemory(DriverRegistryNameLength);
if (DriverRegistryName == NULL) {
return ERROR_NOT_ENOUGH_MEMORY;
}
Privileges[0] = SE_LOAD_DRIVER_PRIVILEGE;
Status = NetpGetPrivilege(1, Privileges);
if (Status != NERR_Success) {
DavFreeMemory(DriverRegistryName);
return Status;
}
if (DavRedirDeviceHandle != INVALID_HANDLE_VALUE) {
NtClose(DavRedirDeviceHandle);
DavRedirDeviceHandle = INVALID_HANDLE_VALUE;
}
wcscpy(DriverRegistryName, SERVICE_REGISTRY_KEY);
wcscat(DriverRegistryName, DAVCLIENT_DRIVER);
RtlInitUnicodeString(&(DriverRegistryString), DriverRegistryName);
// Webclient should not unload the MRxDAV if it does not load it.
DavFreeMemory(DriverRegistryName);
NetpReleasePrivilege();
return(WsMapStatus(ntstatus));
}
NET_API_STATUS
WsLoadDriver(
IN LPWSTR DriverNameString
)
/*++
Routine Description:
This routine loads the DAV driver. Calls the NtLoadDriver function.
Arguments:
none.
Return Value:
Win32 error status.
--*/
{
LPWSTR DriverRegistryName;
ULONG Privileges[1], DriverRegistryNameLength;
UNICODE_STRING DriverRegistryString;
NET_API_STATUS Status;
NTSTATUS ntstatus = STATUS_SUCCESS;
DriverRegistryNameLength = sizeof(SERVICE_REGISTRY_KEY);
DriverRegistryNameLength += ( wcslen(DriverNameString) * sizeof(WCHAR) );
//
// We need to make the DriverRegistryNameLength a multiple of 8. This is
// because DavAllocateMemory calls DebugAlloc which does some stuff which
// requires this. The equation below does this.
//
DriverRegistryNameLength = ( ( ( DriverRegistryNameLength + 7 ) / 8 ) * 8 );
DriverRegistryName = (LPWSTR) DavAllocateMemory(DriverRegistryNameLength);
if (DriverRegistryName == NULL) {
DavPrint((DEBUG_ERRORS, "WsLoadDriver/DavAllocateMemory.\n"));
return ERROR_NOT_ENOUGH_MEMORY;
}
Privileges[0] = SE_LOAD_DRIVER_PRIVILEGE;
Status = NetpGetPrivilege(1, Privileges);
if (Status != NERR_Success) {
DavPrint((DEBUG_ERRORS, "WsLoadDriver/NetpGetPrivilege.\n"));
DavFreeMemory(DriverRegistryName);
return Status;
}
wcscpy(DriverRegistryName, SERVICE_REGISTRY_KEY);
wcscat(DriverRegistryName, DriverNameString);
RtlInitUnicodeString(&(DriverRegistryString), DriverRegistryName);
//
// Webclient becomes a LocalService and can no longer load the MRxDAV.
// We make MRxDAV as a depend service of Webclient. Svchost will load it.
//
NetpReleasePrivilege();
DavFreeMemory(DriverRegistryName);
if (ntstatus != STATUS_SUCCESS && ntstatus != STATUS_IMAGE_ALREADY_LOADED) {
LPWSTR subString[1];
subString[0] = DriverNameString;
DavPrint((DEBUG_ERRORS,
"WsLoadDriver/NtLoadDriver. NtStatus = %08lx\n", ntstatus));
#if 0
DavReportEventW(NELOG_DriverNotLoaded,
EVENTLOG_ERROR_TYPE,
1,
sizeof(NTSTATUS),
subString,
&ntstatus);
#endif
}
return(WsMapStatus(ntstatus));
}
NET_API_STATUS
WsMapStatus(
IN NTSTATUS NtStatus
)
/*++
Routine Description:
This function takes an NT status code and maps it to the appropriate
error code expected from calling a LAN Man API.
Arguments:
NtStatus - Supplies the NT status.
Return Value:
Returns the appropriate LAN Man error code for the NT status.
--*/
{
//
// A small optimization for the most common case.
//
if (NtStatus == STATUS_SUCCESS) {
return NERR_Success;
}
switch (NtStatus) {
case STATUS_OBJECT_NAME_COLLISION:
return ERROR_ALREADY_ASSIGNED;
case STATUS_ACCESS_DENIED:
return ERROR_ACCESS_DENIED;
case STATUS_OBJECT_NAME_NOT_FOUND:
return NERR_UseNotFound;
case STATUS_IMAGE_ALREADY_LOADED:
case STATUS_REDIRECTOR_STARTED:
return ERROR_SERVICE_ALREADY_RUNNING;
case STATUS_REDIRECTOR_HAS_OPEN_HANDLES:
return ERROR_REDIRECTOR_HAS_OPEN_HANDLES;
default:
return NetpNtStatusToApiStatus(NtStatus);
}
}
NTSTATUS
DavMapErrorToNtStatus(
DWORD dwWin32Error
)
/*++
Routine Description:
This function takes an errorcode which is either a WinInet error code or
a or a Win32 error code and converts it into an NTSTATUS value. It does the
following in the order mentioned below:
1. Checks to see if the error code is a WinInet error code and if it is
maps that to an NTSTATUS value. If not,
2. Assumes that this is a Win32 error code and maps that to an NTSTATUS
value.
Arguments:
dwWin32Error - The win32 or wininet error code.
Return Value:
Returns the most appropriate NtStatus value.
--*/
{
int indexLast;
DavPrint((DEBUG_MISC,
"DavMapErrorToNtstatus. dwWin32Error = %08lx\n", dwWin32Error));
//
// Check if its a WinInet error.
//
if (dwWin32Error > INTERNET_ERROR_BASE && dwWin32Error <= INTERNET_ERROR_LAST) {
indexLast = ( ( sizeof(rgHttpToNtstatus1) / sizeof(HTTP_TO_NTSTATUS_MAPPING) ) - 1 );
if (dwWin32Error >= rgHttpToNtstatus1[0].dwHttpError &&
dwWin32Error <= rgHttpToNtstatus1[indexLast].dwHttpError) {
return rgHttpToNtstatus1[dwWin32Error-rgHttpToNtstatus1[0].dwHttpError].Status;
}
indexLast = ( ( sizeof(rgHttpToNtstatus2) / sizeof(HTTP_TO_NTSTATUS_MAPPING) ) - 1 );
if (dwWin32Error >= rgHttpToNtstatus2[0].dwHttpError &&
dwWin32Error <= rgHttpToNtstatus2[indexLast].dwHttpError) {
return rgHttpToNtstatus2[dwWin32Error-rgHttpToNtstatus2[0].dwHttpError].Status;
}
} else if (dwWin32Error >= (DWORD)HTTP_STATUS_FIRST && dwWin32Error <= (DWORD)HTTP_STATUS_LAST) {
#if 0
//
// IMPORTANT!!!
// We don't check for Http error codes here. This mapping is done in
// the DavMapHttpErrorToDosError function. The functions expecting a
// Http response should call DavQueryAndParseResponse function.
//
//
// Check if its a HTTP error code.
//
switch (dwWin32Error) {
case HTTP_STATUS_CONTINUE: // 100 OK to continue with request
return STATUS_SUCCESS;
case HTTP_STATUS_SWITCH_PROTOCOLS: // 101 server has switched protocols in upgrade header
return STATUS_DEVICE_PROTOCOL_ERROR;
case HTTP_STATUS_OK: // 200 // request completed
case HTTP_STATUS_CREATED: // 201 // object created, reason = new URI
case HTTP_STATUS_ACCEPTED: // 202 // async completion (TBS)
case HTTP_STATUS_PARTIAL: // 203 // partial completion
case HTTP_STATUS_NO_CONTENT: // 204 // no info to return
case HTTP_STATUS_RESET_CONTENT: // 205 // request completed, but clear form
case HTTP_STATUS_PARTIAL_CONTENT: // 206 // partial GET furfilled
case DAV_MULTI_STATUS: // 207 // multi status response
return STATUS_SUCCESS;
case HTTP_STATUS_AMBIGUOUS: // 300 // server couldn't decide what to return
return STATUS_UNSUCCESSFUL;
case HTTP_STATUS_MOVED: // 301 // object permanently moved
return STATUS_OBJECT_NAME_NOT_FOUND;
case HTTP_STATUS_REDIRECT:
return STATUS_OBJECT_NAME_NOT_FOUND; // 302 // object temporarily moved
case HTTP_STATUS_REDIRECT_METHOD:
return STATUS_OBJECT_NAME_NOT_FOUND; // 303 // redirection w/ new access method
case HTTP_STATUS_NOT_MODIFIED:
return STATUS_SUCCESS; // 304 // if-modified-since was not modified
case HTTP_STATUS_USE_PROXY:
return STATUS_HOST_UNREACHABLE; // 305 // redirection to proxy, location header specifies proxy to use
case HTTP_STATUS_REDIRECT_KEEP_VERB:
return STATUS_SUCCESS; // 307 // HTTP/1.1: keep same verb
case HTTP_STATUS_BAD_REQUEST: // 400 // invalid syntax
return STATUS_INVALID_PARAMETER;
case HTTP_STATUS_DENIED: // 401 // access denied
return STATUS_ACCESS_DENIED;
case HTTP_STATUS_PAYMENT_REQ: // 402 // payment required
return STATUS_ACCESS_DENIED;
case HTTP_STATUS_FORBIDDEN: // 403 // request forbidden
return STATUS_ACCESS_DENIED;
case HTTP_STATUS_NOT_FOUND: // 404 // object not found
return STATUS_OBJECT_NAME_NOT_FOUND;
case HTTP_STATUS_BAD_METHOD: // 405 // method is not allowed
return STATUS_ACCESS_DENIED;
case HTTP_STATUS_NONE_ACCEPTABLE: // 406 // no response acceptable to client found
return STATUS_ACCESS_DENIED;
case HTTP_STATUS_PROXY_AUTH_REQ: // 407 // proxy authentication required
return STATUS_ACCESS_DENIED;
case HTTP_STATUS_REQUEST_TIMEOUT: // 408 // server timed out waiting for request
return STATUS_IO_TIMEOUT;
case HTTP_STATUS_CONFLICT: // 409 // user should resubmit with more info
return STATUS_INVALID_PARAMETER;
case HTTP_STATUS_GONE: // 410 // the resource is no longer available
return STATUS_OBJECT_NAME_NOT_FOUND;
case HTTP_STATUS_LENGTH_REQUIRED: // 411 // the server refused to accept request w/o a length
return STATUS_INVALID_PARAMETER;
case HTTP_STATUS_PRECOND_FAILED: // 412 // precondition given in request failed
return STATUS_INVALID_PARAMETER;
case HTTP_STATUS_REQUEST_TOO_LARGE: // 413 // request entity was too large
return STATUS_INVALID_PARAMETER;
case HTTP_STATUS_URI_TOO_LONG: // 414 // request URI too long
return STATUS_INVALID_PARAMETER;
case HTTP_STATUS_UNSUPPORTED_MEDIA: // 415 // unsupported media type
return STATUS_INVALID_PARAMETER;
case HTTP_STATUS_RETRY_WITH: // 449 // retry after doing the appropriate action.
return STATUS_RETRY;
case HTTP_STATUS_SERVER_ERROR: // 500 // internal server error
return STATUS_UNSUCCESSFUL;
case HTTP_STATUS_NOT_SUPPORTED: // 501 // required not supported
return STATUS_NOT_SUPPORTED;
case HTTP_STATUS_BAD_GATEWAY: // 502 // error response received from gateway
return STATUS_HOST_UNREACHABLE;
case HTTP_STATUS_SERVICE_UNAVAIL: // 503 // temporarily overloaded
return STATUS_UNSUCCESSFUL;
case HTTP_STATUS_GATEWAY_TIMEOUT: // 504 // timed out waiting for gateway
return STATUS_HOST_UNREACHABLE;
case HTTP_STATUS_VERSION_NOT_SUP: // 505 // HTTP version not supported
return STATUS_NOT_SUPPORTED;
//
// WebDav specific status codes.
//
case DAV_STATUS_INSUFFICIENT_STORAGE: // 507
return STATUS_DISK_FULL;
case DAV_STATUS_UNPROCESSABLE_ENTITY: // 422
return STATUS_INVALID_PARAMETER;
case DAV_STATUS_LOCKED: // 423
return STATUS_ACCESS_DENIED;
case DAV_STATUS_FAILED_DEPENDENCY: // 424
return STATUS_INVALID_PARAMETER;
default:
break;
}
#endif
}
//
// If none of the above match call this function which takes a Win32 error
// and maps it to an NTSTATUS value.
//
return DavDosErrorToNtStatus(dwWin32Error);
}
NTSTATUS
DavDosErrorToNtStatus(
DWORD dwError
)
/*++
Routine Description:
This function takes a win32 error code and converts to the closes NTSTATUS.
As NTSTATUS->Win32Error is many to one mapping, there is a possible loss of
precision in this method of error reporting.
Arguments:
dwError - The win32 error code.
Return Value:
Returns the most appropriate NTSTATUS
--*/
{
if (dwError < sizeof(rgWin32ToNtStatus)/sizeof(WIN32_TO_NTSTATUS_MAPPING)) {
return rgWin32ToNtStatus[dwError].NtStatus;
} else {
switch (dwError) {
case ERROR_BUFFER_OVERFLOW:
return STATUS_BUFFER_OVERFLOW;
case ERROR_NOT_SUPPORTED:
return STATUS_NOT_SUPPORTED;
case ERROR_DISK_FULL:
return STATUS_DISK_FULL;
case ERROR_FILE_EXISTS:
return STATUS_OBJECT_NAME_EXISTS;
case ERROR_INVALID_PASSWORD:
return STATUS_WRONG_PASSWORD;
case ERROR_INVALID_PARAMETER:
return STATUS_INVALID_PARAMETER;
case ERROR_BAD_NETPATH:
return STATUS_BAD_NETWORK_PATH;
case ERROR_CALL_NOT_IMPLEMENTED:
return STATUS_NOT_IMPLEMENTED;
case ERROR_SEM_TIMEOUT:
return STATUS_IO_TIMEOUT;
case ERROR_INSUFFICIENT_BUFFER:
return STATUS_BUFFER_TOO_SMALL;
case ERROR_INVALID_NAME:
return STATUS_OBJECT_NAME_INVALID;
case ERROR_DIR_NOT_EMPTY:
return STATUS_DIRECTORY_NOT_EMPTY;
case ERROR_BUSY:
return STATUS_DEVICE_BUSY;
case ERROR_ALREADY_EXISTS:
return STATUS_OBJECT_NAME_COLLISION;
case ERROR_DIRECTORY:
return STATUS_NOT_A_DIRECTORY;
case ERROR_OPERATION_ABORTED:
return STATUS_CANCELLED;
case ERROR_IO_PENDING:
return STATUS_PENDING;
case ERROR_NOACCESS:
return ERROR_ACCESS_DENIED;
case ERROR_NOT_FOUND:
return STATUS_OBJECT_NAME_NOT_FOUND;
case ERROR_NO_MATCH:
return STATUS_OBJECT_NAME_NOT_FOUND;
case ERROR_CANCELLED:
return STATUS_CANCELLED;
case ERROR_RETRY:
return STATUS_RETRY;
case STATUS_NOT_A_DIRECTORY:
return STATUS_NOT_A_DIRECTORY;
case STATUS_FILE_IS_A_DIRECTORY:
return STATUS_FILE_IS_A_DIRECTORY;
case ERROR_NOT_ENOUGH_QUOTA:
return STATUS_QUOTA_EXCEEDED;
case ERROR_SESSION_CREDENTIAL_CONFLICT:
return STATUS_NETWORK_CREDENTIAL_CONFLICT;
default:
DavPrint((DEBUG_ERRORS, "DavDosErrorToNtStatus: dwError = %d\n", dwError));
return STATUS_UNSUCCESSFUL;
}
}
}
// #define FIND_FLAGS_RETRIEVE_ONLY_STRUCT_INFO 0x2
DWORD
DavrGetDiskSpaceUsage(
IN handle_t dav_binding_h,
LPWSTR lptzLocation,
LONG lLenIn,
LONG *lplReturnLen,
ULARGE_INTEGER *lpMaxSpace,
ULARGE_INTEGER *lpUsedSpace
)
/*++
Routine Description:
Finds out the amount of disk being consumed by wininet urlcache due to Webdav
Arguments:
dav_binding_h - The explicit RPC binding handle.
dwSize - Size of the cache location buffer. On return this will contain the actual size of the
location string.
lptzLocation - Buffer to return Cache location string. As much of the location string as can fit
in the buffer is returned
lpdwReturnSize
lpMaxSpace - Size of disk Quota set for webdav
lpUsedSpace - Size of disk consumed by the urlcache used by webdav
Return Value:
Win32 error code
--*/
{
// iterate through the cache to discover the actual size.
INTERNET_CACHE_CONFIG_INFOW sConfigW;
DWORD dwSize = sizeof(sConfigW), dwError = ERROR_SUCCESS;
BOOL fResult = FALSE;
// should atleass have enough space for a drive letter
if (lLenIn < 3)
{
return ERROR_INVALID_PARAMETER;
}
try
{
sConfigW.dwContainer = 0;
sConfigW.dwStructSize = sizeof(sConfigW);
if (GetUrlCacheConfigInfoW(&sConfigW, &dwSize, CACHE_CONFIG_DISK_CACHE_PATHS_FC |
CACHE_CONFIG_QUOTA_FC |
CACHE_CONFIG_CONTENT_USAGE_FC |
CACHE_CONFIG_STICKY_CONTENT_USAGE_FC))
{
*(ULONGLONG *)lpMaxSpace = (ULONGLONG)(sConfigW.dwQuota) * 1024;
*(ULONGLONG *)lpUsedSpace = (ULONGLONG)(sConfigW.dwNormalUsage+sConfigW.dwExemptUsage) * 1024;
memset(lptzLocation, 0, lLenIn * sizeof(WCHAR));
*lplReturnLen = wcslen(sConfigW.CachePath);
if (*lplReturnLen < lLenIn)
{
// We have enough buffer
memcpy(lptzLocation, sConfigW.CachePath, *lplReturnLen * sizeof(WCHAR));
}
else
{
// We don't have enough buffer, we copy as much as we can
memcpy(lptzLocation, sConfigW.CachePath, lLenIn * sizeof(WCHAR));
}
}
else
{
dwError = GetLastError();
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
dwError = ERROR_INVALID_PARAMETER;
}
return dwError;
}
DWORD
DavrFreeUsedDiskSpace(
IN handle_t dav_binding_h,
DWORD dwPercent
)
/*++
Routine Description:
Frees up dwPercent of the urlcache used by webdav
Arguments:
dav_binding_h - The explicit RPC binding handle.
dwPercent - % of used space to be freed
Return Value:
Win32 error code
--*/
{
DWORD dwError = ERROR_SUCCESS;
if (dwPercent <= 100)
{
if (!FreeUrlCacheSpaceA(NULL, dwPercent, 0))
{
dwError = GetLastError();
}
}
else
{
dwError = ERROR_INVALID_PARAMETER;
}
return dwError;
}