xref: /reactos/dll/shellext/shellbtrfs/reactos.cpp (revision 7983b65e)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         BtrFS FSD for ReactOS
4  * FILE:            dll/shellext/shellbtrfs/reactos.cpp
5  * PURPOSE:         ReactOS glue for Win8.1
6  * PROGRAMMERS:     Pierre Schweitzer <pierre@reactos.org>
7  */
8 
9 #include "shellext.h"
10 #include <initguid.h>
11 #include <ntddstor.h>
12 #include <ndk/rtlfuncs.h>
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 /* So that we can link */
18 DEFINE_GUID(CLSID_WICImagingFactory, 0xcacaf262,0x9370,0x4615,0xa1,0x3b,0x9f,0x55,0x39,0xda,0x4c,0x0a);
19 
20 /* Copied from ntoskrnl_vista */
21 NTSTATUS WINAPI RtlUTF8ToUnicodeN(PWSTR uni_dest, ULONG uni_bytes_max,
22                                   PULONG uni_bytes_written,
23                                   PCCH utf8_src, ULONG utf8_bytes)
24 {
25     NTSTATUS status;
26     ULONG i, j;
27     ULONG written;
28     ULONG ch;
29     ULONG utf8_trail_bytes;
30     WCHAR utf16_ch[3];
31     ULONG utf16_ch_len;
32 
33     if (!utf8_src)
34         return STATUS_INVALID_PARAMETER_4;
35     if (!uni_bytes_written)
36         return STATUS_INVALID_PARAMETER;
37 
38     written = 0;
39     status = STATUS_SUCCESS;
40 
41     for (i = 0; i < utf8_bytes; i++)
42     {
43         /* read UTF-8 lead byte */
44         ch = (BYTE)utf8_src[i];
45         utf8_trail_bytes = 0;
46         if (ch >= 0xf5)
47         {
48             ch = 0xfffd;
49             status = STATUS_SOME_NOT_MAPPED;
50         }
51         else if (ch >= 0xf0)
52         {
53             ch &= 0x07;
54             utf8_trail_bytes = 3;
55         }
56         else if (ch >= 0xe0)
57         {
58             ch &= 0x0f;
59             utf8_trail_bytes = 2;
60         }
61         else if (ch >= 0xc2)
62         {
63             ch &= 0x1f;
64             utf8_trail_bytes = 1;
65         }
66         else if (ch >= 0x80)
67         {
68             /* overlong or trail byte */
69             ch = 0xfffd;
70             status = STATUS_SOME_NOT_MAPPED;
71         }
72 
73         /* read UTF-8 trail bytes */
74         if (i + utf8_trail_bytes < utf8_bytes)
75         {
76             for (j = 0; j < utf8_trail_bytes; j++)
77             {
78                 if ((utf8_src[i + 1] & 0xc0) == 0x80)
79                 {
80                     ch <<= 6;
81                     ch |= utf8_src[i + 1] & 0x3f;
82                     i++;
83                 }
84                 else
85                 {
86                     ch = 0xfffd;
87                     utf8_trail_bytes = 0;
88                     status = STATUS_SOME_NOT_MAPPED;
89                     break;
90                 }
91             }
92         }
93         else
94         {
95             ch = 0xfffd;
96             utf8_trail_bytes = 0;
97             status = STATUS_SOME_NOT_MAPPED;
98             i = utf8_bytes;
99         }
100 
101         /* encode ch as UTF-16 */
102         if ((ch > 0x10ffff) ||
103             (ch >= 0xd800 && ch <= 0xdfff) ||
104             (utf8_trail_bytes == 2 && ch < 0x00800) ||
105             (utf8_trail_bytes == 3 && ch < 0x10000))
106         {
107             /* invalid codepoint or overlong encoding */
108             utf16_ch[0] = 0xfffd;
109             utf16_ch[1] = 0xfffd;
110             utf16_ch[2] = 0xfffd;
111             utf16_ch_len = utf8_trail_bytes;
112             status = STATUS_SOME_NOT_MAPPED;
113         }
114         else if (ch >= 0x10000)
115         {
116             /* surrogate pair */
117             ch -= 0x010000;
118             utf16_ch[0] = 0xd800 + (ch >> 10 & 0x3ff);
119             utf16_ch[1] = 0xdc00 + (ch >>  0 & 0x3ff);
120             utf16_ch_len = 2;
121         }
122         else
123         {
124             /* single unit */
125             utf16_ch[0] = ch;
126             utf16_ch_len = 1;
127         }
128 
129         if (!uni_dest)
130         {
131             written += utf16_ch_len;
132             continue;
133         }
134 
135         for (j = 0; j < utf16_ch_len; j++)
136         {
137             if (uni_bytes_max >= sizeof(WCHAR))
138             {
139                 *uni_dest++ = utf16_ch[j];
140                 uni_bytes_max -= sizeof(WCHAR);
141                 written++;
142             }
143             else
144             {
145                 uni_bytes_max = 0;
146                 status = STATUS_BUFFER_TOO_SMALL;
147             }
148         }
149     }
150 
151     *uni_bytes_written = written * sizeof(WCHAR);
152     return status;
153 }
154 
155 /* Quick and dirty table for conversion */
156 FILE_INFORMATION_CLASS ConvertToFileInfo[MaximumFileInfoByHandleClass] =
157 {
158     FileBasicInformation, FileStandardInformation, FileNameInformation, FileRenameInformation,
159     FileDispositionInformation, FileAllocationInformation, FileEndOfFileInformation, FileStreamInformation,
160     FileCompressionInformation, FileAttributeTagInformation, FileIdBothDirectoryInformation, (FILE_INFORMATION_CLASS)-1,
161     FileIoPriorityHintInformation, FileRemoteProtocolInformation
162 };
163 
164 /* Taken from kernel32 */
165 DWORD
166 BaseSetLastNTError(IN NTSTATUS Status)
167 {
168     DWORD dwErrCode;
169     dwErrCode = RtlNtStatusToDosError(Status);
170     SetLastError(dwErrCode);
171     return dwErrCode;
172 }
173 
174 /* Quick implementation, still going farther than Wine implementation */
175 BOOL
176 WINAPI
177 SetFileInformationByHandle(HANDLE hFile,
178                            FILE_INFO_BY_HANDLE_CLASS FileInformationClass,
179                            LPVOID lpFileInformation,
180                            DWORD dwBufferSize)
181 {
182     NTSTATUS Status;
183     IO_STATUS_BLOCK IoStatusBlock;
184     FILE_INFORMATION_CLASS FileInfoClass;
185 
186     FileInfoClass = (FILE_INFORMATION_CLASS)-1;
187 
188     /* Attempt to convert the class */
189     if (FileInformationClass < MaximumFileInfoByHandleClass)
190     {
191         FileInfoClass = ConvertToFileInfo[FileInformationClass];
192     }
193 
194     /* If wrong, bail out */
195     if (FileInfoClass == -1)
196     {
197         SetLastError(ERROR_INVALID_PARAMETER);
198         return FALSE;
199     }
200 
201     /* And set the information */
202     Status = NtSetInformationFile(hFile, &IoStatusBlock, lpFileInformation,
203                                   dwBufferSize, FileInfoClass);
204 
205     if (!NT_SUCCESS(Status))
206     {
207         BaseSetLastNTError(Status);
208         return FALSE;
209     }
210 
211     return TRUE;
212 }
213 #ifdef __cplusplus
214 }
215 #endif
216