xref: /reactos/win32ss/gdi/gdi32/objects/enhmfile.c (revision 4f0b8d3d)
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 }
554