ec68f24c63a3be40d657a3336d8b078ae0d3b0ae
[reactos.git] / reactos / dll / win32 / gdi32 / objects / enhmfile.c
1 #include "precomp.h"
2
3 #define NDEBUG
4 #include <debug.h>
5
6
7
8 /*
9 * @unimplemented
10 */
11 HENHMETAFILE
12 WINAPI
13 CloseEnhMetaFile(
14 HDC hdc)
15 {
16 UNIMPLEMENTED;
17 return 0;
18 }
19
20
21 #if 0 // Remove once new EnhMetaFile support is implemented.
22 HDC
23 WINAPI
24 CreateEnhMetaFileW(
25 HDC hDC, /* [in] optional reference DC */
26 LPCWSTR filename, /* [in] optional filename for disk metafiles */
27 const RECT* rect, /* [in] optional bounding rectangle */
28 LPCWSTR description /* [in] optional description */
29 )
30 {
31 HDC mDC;
32 PDC_ATTR Dc_Attr;
33 PLDC pLDC;
34 HANDLE hFile;
35 PENHMETAFILE EmfDC;
36 DWORD size = 0, length = 0;
37
38 mDC = NtGdiCreateMetafileDC( hDC ); // Basically changes the handle from 1xxxx to 46xxxx.
39 // If hDC == NULL, works just like createdc in win32k.
40
41 if ( !GdiGetHandleUserData((HGDIOBJ) mDC, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr))
42 {
43 SetLastError (ERROR_INVALID_PARAMETER);
44 return NULL; // need to delete the handle?
45 }
46
47 pLDC = LocalAlloc(LMEM_ZEROINIT, sizeof(LDC));
48
49 Dc_Attr->pvLDC = pLDC;
50 pLDC->hDC = mDC;
51 pLDC->iType = LDC_EMFDC
52
53
54 if (description)
55 {
56 /* App name\0Title\0\0 */
57 length = lstrlenW(description);
58 length += lstrlenW(description + length + 1);
59 length += 3;
60 length *= 2;
61 }
62
63 size = sizeof(ENHMETAFILE) + (length + 3) / 4 * 4;
64
65 //Allocate ENHMETAFILE structure
66 EmfDC = LocalAlloc(LMEM_ZEROINIT, sizeof(ENHMETAFILE));
67 pLDC->pvEmfDC = EmfDC;
68
69 EmfDC->handles_size = HANDLE_LIST_INC;
70 EmfDC->cur_handles = 1;
71
72 EmfDC->horzres = GetDeviceCaps(mDC, HORZRES);
73 EmfDC->vertres = GetDeviceCaps(mDC, VERTRES);
74 EmfDC->logpixelsx = GetDeviceCaps(mDC, LOGPIXELSX);
75 EmfDC->logpixelsy = GetDeviceCaps(mDC, LOGPIXELSY);
76 EmfDC->horzsize = GetDeviceCaps(mDC, HORZSIZE);
77 EmfDC->vertsize = GetDeviceCaps(mDC, VERTSIZE);
78 EmfDC->bitspixel = GetDeviceCaps(mDC, BITSPIXEL);
79 EmfDC->textcaps = GetDeviceCaps(mDC, TEXTCAPS);
80 EmfDC->rastercaps = GetDeviceCaps(mDC, RASTERCAPS);
81 EmfDC->technology = GetDeviceCaps(mDC, TECHNOLOGY);
82 EmfDC->planes = GetDeviceCaps(mDC, PLANES);
83
84 EmfDC->emf = LocalAlloc(LMEM_ZEROINIT, size);
85
86 EmfDC->emf->iType = EMR_HEADER;
87 EmfDC->emf->nSize = size;
88
89 EmfDC->emf->rclBounds.left = EmfDC->emf->rclBounds.top = 0;
90 EmfDC->emf->rclBounds.right = EmfDC->emf->rclBounds.bottom = -1;
91
92 if(rect)
93 {
94 EmfDC->emf->rclFrame.left = rect->left;
95 EmfDC->emf->rclFrame.top = rect->top;
96 EmfDC->emf->rclFrame.right = rect->right;
97 EmfDC->emf->rclFrame.bottom = rect->bottom;
98 }
99 else
100 {
101 /* Set this to {0,0 - -1,-1} and update it at the end */
102 EmfDC->emf->rclFrame.left = EmfDC->emf->rclFrame.top = 0;
103 EmfDC->emf->rclFrame.right = EmfDC->emf->rclFrame.bottom = -1;
104 }
105
106 EmfDC->emf->dSignature = ENHMETA_SIGNATURE;
107 EmfDC->emf->nVersion = 0x10000;
108 EmfDC->emf->nBytes = pLDC->pvEmfDC->nSize;
109 EmfDC->emf->nRecords = 1;
110 EmfDC->emf->nHandles = 1;
111
112 EmfDC->emf->sReserved = 0; /* According to docs, this is reserved and must be 0 */
113 EmfDC->emf->nDescription = length / 2;
114
115 EmfDC->emf->offDescription = length ? sizeof(ENHMETAHEADER) : 0;
116
117 EmfDC->emf->nPalEntries = 0; /* I guess this should start at 0 */
118
119 /* Size in pixels */
120 EmfDC->emf->szlDevice.cx = EmfDC->horzres;
121 EmfDC->emf->szlDevice.cy = EmfDC->vertres;
122
123 /* Size in millimeters */
124 EmfDC->emf->szlMillimeters.cx = EmfDC->horzsize;
125 EmfDC->emf->szlMillimeters.cy = EmfDC->vertsize;
126
127 /* Size in micrometers */
128 EmfDC->emf->szlMicrometers.cx = EmfDC->horzsize * 1000;
129 EmfDC->emf->szlMicrometers.cy = EmfDC->vertsize * 1000;
130
131 RtlCopyMemory((char *)EmfDC->emf + sizeof(ENHMETAHEADER), description, length);
132
133 if (filename) /* disk based metafile */
134 {
135 if ((hFile = CreateFileW(filename, GENERIC_WRITE | GENERIC_READ, 0,
136 NULL, CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE)
137 {
138 EMFDRV_DeleteDC( EmfDC );
139 return NULL;
140 }
141 if (!WriteFile( hFile, (LPSTR)EmfDC->emf, size, NULL, NULL ))
142 {
143 EMFDRV_DeleteDC( EmfDC );
144 return NULL;
145 }
146 EmfDC.hFile = hFile;
147 EmfDC.iType = METAFILE_DISK;
148 }
149 else
150 EmfDC.iType = METAFILE_MEMORY;
151
152 return mDC;
153 }
154 #endif
155
156
157 /*
158 * @unimplemented
159 */
160 HENHMETAFILE
161 WINAPI
162 CopyEnhMetaFileA(
163 HENHMETAFILE hemfSrc,
164 LPCSTR lpszFile)
165 {
166 NTSTATUS Status;
167 LPWSTR lpszFileW;
168 HENHMETAFILE rc = 0;
169
170 Status = HEAP_strdupA2W ( &lpszFileW, lpszFile );
171 if (!NT_SUCCESS (Status))
172 SetLastError (RtlNtStatusToDosError(Status));
173 else
174 {
175 rc = NULL;
176
177 HEAP_free ( lpszFileW );
178 }
179 return rc;
180 }
181
182
183 /*
184 * @unimplemented
185 */
186 HDC
187 WINAPI
188 CreateEnhMetaFileA(
189 HDC hdcRef,
190 LPCSTR lpFileName,
191 CONST RECT *lpRect,
192 LPCSTR lpDescription)
193 {
194 NTSTATUS Status;
195 LPWSTR lpFileNameW, lpDescriptionW;
196 HDC rc = 0;
197
198 lpFileNameW = NULL;
199 if (lpFileName != NULL)
200 {
201 Status = HEAP_strdupA2W ( &lpFileNameW, lpFileName );
202 if (!NT_SUCCESS (Status))
203 SetLastError (RtlNtStatusToDosError(Status));
204
205 return rc;
206 }
207
208 lpDescriptionW = NULL;
209 if (lpDescription != NULL)
210 {
211 Status = HEAP_strdupA2W ( &lpDescriptionW, lpDescription );
212 if (!NT_SUCCESS (Status))
213 SetLastError (RtlNtStatusToDosError(Status));
214
215 return rc;
216 }
217
218 rc = NULL;
219
220 if (lpDescriptionW != NULL)
221 HEAP_free ( lpDescriptionW );
222
223 if (lpFileNameW != NULL)
224 HEAP_free ( lpFileNameW );
225
226 return rc;
227 }
228
229 #if 0
230 /* Previous implementation in win32k */
231 HDC
232 WINAPI
233 NtGdiCreateEnhMetaFile(HDC hDCRef,
234 LPCWSTR File,
235 CONST LPRECT Rect,
236 LPCWSTR Description)
237 {
238 PDC Dc;
239 HDC ret = NULL;
240 DWORD length = 0;
241 HDC tempHDC;
242 DWORD MemSize;
243 DWORD dwDesiredAccess;
244
245 tempHDC = hDCRef;
246 if (hDCRef == NULL)
247 {
248 /* FIXME ??
249 * Shall we create hdc NtGdiHdcCompatible hdc ??
250 */
251 UNICODE_STRING DriverName;
252 RtlInitUnicodeString(&DriverName, L"DISPLAY");
253 //IntGdiCreateDC(&DriverName, NULL, NULL, NULL, FALSE);
254 tempHDC = NtGdiOpenDCW( &DriverName,
255 NULL,
256 NULL,
257 0, // DCW 0 and ICW 1.
258 NULL,
259 (PVOID) NULL,
260 (PVOID) NULL );
261 }
262
263 GDIOBJ_SetOwnership(GdiHandleTable, tempHDC, PsGetCurrentProcess());
264 DC_SetOwnership(tempHDC, PsGetCurrentProcess());
265
266 Dc = DC_LockDc(tempHDC);
267 if (Dc == NULL)
268 {
269 if (hDCRef == NULL)
270 {
271 NtGdiDeleteObjectApp(tempHDC);
272 }
273 SetLastWin32Error(ERROR_INVALID_HANDLE);
274 return NULL;
275 }
276
277 if(Description)
278 {
279 length = wcslen(Description);
280 length += wcslen(Description + length + 1);
281 length += 3;
282 length *= 2;
283 }
284
285 MemSize = sizeof(ENHMETAHEADER) + (length + 3) / 4 * 4;
286
287 if (!(Dc->emh = EngAllocMem(FL_ZERO_MEMORY, MemSize, 0)))
288 {
289 DC_UnlockDc(Dc);
290 if (hDCRef == NULL)
291 {
292 NtGdiDeleteObjectApp(tempHDC);
293 }
294 SetLastWin32Error(ERROR_INVALID_HANDLE);
295 return NULL;
296 }
297
298 Dc->emh->iType = EMR_HEADER;
299 Dc->emh->nSize = MemSize;
300
301 Dc->emh->rclBounds.left = Dc->emh->rclBounds.top = 0;
302 Dc->emh->rclBounds.right = Dc->emh->rclBounds.bottom = -1;
303
304 if(Rect)
305 {
306 Dc->emh->rclFrame.left = Rect->left;
307 Dc->emh->rclFrame.top = Rect->top;
308 Dc->emh->rclFrame.right = Rect->right;
309 Dc->emh->rclFrame.bottom = Rect->bottom;
310 }
311 else
312 {
313 /* Set this to {0,0 - -1,-1} and update it at the end */
314 Dc->emh->rclFrame.left = Dc->emh->rclFrame.top = 0;
315 Dc->emh->rclFrame.right = Dc->emh->rclFrame.bottom = -1;
316 }
317
318 Dc->emh->dSignature = ENHMETA_SIGNATURE;
319 Dc->emh->nVersion = 0x10000;
320 Dc->emh->nBytes = Dc->emh->nSize;
321 Dc->emh->nRecords = 1;
322 Dc->emh->nHandles = 1;
323
324 Dc->emh->sReserved = 0; /* According to docs, this is reserved and must be 0 */
325 Dc->emh->nDescription = length / 2;
326
327 Dc->emh->offDescription = length ? sizeof(ENHMETAHEADER) : 0;
328
329 Dc->emh->nPalEntries = 0; /* I guess this should start at 0 */
330
331 /* Size in pixels */
332 Dc->emh->szlDevice.cx = NtGdiGetDeviceCaps(tempHDC, HORZRES);
333 Dc->emh->szlDevice.cy = NtGdiGetDeviceCaps(tempHDC, VERTRES);
334
335 /* Size in millimeters */
336 Dc->emh->szlMillimeters.cx = NtGdiGetDeviceCaps(tempHDC, HORZSIZE);
337 Dc->emh->szlMillimeters.cy = NtGdiGetDeviceCaps(tempHDC, VERTSIZE);
338
339 /* Size in micrometers */
340 Dc->emh->szlMicrometers.cx = Dc->emh->szlMillimeters.cx * 1000;
341 Dc->emh->szlMicrometers.cy = Dc->emh->szlMillimeters.cy * 1000;
342
343 if(Description)
344 {
345 memcpy((char *)Dc->emh + sizeof(ENHMETAHEADER), Description, length);
346 }
347
348 ret = tempHDC;
349 if (File)
350 {
351 OBJECT_ATTRIBUTES ObjectAttributes;
352 IO_STATUS_BLOCK IoStatusBlock;
353 IO_STATUS_BLOCK Iosb;
354 UNICODE_STRING NtPathU;
355 NTSTATUS Status;
356 ULONG FileAttributes = (FILE_ATTRIBUTE_VALID_FLAGS & ~FILE_ATTRIBUTE_DIRECTORY);
357
358 DPRINT1("Trying Create EnhMetaFile\n");
359
360 /* disk based metafile */
361 dwDesiredAccess = GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE | FILE_READ_ATTRIBUTES;
362
363 if (!RtlDosPathNameToNtPathName_U (File, &NtPathU, NULL, NULL))
364 {
365 DC_UnlockDc(Dc);
366 if (hDCRef == NULL)
367 {
368 NtGdiDeleteObjectApp(tempHDC);
369 }
370 DPRINT1("Can not Create EnhMetaFile\n");
371 SetLastWin32Error(ERROR_PATH_NOT_FOUND);
372 return NULL;
373 }
374
375 InitializeObjectAttributes(&ObjectAttributes, &NtPathU, 0, NULL, NULL);
376
377 Status = NtCreateFile (&Dc->hFile, dwDesiredAccess, &ObjectAttributes, &IoStatusBlock,
378 NULL, FileAttributes, 0, FILE_OVERWRITE_IF, FILE_NON_DIRECTORY_FILE,
379 NULL, 0);
380
381 RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathU.Buffer);
382
383 if (!NT_SUCCESS(Status))
384 {
385 Dc->hFile = NULL;
386 DC_UnlockDc(Dc);
387 if (hDCRef == NULL)
388 {
389 NtGdiDeleteObjectApp(tempHDC);
390 }
391 DPRINT1("Create EnhMetaFile fail\n");
392 SetLastWin32Error(ERROR_INVALID_HANDLE);
393 return NULL;
394 }
395
396 SetLastWin32Error(IoStatusBlock.Information == FILE_OVERWRITTEN ? ERROR_ALREADY_EXISTS : 0);
397
398 Status = NtWriteFile(Dc->hFile, NULL, NULL, NULL, &Iosb, (PVOID)&Dc->emh, Dc->emh->nSize, NULL, NULL);
399 if (Status == STATUS_PENDING)
400 {
401 Status = NtWaitForSingleObject(Dc->hFile,FALSE,NULL);
402 if (NT_SUCCESS(Status))
403 {
404 Status = Iosb.Status;
405 }
406 }
407
408 if (NT_SUCCESS(Status))
409 {
410 ret = tempHDC;
411 DC_UnlockDc(Dc);
412 }
413 else
414 {
415 Dc->hFile = NULL;
416 DPRINT1("Write to EnhMetaFile fail\n");
417 SetLastWin32Error(ERROR_CAN_NOT_COMPLETE);
418 ret = NULL;
419 DC_UnlockDc(Dc);
420 if (hDCRef == NULL)
421 {
422 NtGdiDeleteObjectApp(tempHDC);
423 }
424 }
425 }
426 else
427 {
428 DC_UnlockDc(Dc);
429 }
430
431 return ret;
432 }
433 #endif
434
435
436
437 /*
438 * @unimplemented
439 */
440 HENHMETAFILE
441 WINAPI
442 GetEnhMetaFileA(
443 LPCSTR lpszMetaFile)
444 {
445 NTSTATUS Status;
446 LPWSTR lpszMetaFileW;
447 HENHMETAFILE rc = 0;
448
449 Status = HEAP_strdupA2W ( &lpszMetaFileW, lpszMetaFile );
450 if (!NT_SUCCESS (Status))
451 SetLastError (RtlNtStatusToDosError(Status));
452 else
453 {
454 rc = NULL;
455
456 HEAP_free ( lpszMetaFileW );
457 }
458
459 return rc;
460 }
461
462
463 /*
464 * @unimplemented
465 */
466 UINT
467 WINAPI
468 GetEnhMetaFileDescriptionA(
469 HENHMETAFILE hemf,
470 UINT cchBuffer,
471 LPSTR lpszDescription)
472 {
473 NTSTATUS Status;
474 LPWSTR lpszDescriptionW;
475
476 if ( lpszDescription && cchBuffer )
477 {
478 lpszDescriptionW = (LPWSTR)HEAP_alloc ( cchBuffer*sizeof(WCHAR) );
479 if ( !lpszDescriptionW )
480 {
481 SetLastError (RtlNtStatusToDosError(STATUS_NO_MEMORY));
482 return 0;
483 }
484 }
485 else
486 lpszDescriptionW = NULL;
487
488 if ( lpszDescription && cchBuffer )
489 {
490 Status = RtlUnicodeToMultiByteN ( lpszDescription,
491 cchBuffer,
492 NULL,
493 lpszDescriptionW,
494 cchBuffer );
495 HEAP_free ( lpszDescriptionW );
496 if ( !NT_SUCCESS(Status) )
497 {
498 SetLastError (RtlNtStatusToDosError(Status));
499 return 0;
500 }
501 }
502
503 return 0;
504 }
505
506
507
508 /* Unimplemented functions */
509
510 HENHMETAFILE
511 WINAPI
512 CopyEnhMetaFileW(
513 HENHMETAFILE hemfSrc,
514 LPCWSTR lpszFile)
515 {
516 UNIMPLEMENTED;
517 return 0;
518 }
519
520
521 HENHMETAFILE
522 WINAPI
523 GetEnhMetaFileW(
524 LPCWSTR lpszMetaFile)
525 {
526 UNIMPLEMENTED;
527 return 0;
528 }
529
530
531 UINT
532 WINAPI
533 GetEnhMetaFileDescriptionW(
534 HENHMETAFILE hemf,
535 UINT cchBuffer,
536 LPWSTR lpszDescription)
537 {
538 UNIMPLEMENTED;
539 return 0;
540 }
541
542
543 HDC
544 WINAPI
545 CreateEnhMetaFileW(
546 HDC hdcRef,
547 LPCWSTR lpFileName,
548 LPCRECT lpRect,
549 LPCWSTR lpDescription)
550 {
551 UNIMPLEMENTED;
552 return 0;
553 }