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