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

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. utils.c
  5. Abstract:
  6. Grab bag of functions used by the web dav mini-redir client service.
  7. Author:
  8. Andy Herron (andyhe) 29-Mar-1999
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. --*/
  13. #include "pch.h"
  14. #pragma hdrstop
  15. #include <ntumrefl.h>
  16. #include <usrmddav.h>
  17. #include "global.h"
  18. //
  19. // These tables translate wininet codes to the closest ntstatus codes. There are
  20. // two because there are some errors in wininet which come from ftp and gopher
  21. // which are not relevant to us.
  22. //
  23. typedef struct tagHTTP_TO_NTSTATUS_MAPPING {
  24. DWORD dwHttpError;
  25. NTSTATUS Status;
  26. } HTTP_TO_NTSTATUS_MAPPING;
  27. typedef struct tagWIN32_TO_NTSTATUS_MAPPING {
  28. DWORD dwWin32Error;
  29. NTSTATUS NtStatus;
  30. } WIN32_TO_NTSTATUS_MAPPING;
  31. HTTP_TO_NTSTATUS_MAPPING rgHttpToNtstatus1[] = {
  32. ERROR_INTERNET_OUT_OF_HANDLES ,STATUS_INSUFFICIENT_RESOURCES // (INTERNET_ERROR_BASE + 1)
  33. ,ERROR_INTERNET_TIMEOUT ,STATUS_BAD_NETWORK_PATH // (INTERNET_ERROR_BASE + 2)
  34. ,ERROR_INTERNET_EXTENDED_ERROR ,STATUS_UNSUCCESSFUL // (INTERNET_ERROR_BASE + 3)
  35. ,ERROR_INTERNET_INTERNAL_ERROR ,STATUS_INTERNAL_ERROR // (INTERNET_ERROR_BASE + 4)
  36. ,ERROR_INTERNET_INVALID_URL ,STATUS_OBJECT_NAME_INVALID // (INTERNET_ERROR_BASE + 5)
  37. ,ERROR_INTERNET_UNRECOGNIZED_SCHEME ,STATUS_OBJECT_NAME_INVALID // (INTERNET_ERROR_BASE + 6)
  38. ,ERROR_INTERNET_NAME_NOT_RESOLVED ,STATUS_BAD_NETWORK_PATH // (INTERNET_ERROR_BASE + 7)
  39. ,ERROR_INTERNET_PROTOCOL_NOT_FOUND ,STATUS_OBJECT_TYPE_MISMATCH // (INTERNET_ERROR_BASE + 8)
  40. ,ERROR_INTERNET_INVALID_OPTION ,STATUS_INVALID_PARAMETER // (INTERNET_ERROR_BASE + 9)
  41. ,ERROR_INTERNET_BAD_OPTION_LENGTH ,STATUS_INVALID_PARAMETER // (INTERNET_ERROR_BASE + 10)
  42. ,ERROR_INTERNET_OPTION_NOT_SETTABLE ,STATUS_INVALID_PARAMETER // (INTERNET_ERROR_BASE + 11)
  43. ,ERROR_INTERNET_SHUTDOWN ,STATUS_UNSUCCESSFUL // (INTERNET_ERROR_BASE + 12)
  44. ,ERROR_INTERNET_INCORRECT_USER_NAME ,STATUS_LOGON_FAILURE // (INTERNET_ERROR_BASE + 13)
  45. ,ERROR_INTERNET_INCORRECT_PASSWORD ,STATUS_LOGON_FAILURE // (INTERNET_ERROR_BASE + 14)
  46. ,ERROR_INTERNET_LOGIN_FAILURE ,STATUS_LOGON_FAILURE // (INTERNET_ERROR_BASE + 15)
  47. ,ERROR_INTERNET_INVALID_OPERATION ,STATUS_INVALID_DEVICE_REQUEST // (INTERNET_ERROR_BASE + 16)
  48. ,ERROR_INTERNET_OPERATION_CANCELLED ,STATUS_CANCELLED // (INTERNET_ERROR_BASE + 17)
  49. ,ERROR_INTERNET_INCORRECT_HANDLE_TYPE ,STATUS_INVALID_HANDLE // (INTERNET_ERROR_BASE + 18)
  50. ,ERROR_INTERNET_INCORRECT_HANDLE_STATE ,STATUS_INVALID_HANDLE // (INTERNET_ERROR_BASE + 19)
  51. ,ERROR_INTERNET_NOT_PROXY_REQUEST ,STATUS_INVALID_PARAMETER // (INTERNET_ERROR_BASE + 20)
  52. ,ERROR_INTERNET_REGISTRY_VALUE_NOT_FOUND ,STATUS_OBJECT_NAME_NOT_FOUND // (INTERNET_ERROR_BASE + 21)
  53. ,ERROR_INTERNET_BAD_REGISTRY_PARAMETER ,STATUS_INVALID_PARAMETER // (INTERNET_ERROR_BASE + 22)
  54. ,ERROR_INTERNET_NO_DIRECT_ACCESS ,STATUS_UNSUCCESSFUL // (INTERNET_ERROR_BASE + 23)
  55. ,ERROR_INTERNET_NO_CONTEXT ,STATUS_UNSUCCESSFUL // (INTERNET_ERROR_BASE + 24)
  56. ,ERROR_INTERNET_NO_CALLBACK ,STATUS_UNSUCCESSFUL // (INTERNET_ERROR_BASE + 25)
  57. ,ERROR_INTERNET_REQUEST_PENDING ,STATUS_PENDING // (INTERNET_ERROR_BASE + 26)
  58. ,ERROR_INTERNET_INCORRECT_FORMAT ,STATUS_INVALID_NETWORK_RESPONSE // (INTERNET_ERROR_BASE + 27)
  59. ,ERROR_INTERNET_ITEM_NOT_FOUND ,STATUS_OBJECT_PATH_NOT_FOUND // (INTERNET_ERROR_BASE + 28)
  60. ,ERROR_INTERNET_CANNOT_CONNECT ,STATUS_BAD_NETWORK_PATH // (INTERNET_ERROR_BASE + 29)
  61. ,ERROR_INTERNET_CONNECTION_ABORTED ,STATUS_REQUEST_ABORTED // (INTERNET_ERROR_BASE + 30)
  62. ,ERROR_INTERNET_CONNECTION_RESET ,STATUS_CONNECTION_RESET // (INTERNET_ERROR_BASE + 31)
  63. ,ERROR_INTERNET_FORCE_RETRY ,STATUS_RETRY // (INTERNET_ERROR_BASE + 32)
  64. ,ERROR_INTERNET_INVALID_PROXY_REQUEST ,STATUS_INVALID_PARAMETER // (INTERNET_ERROR_BASE + 33)
  65. ,ERROR_INTERNET_NEED_UI ,STATUS_ACCESS_DENIED // (INTERNET_ERROR_BASE + 34)
  66. };
  67. HTTP_TO_NTSTATUS_MAPPING rgHttpToNtstatus2[] = {
  68. ERROR_HTTP_HEADER_NOT_FOUND ,STATUS_INVALID_NETWORK_RESPONSE // (INTERNET_ERROR_BASE + 150)
  69. ,ERROR_HTTP_DOWNLEVEL_SERVER ,STATUS_INVALID_NETWORK_RESPONSE // (INTERNET_ERROR_BASE + 151)
  70. ,ERROR_HTTP_INVALID_SERVER_RESPONSE ,STATUS_INVALID_NETWORK_RESPONSE // (INTERNET_ERROR_BASE + 152)
  71. ,ERROR_HTTP_INVALID_HEADER ,STATUS_INVALID_NETWORK_RESPONSE // (INTERNET_ERROR_BASE + 153)
  72. ,ERROR_HTTP_INVALID_QUERY_REQUEST ,STATUS_INVALID_PARAMETER // (INTERNET_ERROR_BASE + 154)
  73. ,ERROR_HTTP_HEADER_ALREADY_EXISTS ,STATUS_INVALID_PARAMETER // (INTERNET_ERROR_BASE + 155)
  74. ,ERROR_HTTP_REDIRECT_FAILED ,STATUS_HOST_UNREACHABLE // (INTERNET_ERROR_BASE + 156)
  75. ,ERROR_INTERNET_SECURITY_CHANNEL_ERROR ,STATUS_INTERNAL_ERROR // (INTERNET_ERROR_BASE + 157)
  76. ,ERROR_INTERNET_UNABLE_TO_CACHE_FILE ,STATUS_INTERNAL_ERROR // (INTERNET_ERROR_BASE + 158)
  77. ,ERROR_INTERNET_TCPIP_NOT_INSTALLED ,STATUS_INTERNAL_ERROR // (INTERNET_ERROR_BASE + 159)
  78. ,ERROR_HTTP_NOT_REDIRECTED ,STATUS_INTERNAL_ERROR // (INTERNET_ERROR_BASE + 160)
  79. ,ERROR_HTTP_COOKIE_NEEDS_CONFIRMATION ,STATUS_INTERNAL_ERROR // (INTERNET_ERROR_BASE + 161)
  80. ,ERROR_HTTP_COOKIE_DECLINED ,STATUS_INTERNAL_ERROR // (INTERNET_ERROR_BASE + 162)
  81. ,ERROR_INTERNET_DISCONNECTED ,STATUS_CONNECTION_DISCONNECTED // (INTERNET_ERROR_BASE + 163)
  82. ,ERROR_INTERNET_SERVER_UNREACHABLE ,STATUS_HOST_UNREACHABLE // (INTERNET_ERROR_BASE + 164)
  83. ,ERROR_INTERNET_PROXY_SERVER_UNREACHABLE ,STATUS_HOST_UNREACHABLE // (INTERNET_ERROR_BASE + 165)
  84. ,ERROR_INTERNET_BAD_AUTO_PROXY_SCRIPT ,STATUS_DEVICE_CONFIGURATION_ERROR// (INTERNET_ERROR_BASE + 166)
  85. ,ERROR_INTERNET_UNABLE_TO_DOWNLOAD_SCRIPT ,STATUS_INTERNAL_ERROR // (INTERNET_ERROR_BASE + 167)
  86. ,ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION ,STATUS_NETWORK_SESSION_EXPIRED // (INTERNET_ERROR_BASE + 168)
  87. ,ERROR_INTERNET_SEC_INVALID_CERT ,STATUS_ACCESS_DENIED // (INTERNET_ERROR_BASE + 169)
  88. ,ERROR_INTERNET_SEC_CERT_REVOKED ,STATUS_ACCESS_DENIED // (INTERNET_ERROR_BASE + 170)
  89. };
  90. WIN32_TO_NTSTATUS_MAPPING rgWin32ToNtStatus [] = {
  91. ERROR_SUCCESS, STATUS_SUCCESS // 0L
  92. ,ERROR_INVALID_FUNCTION, STATUS_NOT_IMPLEMENTED // 1L
  93. ,ERROR_FILE_NOT_FOUND, STATUS_OBJECT_NAME_NOT_FOUND // 2L
  94. ,ERROR_PATH_NOT_FOUND, STATUS_OBJECT_PATH_NOT_FOUND // 3L
  95. ,ERROR_TOO_MANY_OPEN_FILES, STATUS_TOO_MANY_OPENED_FILES // 4L
  96. ,ERROR_ACCESS_DENIED, STATUS_ACCESS_DENIED // 5L
  97. ,ERROR_INVALID_HANDLE, STATUS_INVALID_HANDLE // 6L
  98. ,ERROR_ARENA_TRASHED, STATUS_UNSUCCESSFUL // 7L
  99. ,ERROR_NOT_ENOUGH_MEMORY, STATUS_INSUFFICIENT_RESOURCES // 8L
  100. ,ERROR_INVALID_BLOCK, STATUS_UNSUCCESSFUL // 9L
  101. ,ERROR_BAD_ENVIRONMENT, STATUS_UNSUCCESSFUL // 10L
  102. ,ERROR_BAD_FORMAT, STATUS_UNSUCCESSFUL // 11L
  103. ,ERROR_INVALID_ACCESS, STATUS_UNSUCCESSFUL // 12L
  104. ,ERROR_INVALID_DATA, STATUS_UNSUCCESSFUL // 13L
  105. ,ERROR_OUTOFMEMORY, STATUS_UNSUCCESSFUL // 14L
  106. ,ERROR_INVALID_DRIVE, STATUS_UNSUCCESSFUL // 15L
  107. ,ERROR_CURRENT_DIRECTORY, STATUS_UNSUCCESSFUL // 16L
  108. ,ERROR_NOT_SAME_DEVICE, STATUS_UNSUCCESSFUL // 17L
  109. ,ERROR_NO_MORE_FILES, STATUS_UNSUCCESSFUL // 18L
  110. ,ERROR_WRITE_PROTECT, STATUS_UNSUCCESSFUL // 19L
  111. ,ERROR_BAD_UNIT, STATUS_UNSUCCESSFUL // 20L
  112. ,ERROR_NOT_READY, STATUS_UNSUCCESSFUL // 21L
  113. ,ERROR_BAD_COMMAND, STATUS_UNSUCCESSFUL // 22L
  114. ,ERROR_CRC, STATUS_UNSUCCESSFUL // 23L
  115. ,ERROR_BAD_LENGTH, STATUS_UNSUCCESSFUL // 24L
  116. ,ERROR_SEEK, STATUS_UNSUCCESSFUL // 25L
  117. ,ERROR_NOT_DOS_DISK, STATUS_UNSUCCESSFUL // 26L
  118. ,ERROR_SECTOR_NOT_FOUND, STATUS_UNSUCCESSFUL // 27L
  119. ,ERROR_OUT_OF_PAPER, STATUS_UNSUCCESSFUL // 28L
  120. ,ERROR_WRITE_FAULT, STATUS_UNSUCCESSFUL // 29L
  121. ,ERROR_READ_FAULT, STATUS_UNSUCCESSFUL // 30L
  122. ,ERROR_GEN_FAILURE, STATUS_UNSUCCESSFUL // 31L
  123. ,ERROR_SHARING_VIOLATION, STATUS_SHARING_VIOLATION // 32L
  124. ,ERROR_LOCK_VIOLATION, STATUS_LOCK_NOT_GRANTED // 33L
  125. ,ERROR_WRONG_DISK, STATUS_UNSUCCESSFUL // 34L
  126. ,0,0 // 35L
  127. ,ERROR_SHARING_BUFFER_EXCEEDED, STATUS_UNSUCCESSFUL // 36L
  128. ,0,0 // 37L
  129. ,ERROR_HANDLE_EOF, STATUS_END_OF_FILE // 38L
  130. ,ERROR_HANDLE_DISK_FULL, STATUS_UNSUCCESSFUL // 39L
  131. };
  132. //
  133. // Implementation of functions begins here.
  134. //
  135. DWORD
  136. ReadDWord(
  137. HKEY KeyHandle,
  138. LPTSTR lpValueName,
  139. DWORD DefaultValue
  140. )
  141. /*++
  142. Routine Description:
  143. Read a DWORD value from the registry. If there is a problem then
  144. return the default value.
  145. Arguments:
  146. KeyHandle - Handle of the key (value) being read.
  147. lpValueName - The value name.
  148. DefaultValue - The default value to return, if the name does not exists as
  149. a value of the key handle.
  150. Return Value:
  151. Win32 error status.
  152. --*/
  153. {
  154. DWORD Value;
  155. DWORD ValueSize = sizeof(Value);
  156. DWORD ValueType;
  157. if ((KeyHandle) &&
  158. (RegQueryValueEx(KeyHandle,
  159. lpValueName,
  160. 0,
  161. &ValueType,
  162. (PUCHAR)&Value,
  163. &ValueSize ) == ERROR_SUCCESS )) {
  164. return Value;
  165. } else {
  166. return DefaultValue;
  167. }
  168. }
  169. VOID
  170. UpdateServiceStatus (
  171. DWORD dwState
  172. )
  173. /*++
  174. Routine Description:
  175. This routines updates the service status.
  176. Arguments:
  177. dwState - The state the service has to be updated to.
  178. Return Value:
  179. none.
  180. --*/
  181. {
  182. if (g_registeredService) {
  183. ASSERT (g_hStatus);
  184. g_status.dwCurrentState = dwState;
  185. SetServiceStatus(g_hStatus, &g_status);
  186. } else {
  187. g_status.dwCurrentState = dwState;
  188. }
  189. }
  190. NET_API_STATUS
  191. WsLoadRedir(
  192. VOID
  193. )
  194. /*++
  195. Routine Description:
  196. This loads, starts, and configures the kernel mini-redir. If the redir
  197. is already loaded or started, it is not a fatal error.
  198. Arguments:
  199. none.
  200. Return Value:
  201. Win32 error status.
  202. --*/
  203. {
  204. NET_API_STATUS err = ERROR_SUCCESS;
  205. NTSTATUS NtStatus = STATUS_SUCCESS;
  206. UNICODE_STRING DeviceName;
  207. IO_STATUS_BLOCK IoStatusBlock;
  208. OBJECT_ATTRIBUTES ObjectAttributes;
  209. BOOL driverAlreadyLoaded = FALSE;
  210. err = WsLoadDriver(DAVCLIENT_DRIVER);
  211. if (err == ERROR_SERVICE_ALREADY_RUNNING) {
  212. driverAlreadyLoaded = TRUE;
  213. err = ERROR_SUCCESS;
  214. }
  215. if (err != ERROR_SUCCESS) {
  216. DavPrint((DEBUG_ERRORS,
  217. "WsLoadRedir/WsLoadDriver: Error Val = %08lx.\n", err));
  218. return err;
  219. }
  220. //
  221. // Open the redirector device.
  222. //
  223. RtlInitUnicodeString(&(DeviceName), DD_DAV_DEVICE_NAME_U);
  224. InitializeObjectAttributes(&(ObjectAttributes),
  225. &(DeviceName),
  226. OBJ_CASE_INSENSITIVE,
  227. NULL,
  228. NULL);
  229. NtStatus = NtOpenFile(&(DavRedirDeviceHandle),
  230. SYNCHRONIZE,
  231. &(ObjectAttributes),
  232. &(IoStatusBlock),
  233. FILE_SHARE_VALID_FLAGS,
  234. FILE_SYNCHRONOUS_IO_NONALERT);
  235. if (NtStatus != STATUS_SUCCESS) {
  236. DavPrint((DEBUG_ERRORS, "WsLoadRedir/NtOpenFile: Error Val = %08lx\n", NtStatus));
  237. DavRedirDeviceHandle = INVALID_HANDLE_VALUE;
  238. return RtlNtStatusToDosError(NtStatus);
  239. }
  240. return ERROR_SUCCESS;
  241. }
  242. NET_API_STATUS
  243. WsUnloadRedir(
  244. VOID
  245. )
  246. /*++
  247. Routine Description:
  248. This routine unloads the DAV driver. Calls the NtUnloadDriver function.
  249. Arguments:
  250. none.
  251. Return Value:
  252. Win32 error status.
  253. --*/
  254. {
  255. LPWSTR DriverRegistryName;
  256. ULONG Privileges[1], DriverRegistryNameLength;
  257. UNICODE_STRING DriverRegistryString;
  258. NET_API_STATUS Status;
  259. NTSTATUS ntstatus = STATUS_SUCCESS;
  260. DriverRegistryNameLength = sizeof(SERVICE_REGISTRY_KEY);
  261. DriverRegistryNameLength += sizeof(DAVCLIENT_DRIVER);
  262. //
  263. // We need to make the DriverRegistryNameLength a multiple of 8. This is
  264. // because DavAllocateMemory calls DebugAlloc which does some stuff which
  265. // requires this. The equation below does this.
  266. //
  267. DriverRegistryNameLength = ( ( ( DriverRegistryNameLength + 7 ) / 8 ) * 8 );
  268. DriverRegistryName = (LPWSTR) DavAllocateMemory(DriverRegistryNameLength);
  269. if (DriverRegistryName == NULL) {
  270. return ERROR_NOT_ENOUGH_MEMORY;
  271. }
  272. Privileges[0] = SE_LOAD_DRIVER_PRIVILEGE;
  273. Status = NetpGetPrivilege(1, Privileges);
  274. if (Status != NERR_Success) {
  275. DavFreeMemory(DriverRegistryName);
  276. return Status;
  277. }
  278. if (DavRedirDeviceHandle != INVALID_HANDLE_VALUE) {
  279. NtClose(DavRedirDeviceHandle);
  280. DavRedirDeviceHandle = INVALID_HANDLE_VALUE;
  281. }
  282. wcscpy(DriverRegistryName, SERVICE_REGISTRY_KEY);
  283. wcscat(DriverRegistryName, DAVCLIENT_DRIVER);
  284. RtlInitUnicodeString(&(DriverRegistryString), DriverRegistryName);
  285. // Webclient should not unload the MRxDAV if it does not load it.
  286. DavFreeMemory(DriverRegistryName);
  287. NetpReleasePrivilege();
  288. return(WsMapStatus(ntstatus));
  289. }
  290. NET_API_STATUS
  291. WsLoadDriver(
  292. IN LPWSTR DriverNameString
  293. )
  294. /*++
  295. Routine Description:
  296. This routine loads the DAV driver. Calls the NtLoadDriver function.
  297. Arguments:
  298. none.
  299. Return Value:
  300. Win32 error status.
  301. --*/
  302. {
  303. LPWSTR DriverRegistryName;
  304. ULONG Privileges[1], DriverRegistryNameLength;
  305. UNICODE_STRING DriverRegistryString;
  306. NET_API_STATUS Status;
  307. NTSTATUS ntstatus = STATUS_SUCCESS;
  308. DriverRegistryNameLength = sizeof(SERVICE_REGISTRY_KEY);
  309. DriverRegistryNameLength += ( wcslen(DriverNameString) * sizeof(WCHAR) );
  310. //
  311. // We need to make the DriverRegistryNameLength a multiple of 8. This is
  312. // because DavAllocateMemory calls DebugAlloc which does some stuff which
  313. // requires this. The equation below does this.
  314. //
  315. DriverRegistryNameLength = ( ( ( DriverRegistryNameLength + 7 ) / 8 ) * 8 );
  316. DriverRegistryName = (LPWSTR) DavAllocateMemory(DriverRegistryNameLength);
  317. if (DriverRegistryName == NULL) {
  318. DavPrint((DEBUG_ERRORS, "WsLoadDriver/DavAllocateMemory.\n"));
  319. return ERROR_NOT_ENOUGH_MEMORY;
  320. }
  321. Privileges[0] = SE_LOAD_DRIVER_PRIVILEGE;
  322. Status = NetpGetPrivilege(1, Privileges);
  323. if (Status != NERR_Success) {
  324. DavPrint((DEBUG_ERRORS, "WsLoadDriver/NetpGetPrivilege.\n"));
  325. DavFreeMemory(DriverRegistryName);
  326. return Status;
  327. }
  328. wcscpy(DriverRegistryName, SERVICE_REGISTRY_KEY);
  329. wcscat(DriverRegistryName, DriverNameString);
  330. RtlInitUnicodeString(&(DriverRegistryString), DriverRegistryName);
  331. //
  332. // Webclient becomes a LocalService and can no longer load the MRxDAV.
  333. // We make MRxDAV as a depend service of Webclient. Svchost will load it.
  334. //
  335. NetpReleasePrivilege();
  336. DavFreeMemory(DriverRegistryName);
  337. if (ntstatus != STATUS_SUCCESS && ntstatus != STATUS_IMAGE_ALREADY_LOADED) {
  338. LPWSTR subString[1];
  339. subString[0] = DriverNameString;
  340. DavPrint((DEBUG_ERRORS,
  341. "WsLoadDriver/NtLoadDriver. NtStatus = %08lx\n", ntstatus));
  342. #if 0
  343. DavReportEventW(NELOG_DriverNotLoaded,
  344. EVENTLOG_ERROR_TYPE,
  345. 1,
  346. sizeof(NTSTATUS),
  347. subString,
  348. &ntstatus);
  349. #endif
  350. }
  351. return(WsMapStatus(ntstatus));
  352. }
  353. NET_API_STATUS
  354. WsMapStatus(
  355. IN NTSTATUS NtStatus
  356. )
  357. /*++
  358. Routine Description:
  359. This function takes an NT status code and maps it to the appropriate
  360. error code expected from calling a LAN Man API.
  361. Arguments:
  362. NtStatus - Supplies the NT status.
  363. Return Value:
  364. Returns the appropriate LAN Man error code for the NT status.
  365. --*/
  366. {
  367. //
  368. // A small optimization for the most common case.
  369. //
  370. if (NtStatus == STATUS_SUCCESS) {
  371. return NERR_Success;
  372. }
  373. switch (NtStatus) {
  374. case STATUS_OBJECT_NAME_COLLISION:
  375. return ERROR_ALREADY_ASSIGNED;
  376. case STATUS_ACCESS_DENIED:
  377. return ERROR_ACCESS_DENIED;
  378. case STATUS_OBJECT_NAME_NOT_FOUND:
  379. return NERR_UseNotFound;
  380. case STATUS_IMAGE_ALREADY_LOADED:
  381. case STATUS_REDIRECTOR_STARTED:
  382. return ERROR_SERVICE_ALREADY_RUNNING;
  383. case STATUS_REDIRECTOR_HAS_OPEN_HANDLES:
  384. return ERROR_REDIRECTOR_HAS_OPEN_HANDLES;
  385. default:
  386. return NetpNtStatusToApiStatus(NtStatus);
  387. }
  388. }
  389. NTSTATUS
  390. DavMapErrorToNtStatus(
  391. DWORD dwWin32Error
  392. )
  393. /*++
  394. Routine Description:
  395. This function takes an errorcode which is either a WinInet error code or
  396. a or a Win32 error code and converts it into an NTSTATUS value. It does the
  397. following in the order mentioned below:
  398. 1. Checks to see if the error code is a WinInet error code and if it is
  399. maps that to an NTSTATUS value. If not,
  400. 2. Assumes that this is a Win32 error code and maps that to an NTSTATUS
  401. value.
  402. Arguments:
  403. dwWin32Error - The win32 or wininet error code.
  404. Return Value:
  405. Returns the most appropriate NtStatus value.
  406. --*/
  407. {
  408. int indexLast;
  409. DavPrint((DEBUG_MISC,
  410. "DavMapErrorToNtstatus. dwWin32Error = %08lx\n", dwWin32Error));
  411. //
  412. // Check if its a WinInet error.
  413. //
  414. if (dwWin32Error > INTERNET_ERROR_BASE && dwWin32Error <= INTERNET_ERROR_LAST) {
  415. indexLast = ( ( sizeof(rgHttpToNtstatus1) / sizeof(HTTP_TO_NTSTATUS_MAPPING) ) - 1 );
  416. if (dwWin32Error >= rgHttpToNtstatus1[0].dwHttpError &&
  417. dwWin32Error <= rgHttpToNtstatus1[indexLast].dwHttpError) {
  418. return rgHttpToNtstatus1[dwWin32Error-rgHttpToNtstatus1[0].dwHttpError].Status;
  419. }
  420. indexLast = ( ( sizeof(rgHttpToNtstatus2) / sizeof(HTTP_TO_NTSTATUS_MAPPING) ) - 1 );
  421. if (dwWin32Error >= rgHttpToNtstatus2[0].dwHttpError &&
  422. dwWin32Error <= rgHttpToNtstatus2[indexLast].dwHttpError) {
  423. return rgHttpToNtstatus2[dwWin32Error-rgHttpToNtstatus2[0].dwHttpError].Status;
  424. }
  425. } else if (dwWin32Error >= (DWORD)HTTP_STATUS_FIRST && dwWin32Error <= (DWORD)HTTP_STATUS_LAST) {
  426. #if 0
  427. //
  428. // IMPORTANT!!!
  429. // We don't check for Http error codes here. This mapping is done in
  430. // the DavMapHttpErrorToDosError function. The functions expecting a
  431. // Http response should call DavQueryAndParseResponse function.
  432. //
  433. //
  434. // Check if its a HTTP error code.
  435. //
  436. switch (dwWin32Error) {
  437. case HTTP_STATUS_CONTINUE: // 100 OK to continue with request
  438. return STATUS_SUCCESS;
  439. case HTTP_STATUS_SWITCH_PROTOCOLS: // 101 server has switched protocols in upgrade header
  440. return STATUS_DEVICE_PROTOCOL_ERROR;
  441. case HTTP_STATUS_OK: // 200 // request completed
  442. case HTTP_STATUS_CREATED: // 201 // object created, reason = new URI
  443. case HTTP_STATUS_ACCEPTED: // 202 // async completion (TBS)
  444. case HTTP_STATUS_PARTIAL: // 203 // partial completion
  445. case HTTP_STATUS_NO_CONTENT: // 204 // no info to return
  446. case HTTP_STATUS_RESET_CONTENT: // 205 // request completed, but clear form
  447. case HTTP_STATUS_PARTIAL_CONTENT: // 206 // partial GET furfilled
  448. case DAV_MULTI_STATUS: // 207 // multi status response
  449. return STATUS_SUCCESS;
  450. case HTTP_STATUS_AMBIGUOUS: // 300 // server couldn't decide what to return
  451. return STATUS_UNSUCCESSFUL;
  452. case HTTP_STATUS_MOVED: // 301 // object permanently moved
  453. return STATUS_OBJECT_NAME_NOT_FOUND;
  454. case HTTP_STATUS_REDIRECT:
  455. return STATUS_OBJECT_NAME_NOT_FOUND; // 302 // object temporarily moved
  456. case HTTP_STATUS_REDIRECT_METHOD:
  457. return STATUS_OBJECT_NAME_NOT_FOUND; // 303 // redirection w/ new access method
  458. case HTTP_STATUS_NOT_MODIFIED:
  459. return STATUS_SUCCESS; // 304 // if-modified-since was not modified
  460. case HTTP_STATUS_USE_PROXY:
  461. return STATUS_HOST_UNREACHABLE; // 305 // redirection to proxy, location header specifies proxy to use
  462. case HTTP_STATUS_REDIRECT_KEEP_VERB:
  463. return STATUS_SUCCESS; // 307 // HTTP/1.1: keep same verb
  464. case HTTP_STATUS_BAD_REQUEST: // 400 // invalid syntax
  465. return STATUS_INVALID_PARAMETER;
  466. case HTTP_STATUS_DENIED: // 401 // access denied
  467. return STATUS_ACCESS_DENIED;
  468. case HTTP_STATUS_PAYMENT_REQ: // 402 // payment required
  469. return STATUS_ACCESS_DENIED;
  470. case HTTP_STATUS_FORBIDDEN: // 403 // request forbidden
  471. return STATUS_ACCESS_DENIED;
  472. case HTTP_STATUS_NOT_FOUND: // 404 // object not found
  473. return STATUS_OBJECT_NAME_NOT_FOUND;
  474. case HTTP_STATUS_BAD_METHOD: // 405 // method is not allowed
  475. return STATUS_ACCESS_DENIED;
  476. case HTTP_STATUS_NONE_ACCEPTABLE: // 406 // no response acceptable to client found
  477. return STATUS_ACCESS_DENIED;
  478. case HTTP_STATUS_PROXY_AUTH_REQ: // 407 // proxy authentication required
  479. return STATUS_ACCESS_DENIED;
  480. case HTTP_STATUS_REQUEST_TIMEOUT: // 408 // server timed out waiting for request
  481. return STATUS_IO_TIMEOUT;
  482. case HTTP_STATUS_CONFLICT: // 409 // user should resubmit with more info
  483. return STATUS_INVALID_PARAMETER;
  484. case HTTP_STATUS_GONE: // 410 // the resource is no longer available
  485. return STATUS_OBJECT_NAME_NOT_FOUND;
  486. case HTTP_STATUS_LENGTH_REQUIRED: // 411 // the server refused to accept request w/o a length
  487. return STATUS_INVALID_PARAMETER;
  488. case HTTP_STATUS_PRECOND_FAILED: // 412 // precondition given in request failed
  489. return STATUS_INVALID_PARAMETER;
  490. case HTTP_STATUS_REQUEST_TOO_LARGE: // 413 // request entity was too large
  491. return STATUS_INVALID_PARAMETER;
  492. case HTTP_STATUS_URI_TOO_LONG: // 414 // request URI too long
  493. return STATUS_INVALID_PARAMETER;
  494. case HTTP_STATUS_UNSUPPORTED_MEDIA: // 415 // unsupported media type
  495. return STATUS_INVALID_PARAMETER;
  496. case HTTP_STATUS_RETRY_WITH: // 449 // retry after doing the appropriate action.
  497. return STATUS_RETRY;
  498. case HTTP_STATUS_SERVER_ERROR: // 500 // internal server error
  499. return STATUS_UNSUCCESSFUL;
  500. case HTTP_STATUS_NOT_SUPPORTED: // 501 // required not supported
  501. return STATUS_NOT_SUPPORTED;
  502. case HTTP_STATUS_BAD_GATEWAY: // 502 // error response received from gateway
  503. return STATUS_HOST_UNREACHABLE;
  504. case HTTP_STATUS_SERVICE_UNAVAIL: // 503 // temporarily overloaded
  505. return STATUS_UNSUCCESSFUL;
  506. case HTTP_STATUS_GATEWAY_TIMEOUT: // 504 // timed out waiting for gateway
  507. return STATUS_HOST_UNREACHABLE;
  508. case HTTP_STATUS_VERSION_NOT_SUP: // 505 // HTTP version not supported
  509. return STATUS_NOT_SUPPORTED;
  510. //
  511. // WebDav specific status codes.
  512. //
  513. case DAV_STATUS_INSUFFICIENT_STORAGE: // 507
  514. return STATUS_DISK_FULL;
  515. case DAV_STATUS_UNPROCESSABLE_ENTITY: // 422
  516. return STATUS_INVALID_PARAMETER;
  517. case DAV_STATUS_LOCKED: // 423
  518. return STATUS_ACCESS_DENIED;
  519. case DAV_STATUS_FAILED_DEPENDENCY: // 424
  520. return STATUS_INVALID_PARAMETER;
  521. default:
  522. break;
  523. }
  524. #endif
  525. }
  526. //
  527. // If none of the above match call this function which takes a Win32 error
  528. // and maps it to an NTSTATUS value.
  529. //
  530. return DavDosErrorToNtStatus(dwWin32Error);
  531. }
  532. NTSTATUS
  533. DavDosErrorToNtStatus(
  534. DWORD dwError
  535. )
  536. /*++
  537. Routine Description:
  538. This function takes a win32 error code and converts to the closes NTSTATUS.
  539. As NTSTATUS->Win32Error is many to one mapping, there is a possible loss of
  540. precision in this method of error reporting.
  541. Arguments:
  542. dwError - The win32 error code.
  543. Return Value:
  544. Returns the most appropriate NTSTATUS
  545. --*/
  546. {
  547. if (dwError < sizeof(rgWin32ToNtStatus)/sizeof(WIN32_TO_NTSTATUS_MAPPING)) {
  548. return rgWin32ToNtStatus[dwError].NtStatus;
  549. } else {
  550. switch (dwError) {
  551. case ERROR_BUFFER_OVERFLOW:
  552. return STATUS_BUFFER_OVERFLOW;
  553. case ERROR_NOT_SUPPORTED:
  554. return STATUS_NOT_SUPPORTED;
  555. case ERROR_DISK_FULL:
  556. return STATUS_DISK_FULL;
  557. case ERROR_FILE_EXISTS:
  558. return STATUS_OBJECT_NAME_EXISTS;
  559. case ERROR_INVALID_PASSWORD:
  560. return STATUS_WRONG_PASSWORD;
  561. case ERROR_INVALID_PARAMETER:
  562. return STATUS_INVALID_PARAMETER;
  563. case ERROR_BAD_NETPATH:
  564. return STATUS_BAD_NETWORK_PATH;
  565. case ERROR_CALL_NOT_IMPLEMENTED:
  566. return STATUS_NOT_IMPLEMENTED;
  567. case ERROR_SEM_TIMEOUT:
  568. return STATUS_IO_TIMEOUT;
  569. case ERROR_INSUFFICIENT_BUFFER:
  570. return STATUS_BUFFER_TOO_SMALL;
  571. case ERROR_INVALID_NAME:
  572. return STATUS_OBJECT_NAME_INVALID;
  573. case ERROR_DIR_NOT_EMPTY:
  574. return STATUS_DIRECTORY_NOT_EMPTY;
  575. case ERROR_BUSY:
  576. return STATUS_DEVICE_BUSY;
  577. case ERROR_ALREADY_EXISTS:
  578. return STATUS_OBJECT_NAME_COLLISION;
  579. case ERROR_DIRECTORY:
  580. return STATUS_NOT_A_DIRECTORY;
  581. case ERROR_OPERATION_ABORTED:
  582. return STATUS_CANCELLED;
  583. case ERROR_IO_PENDING:
  584. return STATUS_PENDING;
  585. case ERROR_NOACCESS:
  586. return ERROR_ACCESS_DENIED;
  587. case ERROR_NOT_FOUND:
  588. return STATUS_OBJECT_NAME_NOT_FOUND;
  589. case ERROR_NO_MATCH:
  590. return STATUS_OBJECT_NAME_NOT_FOUND;
  591. case ERROR_CANCELLED:
  592. return STATUS_CANCELLED;
  593. case ERROR_RETRY:
  594. return STATUS_RETRY;
  595. case STATUS_NOT_A_DIRECTORY:
  596. return STATUS_NOT_A_DIRECTORY;
  597. case STATUS_FILE_IS_A_DIRECTORY:
  598. return STATUS_FILE_IS_A_DIRECTORY;
  599. case ERROR_NOT_ENOUGH_QUOTA:
  600. return STATUS_QUOTA_EXCEEDED;
  601. case ERROR_SESSION_CREDENTIAL_CONFLICT:
  602. return STATUS_NETWORK_CREDENTIAL_CONFLICT;
  603. default:
  604. DavPrint((DEBUG_ERRORS, "DavDosErrorToNtStatus: dwError = %d\n", dwError));
  605. return STATUS_UNSUCCESSFUL;
  606. }
  607. }
  608. }
  609. // #define FIND_FLAGS_RETRIEVE_ONLY_STRUCT_INFO 0x2
  610. DWORD
  611. DavrGetDiskSpaceUsage(
  612. IN handle_t dav_binding_h,
  613. LPWSTR lptzLocation,
  614. LONG lLenIn,
  615. LONG *lplReturnLen,
  616. ULARGE_INTEGER *lpMaxSpace,
  617. ULARGE_INTEGER *lpUsedSpace
  618. )
  619. /*++
  620. Routine Description:
  621. Finds out the amount of disk being consumed by wininet urlcache due to Webdav
  622. Arguments:
  623. dav_binding_h - The explicit RPC binding handle.
  624. dwSize - Size of the cache location buffer. On return this will contain the actual size of the
  625. location string.
  626. lptzLocation - Buffer to return Cache location string. As much of the location string as can fit
  627. in the buffer is returned
  628. lpdwReturnSize
  629. lpMaxSpace - Size of disk Quota set for webdav
  630. lpUsedSpace - Size of disk consumed by the urlcache used by webdav
  631. Return Value:
  632. Win32 error code
  633. --*/
  634. {
  635. // iterate through the cache to discover the actual size.
  636. INTERNET_CACHE_CONFIG_INFOW sConfigW;
  637. DWORD dwSize = sizeof(sConfigW), dwError = ERROR_SUCCESS;
  638. BOOL fResult = FALSE;
  639. // should atleass have enough space for a drive letter
  640. if (lLenIn < 3)
  641. {
  642. return ERROR_INVALID_PARAMETER;
  643. }
  644. try
  645. {
  646. sConfigW.dwContainer = 0;
  647. sConfigW.dwStructSize = sizeof(sConfigW);
  648. if (GetUrlCacheConfigInfoW(&sConfigW, &dwSize, CACHE_CONFIG_DISK_CACHE_PATHS_FC |
  649. CACHE_CONFIG_QUOTA_FC |
  650. CACHE_CONFIG_CONTENT_USAGE_FC |
  651. CACHE_CONFIG_STICKY_CONTENT_USAGE_FC))
  652. {
  653. *(ULONGLONG *)lpMaxSpace = (ULONGLONG)(sConfigW.dwQuota) * 1024;
  654. *(ULONGLONG *)lpUsedSpace = (ULONGLONG)(sConfigW.dwNormalUsage+sConfigW.dwExemptUsage) * 1024;
  655. memset(lptzLocation, 0, lLenIn * sizeof(WCHAR));
  656. *lplReturnLen = wcslen(sConfigW.CachePath);
  657. if (*lplReturnLen < lLenIn)
  658. {
  659. // We have enough buffer
  660. memcpy(lptzLocation, sConfigW.CachePath, *lplReturnLen * sizeof(WCHAR));
  661. }
  662. else
  663. {
  664. // We don't have enough buffer, we copy as much as we can
  665. memcpy(lptzLocation, sConfigW.CachePath, lLenIn * sizeof(WCHAR));
  666. }
  667. }
  668. else
  669. {
  670. dwError = GetLastError();
  671. }
  672. }
  673. except(EXCEPTION_EXECUTE_HANDLER)
  674. {
  675. dwError = ERROR_INVALID_PARAMETER;
  676. }
  677. return dwError;
  678. }
  679. DWORD
  680. DavrFreeUsedDiskSpace(
  681. IN handle_t dav_binding_h,
  682. DWORD dwPercent
  683. )
  684. /*++
  685. Routine Description:
  686. Frees up dwPercent of the urlcache used by webdav
  687. Arguments:
  688. dav_binding_h - The explicit RPC binding handle.
  689. dwPercent - % of used space to be freed
  690. Return Value:
  691. Win32 error code
  692. --*/
  693. {
  694. DWORD dwError = ERROR_SUCCESS;
  695. if (dwPercent <= 100)
  696. {
  697. if (!FreeUrlCacheSpaceA(NULL, dwPercent, 0))
  698. {
  699. dwError = GetLastError();
  700. }
  701. }
  702. else
  703. {
  704. dwError = ERROR_INVALID_PARAMETER;
  705. }
  706. return dwError;
  707. }