xref: /reactos/win32ss/user/ntuser/misc/file.c (revision f308c6a2)
1 /*
2  * COPYRIGHT:        GPL, see COPYING in the top level directory
3  * PROJECT:          ReactOS win32 kernel mode subsystem server
4  * PURPOSE:          File access support routines
5  * FILE:             win32ss/user/ntuser/misc/file.c
6  * PROGRAMER:        Timo Kreuzer (timo.kreuzer@reactos.org)
7  */
8 
9 #include <win32k.h>
10 
11 #define NDEBUG
12 #include <debug.h>
13 
14 BOOL
15 NTAPI
16 W32kDosPathNameToNtPathName(
17     IN PCWSTR pwszDosPathName,
18     OUT PUNICODE_STRING pustrNtPathName)
19 {
20     NTSTATUS Status;
21 
22     /* Prepend "\??\" */
23     pustrNtPathName->Length = 0;
24     Status = RtlAppendUnicodeToString(pustrNtPathName, L"\\??\\");
25     if (!NT_SUCCESS(Status))
26     {
27         return FALSE;
28     }
29 
30     /* Append the dos name */
31     Status = RtlAppendUnicodeToString(pustrNtPathName, pwszDosPathName);
32     if (!NT_SUCCESS(Status))
33     {
34         return FALSE;
35     }
36 
37     return TRUE;
38 }
39 
40 
41 HANDLE
42 NTAPI
43 W32kOpenFile(PCWSTR pwszFileName, DWORD dwDesiredAccess)
44 {
45     UNICODE_STRING ustrFile;
46     OBJECT_ATTRIBUTES ObjectAttributes;
47     IO_STATUS_BLOCK IoStatusBlock;
48     HANDLE hFile = INVALID_HANDLE_VALUE;
49     NTSTATUS Status;
50 
51     DPRINT("W32kOpenFile(%S)\n", pwszFileName);
52 
53     RtlInitUnicodeString(&ustrFile, pwszFileName);
54 
55     InitializeObjectAttributes(&ObjectAttributes,
56                                &ustrFile,
57                                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
58                                NULL,
59                                NULL);
60 
61     Status = ZwCreateFile(&hFile,
62                           dwDesiredAccess,
63                           &ObjectAttributes,
64                           &IoStatusBlock,
65                           NULL,
66                           FILE_ATTRIBUTE_NORMAL,
67                           0,
68                           FILE_OPEN,
69                           FILE_NON_DIRECTORY_FILE,
70                           NULL,
71                           0);
72     if (!NT_SUCCESS(Status))
73     {
74         SetLastNtError(Status);
75         hFile = NULL;
76     }
77 
78     DPRINT("Leaving W32kOpenFile, Status=0x%lx, hFile=0x%p\n", Status, hFile);
79     return hFile;
80 }
81 
82 HANDLE
83 NTAPI
84 W32kCreateFileSection(HANDLE hFile,
85                       ULONG flAllocation,
86                       DWORD flPageProtection,
87                       ULONGLONG ullMaxSize)
88 {
89     NTSTATUS Status;
90     HANDLE hSection;
91     ACCESS_MASK amDesiredAccess;
92 
93     /* Set access mask */
94     amDesiredAccess = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ;
95 
96     /* Check if write access is requested */
97     if (flPageProtection == PAGE_READWRITE)
98     {
99         /* Add it to access mask */
100         amDesiredAccess |= SECTION_MAP_WRITE;
101     }
102 
103     /* Now create the actual section */
104     Status = ZwCreateSection(&hSection,
105                              amDesiredAccess,
106                              NULL,
107                              NULL,
108                              flPageProtection,
109                              flAllocation,
110                              hFile);
111     if (!NT_SUCCESS(Status))
112     {
113         SetLastNtError(Status);
114         hSection = NULL;
115     }
116 
117     DPRINT("Leaving W32kCreateFileSection, Status=0x%lx, hSection=0x%p\n", Status, hSection);
118 
119     /* Return section handle */
120     return hSection;
121 }
122 
123 PVOID
124 NTAPI
125 W32kMapViewOfSection(
126     HANDLE hSection,
127     DWORD dwPageProtect,
128     ULONG_PTR ulSectionOffset)
129 {
130     NTSTATUS Status;
131     LARGE_INTEGER liSectionOffset;
132     ULONG_PTR ulViewSize;
133     PVOID pvBase = NULL;
134 
135     liSectionOffset.QuadPart = ulViewSize = ulSectionOffset;
136     Status = ZwMapViewOfSection(hSection,
137                                 NtCurrentProcess(),
138                                 &pvBase,
139                                 0,
140                                 0,
141                                 &liSectionOffset,
142                                 &ulViewSize,
143                                 ViewShare,
144                                 0,
145                                 dwPageProtect);
146     if (!NT_SUCCESS(Status))
147     {
148         SetLastNtError(Status);
149         pvBase = NULL;
150     }
151 
152     DPRINT("Leaving W32kMapViewOfSection, Status=0x%lx, pvBase=0x%p\n", Status, pvBase);
153 
154     return pvBase;
155 }
156 
157 HBITMAP
158 NTAPI
159 UserLoadImage(PCWSTR pwszName)
160 {
161     NTSTATUS Status = STATUS_SUCCESS;
162     HANDLE hFile, hSection;
163     BITMAPFILEHEADER *pbmfh;
164     LPBITMAPINFO pbmi;
165     PVOID pvBits;
166     HBITMAP hbmp = 0;
167 
168     DPRINT("Enter UserLoadImage(%ls)\n", pwszName);
169 
170     /* Open the file */
171     hFile = W32kOpenFile(pwszName, FILE_READ_DATA);
172     if (!hFile)
173     {
174         return NULL;
175     }
176 
177     /* Create a section */
178     hSection = W32kCreateFileSection(hFile, SEC_COMMIT, PAGE_READONLY, 0);
179     ZwClose(hFile);
180     if (!hSection)
181     {
182         return NULL;
183     }
184 
185     /* Map the section */
186     pbmfh = W32kMapViewOfSection(hSection, PAGE_READONLY, 0);
187     ZwClose(hSection);
188     if (!pbmfh)
189     {
190         return NULL;
191     }
192 
193     /* Get a pointer to the BITMAPINFO */
194     pbmi = (LPBITMAPINFO)(pbmfh + 1);
195 
196 	_SEH2_TRY
197 	{
198 		ProbeForRead(&pbmfh->bfSize, sizeof(DWORD), 1);
199 		ProbeForRead(pbmfh, pbmfh->bfSize, 1);
200 	}
201 	_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
202 	{
203 		Status = _SEH2_GetExceptionCode();
204 	}
205 	_SEH2_END
206 
207 	if(!NT_SUCCESS(Status))
208 	{
209 		DPRINT1("Bad File?\n");
210 		goto leave;
211 	}
212 
213     if (pbmfh->bfType == 0x4D42 /* 'BM' */)
214     {
215 		/* Could be BITMAPCOREINFO */
216 		BITMAPINFO* pConvertedInfo;
217 		HDC hdc;
218 
219 		pvBits = (PVOID)((PCHAR)pbmfh + pbmfh->bfOffBits);
220 
221 		pConvertedInfo = DIB_ConvertBitmapInfo(pbmi, DIB_RGB_COLORS);
222 		if(!pConvertedInfo)
223 		{
224 			DPRINT1("Unable to convert the bitmap Info\n");
225 			goto leave;
226 		}
227 
228 		hdc = IntGdiCreateDC(NULL, NULL, NULL, NULL,FALSE);
229 
230         hbmp = GreCreateDIBitmapInternal(hdc,
231                                          pConvertedInfo->bmiHeader.biWidth,
232 				                         pConvertedInfo->bmiHeader.biHeight,
233                                          CBM_INIT,
234                                          pvBits,
235                                          pConvertedInfo,
236                                          DIB_RGB_COLORS,
237                                          0,
238                                          pbmfh->bfSize - pbmfh->bfOffBits,
239                                          0);
240 
241 		NtGdiDeleteObjectApp(hdc);
242 		DIB_FreeConvertedBitmapInfo(pConvertedInfo, pbmi, -1);
243     }
244 	else
245 	{
246 		DPRINT1("Unknown file type!\n");
247 	}
248 
249 leave:
250     /* Unmap our section, we don't need it anymore */
251     ZwUnmapViewOfSection(NtCurrentProcess(), pbmfh);
252 
253     DPRINT("Leaving UserLoadImage, hbmp = %p\n", hbmp);
254     return hbmp;
255 }
256