4 * Copyright 1996 Ulrich Schmid
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #define WIN32_LEAN_AND_MEAN
25 #include "wine/winuser16.h"
29 #define MALLOCHUNK 1000
31 #define GET_USHORT(buffer, i)\
32 (((BYTE)((buffer)[(i)]) + 0x100 * (BYTE)((buffer)[(i)+1])))
33 #define GET_SHORT(buffer, i)\
34 (((BYTE)((buffer)[(i)]) + 0x100 * (signed char)((buffer)[(i)+1])))
35 #define PUT_SHORT(buffer, i, s)\
36 (((buffer)[(i)] = (s) & 0xff, (buffer)[(i)+1] = ((s) >> 8) & 0xff))
38 static BOOL
GRPFILE_ReadFileToBuffer(LPCSTR
, HLOCAL
*, INT
*);
39 static HLOCAL
GRPFILE_ScanGroup(LPCSTR
, INT
, LPCSTR
, BOOL
);
40 static HLOCAL
GRPFILE_ScanProgram(LPCSTR
, INT
, LPCSTR
, INT
,
41 LPCSTR
, HLOCAL
,LPCSTR
);
42 static BOOL
GRPFILE_DoWriteGroupFile(HFILE file
, PROGGROUP
*group
);
44 /***********************************************************************
46 * GRPFILE_ModifyFileName
48 * Change extension `.grp' to `.gr'
51 static VOID
GRPFILE_ModifyFileName(LPSTR lpszNewName
, LPCSTR lpszOrigName
,
52 INT nSize
, BOOL bModify
)
54 lstrcpyn(lpszNewName
, lpszOrigName
, nSize
);
55 lpszNewName
[nSize
-1] = '\0';
57 if (!lstrcmpi(lpszNewName
+ strlen(lpszNewName
) - 4, ".grp"))
58 lpszNewName
[strlen(lpszNewName
) - 1] = '\0';
61 /***********************************************************************
63 * GRPFILE_ReadGroupFile
66 HLOCAL
GRPFILE_ReadGroupFile(LPCSTR lpszPath
)
68 CHAR szPath_gr
[MAX_PATHNAME_LEN
];
69 BOOL bFileNameModified
= FALSE
;
71 HLOCAL hBuffer
, hGroup
;
74 /* if `.gr' file exists use that */
75 GRPFILE_ModifyFileName(szPath_gr
, lpszPath
, MAX_PATHNAME_LEN
, TRUE
);
76 if (OpenFile(szPath_gr
, &dummy
, OF_EXIST
) != HFILE_ERROR
)
79 bFileNameModified
= TRUE
;
82 /* Read the whole file into a buffer */
83 if (!GRPFILE_ReadFileToBuffer(lpszPath
, &hBuffer
, &size
))
85 MAIN_MessageBoxIDS_s(IDS_GRPFILE_READ_ERROR_s
, lpszPath
, IDS_ERROR
, MB_YESNO
);
89 /* Interpret buffer */
90 hGroup
= GRPFILE_ScanGroup(LocalLock(hBuffer
), size
,
91 lpszPath
, bFileNameModified
);
93 MAIN_MessageBoxIDS_s(IDS_GRPFILE_READ_ERROR_s
, lpszPath
, IDS_ERROR
, MB_YESNO
);
100 /***********************************************************************
102 * GRPFILE_ReadFileToBuffer
105 static BOOL
GRPFILE_ReadFileToBuffer(LPCSTR path
, HLOCAL
*phBuffer
,
110 HLOCAL hBuffer
, hNewBuffer
;
113 file
=_lopen(path
, OF_READ
);
114 if (file
== HFILE_ERROR
) return FALSE
;
117 hBuffer
= LocalAlloc(LMEM_FIXED
, size
+ MALLOCHUNK
+ 1);
118 if (!hBuffer
) return FALSE
;
119 buffer
= LocalLock(hBuffer
);
121 while ((len
= _lread(file
, buffer
+ size
, MALLOCHUNK
))
125 hNewBuffer
= LocalReAlloc(hBuffer
, size
+ MALLOCHUNK
+ 1,
132 hBuffer
= hNewBuffer
;
133 buffer
= LocalLock(hBuffer
);
138 if (len
== (UINT
)HFILE_ERROR
)
152 /***********************************************************************
156 static HLOCAL
GRPFILE_ScanGroup(LPCSTR buffer
, INT size
,
158 BOOL bModifiedFileName
)
164 INT x
, y
, width
, height
, iconx
, icony
, nCmdShow
;
165 INT number_of_programs
;
166 BOOL bOverwriteFileOk
;
168 if (buffer
[0] != 'P' || buffer
[1] != 'M') return(0);
169 if (buffer
[2] == 'C' && buffer
[3] == 'C')
170 /* original with checksum */
171 bOverwriteFileOk
= FALSE
;
172 else if (buffer
[2] == 'X' && buffer
[3] == 'X')
173 /* modified without checksum */
174 bOverwriteFileOk
= TRUE
;
177 /* checksum = GET_USHORT(buffer, 4) (ignored) */
179 extension
= buffer
+ GET_USHORT(buffer
, 6);
180 if (extension
== buffer
+ size
) extension
= 0;
181 else if (extension
+ 6 > buffer
+ size
) return(0);
183 nCmdShow
= GET_USHORT(buffer
, 8);
184 x
= GET_SHORT(buffer
, 10);
185 y
= GET_SHORT(buffer
, 12);
186 width
= GET_USHORT(buffer
, 14);
187 height
= GET_USHORT(buffer
, 16);
188 iconx
= GET_SHORT(buffer
, 18);
189 icony
= GET_SHORT(buffer
, 20);
190 lpszName
= buffer
+ GET_USHORT(buffer
, 22);
191 if (lpszName
>= buffer
+ size
) return(0);
193 /* unknown bytes 24 - 31 ignored */
195 Unknown bytes should be:
196 wLogPixelsX = GET_SHORT(buffer, 24);
197 wLogPixelsY = GET_SHORT(buffer, 26);
198 byBitsPerPixel = byte at 28;
199 byPlanes = byte at 29;
200 wReserved = GET_SHORT(buffer, 30);
203 hGroup
= GROUP_AddGroup(lpszName
, lpszGrpFile
, nCmdShow
, x
, y
,
204 width
, height
, iconx
, icony
,
205 bModifiedFileName
, bOverwriteFileOk
,
207 if (!hGroup
) return(0);
209 number_of_programs
= GET_USHORT(buffer
, 32);
210 if (2 * number_of_programs
+ 34 > size
) return(0);
211 for (i
=0, seqnum
=0; i
< number_of_programs
; i
++, seqnum
++)
213 LPCSTR program_ptr
= buffer
+ GET_USHORT(buffer
, 34 + 2*i
);
214 if (program_ptr
+ 24 > buffer
+ size
) return(0);
215 if (!GET_USHORT(buffer
, 34 + 2*i
)) continue;
216 if (!GRPFILE_ScanProgram(buffer
, size
, program_ptr
, seqnum
,
217 extension
, hGroup
, lpszGrpFile
))
219 GROUP_DeleteGroup(hGroup
);
224 /* FIXME shouldn't be necessary */
225 GROUP_ShowGroupWindow(hGroup
);
230 /***********************************************************************
231 * GRPFILE_ScanProgram
234 static HLOCAL
GRPFILE_ScanProgram(LPCSTR buffer
, INT size
,
235 LPCSTR program_ptr
, INT seqnum
,
236 LPCSTR extension
, HLOCAL hGroup
,
241 LPCSTR lpszName
, lpszCmdLine
, lpszIconFile
, lpszWorkDir
;
242 LPCSTR iconinfo_ptr
, iconANDbits_ptr
, iconXORbits_ptr
;
243 INT x
, y
, nIconIndex
, iconANDsize
, iconXORsize
;
244 INT nHotKey
, nCmdShow
;
245 CURSORICONINFO iconinfo
;
247 x
= GET_SHORT(program_ptr
, 0);
248 y
= GET_SHORT(program_ptr
, 2);
249 nIconIndex
= GET_USHORT(program_ptr
, 4);
251 /* FIXME is this correct ?? */
252 icontype
= GET_USHORT(program_ptr
, 6);
256 MAIN_MessageBoxIDS_s(IDS_UNKNOWN_FEATURE_s
, lpszGrpFile
,
259 iconXORsize
= GET_USHORT(program_ptr
, 8);
260 iconANDsize
= GET_USHORT(program_ptr
, 10) / 8;
261 iconinfo_ptr
= buffer
+ GET_USHORT(program_ptr
, 12);
262 iconXORbits_ptr
= buffer
+ GET_USHORT(program_ptr
, 14);
263 iconANDbits_ptr
= buffer
+ GET_USHORT(program_ptr
, 16);
264 iconinfo
.ptHotSpot
.x
= GET_USHORT(iconinfo_ptr
, 0);
265 iconinfo
.ptHotSpot
.y
= GET_USHORT(iconinfo_ptr
, 2);
266 iconinfo
.nWidth
= GET_USHORT(iconinfo_ptr
, 4);
267 iconinfo
.nHeight
= GET_USHORT(iconinfo_ptr
, 6);
268 iconinfo
.nWidthBytes
= GET_USHORT(iconinfo_ptr
, 8);
269 iconinfo
.bPlanes
= GET_USHORT(iconinfo_ptr
, 10);
270 iconinfo
.bBitsPerPixel
= GET_USHORT(iconinfo_ptr
, 11);
273 iconANDsize
= GET_USHORT(program_ptr
, 8);
274 iconXORsize
= GET_USHORT(program_ptr
, 10);
275 iconinfo_ptr
= buffer
+ GET_USHORT(program_ptr
, 12);
276 iconANDbits_ptr
= buffer
+ GET_USHORT(program_ptr
, 14);
277 iconXORbits_ptr
= buffer
+ GET_USHORT(program_ptr
, 16);
278 iconinfo
.ptHotSpot
.x
= GET_USHORT(iconinfo_ptr
, 0);
279 iconinfo
.ptHotSpot
.y
= GET_USHORT(iconinfo_ptr
, 2);
280 iconinfo
.nWidth
= GET_USHORT(iconinfo_ptr
, 4);
281 iconinfo
.nHeight
= GET_USHORT(iconinfo_ptr
, 6);
282 iconinfo
.nWidthBytes
= GET_USHORT(iconinfo_ptr
, 8) * 8;
283 iconinfo
.bPlanes
= GET_USHORT(iconinfo_ptr
, 10);
284 iconinfo
.bBitsPerPixel
= GET_USHORT(iconinfo_ptr
, 11);
287 if (iconANDbits_ptr
+ iconANDsize
> buffer
+ size
||
288 iconXORbits_ptr
+ iconXORsize
> buffer
+ size
) return(0);
290 hIcon
= CreateIcon( Globals
.hInstance
, iconinfo
.nWidth
, iconinfo
.nHeight
,
291 iconinfo
.bPlanes
, iconinfo
.bBitsPerPixel
,
292 iconANDbits_ptr
, iconXORbits_ptr
);
294 lpszName
= buffer
+ GET_USHORT(program_ptr
, 18);
295 lpszCmdLine
= buffer
+ GET_USHORT(program_ptr
, 20);
296 lpszIconFile
= buffer
+ GET_USHORT(program_ptr
, 22);
297 if (iconinfo_ptr
+ 6 > buffer
+ size
||
298 lpszName
> buffer
+ size
||
299 lpszCmdLine
> buffer
+ size
||
300 lpszIconFile
> buffer
+ size
) return(0);
302 /* Scan Extensions */
305 nCmdShow
= SW_SHOWNORMAL
;
308 LPCSTR ptr
= extension
;
309 while (ptr
+ 6 <= buffer
+ size
)
311 UINT type
= GET_USHORT(ptr
, 0);
312 UINT number
= GET_USHORT(ptr
, 2);
313 UINT skip
= GET_USHORT(ptr
, 4);
315 if (number
== seqnum
)
320 if (ptr
+ 10 > buffer
+ size
) return(0);
321 if (ptr
[6] != 'P' || ptr
[7] != 'M' ||
322 ptr
[8] != 'C' || ptr
[9] != 'C') return(0);
325 lpszWorkDir
= ptr
+ 6;
328 if (ptr
+ 8 > buffer
+ size
) return(0);
329 nHotKey
= GET_USHORT(ptr
, 6);
332 if (ptr
+ 8 > buffer
+ size
) return(0);
333 nCmdShow
= GET_USHORT(ptr
, 6);
336 MAIN_MessageBoxIDS_s(IDS_UNKNOWN_FEATURE_s
,
337 lpszGrpFile
, IDS_WARNING
, MB_OK
);
345 return (PROGRAM_AddProgram(hGroup
, hIcon
, lpszName
, x
, y
,
346 lpszCmdLine
, lpszIconFile
,
347 nIconIndex
, lpszWorkDir
,
351 /***********************************************************************
353 * GRPFILE_WriteGroupFile
356 BOOL
GRPFILE_WriteGroupFile(HLOCAL hGroup
)
358 CHAR szPath
[MAX_PATHNAME_LEN
];
359 PROGGROUP
*group
= LocalLock(hGroup
);
364 GRPFILE_ModifyFileName(szPath
, LocalLock(group
->hGrpFile
),
366 group
->bFileNameModified
);
368 /* Try not to overwrite original files */
370 /* group->bOverwriteFileOk == TRUE only if a file has the modified format */
371 if (!group
->bOverwriteFileOk
&&
372 OpenFile(szPath
, &dummy
, OF_EXIST
) != HFILE_ERROR
)
374 /* Original file exists, try `.gr' extension */
375 GRPFILE_ModifyFileName(szPath
, LocalLock(group
->hGrpFile
),
376 MAX_PATHNAME_LEN
, TRUE
);
377 if (OpenFile(szPath
, &dummy
, OF_EXIST
) != HFILE_ERROR
)
379 /* File exists. Do not overwrite */
380 MAIN_MessageBoxIDS_s(IDS_FILE_NOT_OVERWRITTEN_s
, szPath
,
384 /* Inform about the modified file name */
386 MAIN_MessageBoxIDS_s(IDS_SAVE_GROUP_AS_s
, szPath
, IDS_INFO
,
387 MB_OKCANCEL
| MB_ICONINFORMATION
))
392 /* Warn about the (possible) incompatibility */
393 CHAR msg
[MAX_PATHNAME_LEN
+ 200];
395 "Group files written by this DRAFT Program Manager "
396 "possibly cannot be read by the Microsoft Program Manager!!\n"
397 "Are you sure to write %s?", szPath
);
398 if (IDOK
!= MessageBox(Globals
.hMainWnd
, msg
, "WARNING",
399 MB_OKCANCEL
| MB_DEFBUTTON2
)) return FALSE
;
403 if (OpenFile(szPath
, &dummy
, OF_EXIST
) == HFILE_ERROR
)
405 CHAR msg
[MAX_PATHNAME_LEN
+ 200];
406 wsprintf(msg
, "Cause of a bug you must now touch the file %s\n", szPath
);
407 MessageBox(Globals
.hMainWnd
, msg
, "", MB_OK
);
411 file
= _lopen(szPath
, OF_WRITE
);
412 if (file
!= HFILE_ERROR
)
414 ret
= GRPFILE_DoWriteGroupFile(file
, group
);
420 MAIN_MessageBoxIDS_s(IDS_FILE_WRITE_ERROR_s
, szPath
, IDS_ERROR
, MB_OK
);
425 /***********************************************************************
427 * GRPFILE_CalculateSizes
430 static VOID
GRPFILE_CalculateSizes(PROGRAM
*program
,
431 INT
*Progs
, INT
*Icons
)
433 CURSORICONINFO
*iconinfo
= LocalLock(program
->hIcon
);
434 INT sizeXor
= iconinfo
->nHeight
* iconinfo
->nWidthBytes
;
435 INT sizeAnd
= iconinfo
->nHeight
* ((iconinfo
->nWidth
+ 15) / 16 * 2);
438 *Progs
+= lstrlen(LocalLock(program
->hName
)) + 1;
439 *Progs
+= lstrlen(LocalLock(program
->hCmdLine
)) + 1;
440 *Progs
+= lstrlen(LocalLock(program
->hIconFile
)) + 1;
442 *Icons
+= 12; /* IconInfo */
447 /***********************************************************************/
448 UINT16 GRPFILE_checksum
;
449 BOOL GRPFILE_checksum_half_word
;
450 BYTE GRPFILE_checksum_last_byte
;
451 /***********************************************************************
453 * GRPFILE_InitChecksum
456 static void GRPFILE_InitChecksum(void)
458 GRPFILE_checksum
= 0;
459 GRPFILE_checksum_half_word
= 0;
462 /***********************************************************************
464 * GRPFILE_GetChecksum
467 static UINT16
GRPFILE_GetChecksum(void)
469 return GRPFILE_checksum
;
472 /***********************************************************************
474 * GRPFILE_WriteWithChecksum
476 * Looks crazier than it is:
479 * chksum = cksum - 1. word;
480 * chksum = cksum - 2. word;
483 * if (filelen is even)
489 static UINT
GRPFILE_WriteWithChecksum(HFILE file
, LPCSTR str
, UINT size
)
492 if (GRPFILE_checksum_half_word
) {
493 GRPFILE_checksum
-= GRPFILE_checksum_last_byte
;
495 for (i
=0; i
< size
; i
++) {
496 if (GRPFILE_checksum_half_word
) {
497 GRPFILE_checksum
-= str
[i
] << 8;
499 GRPFILE_checksum
-= str
[i
];
501 GRPFILE_checksum_half_word
^= 1;
504 if (GRPFILE_checksum_half_word
) {
505 GRPFILE_checksum_last_byte
= str
[size
-1];
506 GRPFILE_checksum
+= GRPFILE_checksum_last_byte
;
509 return _lwrite(file
, str
, size
);
513 /***********************************************************************
515 * GRPFILE_DoWriteGroupFile
518 static BOOL
GRPFILE_DoWriteGroupFile(HFILE file
, PROGGROUP
*group
)
522 INT NumProg
, Title
, Progs
, Icons
, Extension
;
523 INT CurrProg
, CurrIcon
, nCmdShow
, ptr
, seqnum
;
525 LPCSTR lpszTitle
= LocalLock(group
->hName
);
529 GRPFILE_InitChecksum();
531 /* Calculate offsets */
535 need_extension
= FALSE
;
536 hProgram
= group
->hPrograms
;
539 PROGRAM
*program
= LocalLock(hProgram
);
540 LPCSTR lpszWorkDir
= LocalLock(program
->hWorkDir
);
543 GRPFILE_CalculateSizes(program
, &Icons
, &Extension
);
545 /* Set a flag if an extension is needed */
546 if (lpszWorkDir
[0] || program
->nHotKey
||
547 program
->nCmdShow
!= SW_SHOWNORMAL
) need_extension
= TRUE
;
549 hProgram
= program
->hNext
;
551 Title
= 34 + NumProg
* 2;
552 Progs
= Title
+ lstrlen(lpszTitle
) + 1;
562 PUT_SHORT(buffer
, 4, 0); /* Checksum zero for now, written later */
563 PUT_SHORT(buffer
, 6, Extension
);
564 /* Update group->nCmdShow */
565 if (IsIconic(group
->hWnd
)) nCmdShow
= SW_SHOWMINIMIZED
;
566 else if (IsZoomed(group
->hWnd
)) nCmdShow
= SW_SHOWMAXIMIZED
;
567 else nCmdShow
= SW_SHOWNORMAL
;
568 PUT_SHORT(buffer
, 8, nCmdShow
);
569 PUT_SHORT(buffer
, 10, group
->x
);
570 PUT_SHORT(buffer
, 12, group
->y
);
571 PUT_SHORT(buffer
, 14, group
->width
);
572 PUT_SHORT(buffer
, 16, group
->height
);
573 PUT_SHORT(buffer
, 18, group
->iconx
);
574 PUT_SHORT(buffer
, 20, group
->icony
);
575 PUT_SHORT(buffer
, 22, Title
);
576 PUT_SHORT(buffer
, 24, 0x0020); /* unknown */
577 PUT_SHORT(buffer
, 26, 0x0020); /* unknown */
578 PUT_SHORT(buffer
, 28, 0x0108); /* unknown */
579 PUT_SHORT(buffer
, 30, 0x0000); /* unknown */
580 PUT_SHORT(buffer
, 32, NumProg
);
582 if ((UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, buffer
, 34)) return FALSE
;
587 hProgram
= group
->hPrograms
;
590 PROGRAM
*program
= LocalLock(hProgram
);
592 PUT_SHORT(buffer
, 0, CurrProg
);
593 if ((UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, buffer
, 2))
596 GRPFILE_CalculateSizes(program
, &CurrProg
, &CurrIcon
);
597 hProgram
= program
->hNext
;
601 if ((UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, lpszTitle
,
602 lstrlen(lpszTitle
) + 1))
605 /* Program entries */
608 hProgram
= group
->hPrograms
;
611 PROGRAM
*program
= LocalLock(hProgram
);
612 CURSORICONINFO
*iconinfo
= LocalLock(program
->hIcon
);
613 LPCSTR Name
= LocalLock(program
->hName
);
614 LPCSTR CmdLine
= LocalLock(program
->hCmdLine
);
615 LPCSTR IconFile
= LocalLock(program
->hIconFile
);
616 INT sizeXor
= iconinfo
->nHeight
* iconinfo
->nWidthBytes
;
617 INT sizeAnd
= iconinfo
->nHeight
* ((iconinfo
->nWidth
+ 15) / 16 * 2);
619 PUT_SHORT(buffer
, 0, program
->x
);
620 PUT_SHORT(buffer
, 2, program
->y
);
621 PUT_SHORT(buffer
, 4, program
->nIconIndex
);
622 PUT_SHORT(buffer
, 6, 0x048c); /* unknown */
623 PUT_SHORT(buffer
, 8, sizeXor
);
624 PUT_SHORT(buffer
, 10, sizeAnd
* 8);
625 PUT_SHORT(buffer
, 12, CurrIcon
);
626 PUT_SHORT(buffer
, 14, CurrIcon
+ 12 + sizeAnd
);
627 PUT_SHORT(buffer
, 16, CurrIcon
+ 12);
629 PUT_SHORT(buffer
, 18, ptr
);
630 ptr
+= lstrlen(Name
) + 1;
631 PUT_SHORT(buffer
, 20, ptr
);
632 ptr
+= lstrlen(CmdLine
) + 1;
633 PUT_SHORT(buffer
, 22, ptr
);
635 if ((UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, buffer
, 24) ||
636 (UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, Name
, lstrlen(Name
) + 1) ||
637 (UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, CmdLine
, lstrlen(CmdLine
) + 1) ||
638 (UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, IconFile
, lstrlen(IconFile
) + 1))
641 GRPFILE_CalculateSizes(program
, &CurrProg
, &CurrIcon
);
642 hProgram
= program
->hNext
;
646 #if 0 /* FIXME: this is broken anyway */
647 hProgram
= group
->hPrograms
;
650 PROGRAM
*program
= LocalLock(hProgram
);
651 CURSORICONINFO
*iconinfo
= LocalLock(program
->hIcon
);
652 LPVOID XorBits
, AndBits
;
653 INT sizeXor
= iconinfo
->nHeight
* iconinfo
->nWidthBytes
;
654 INT sizeAnd
= iconinfo
->nHeight
* ((iconinfo
->nWidth
+ 15) / 16 * 2);
655 /* DumpIcon16(LocalLock(program->hIcon), 0, &XorBits, &AndBits);*/
657 PUT_SHORT(buffer
, 0, iconinfo
->ptHotSpot
.x
);
658 PUT_SHORT(buffer
, 2, iconinfo
->ptHotSpot
.y
);
659 PUT_SHORT(buffer
, 4, iconinfo
->nWidth
);
660 PUT_SHORT(buffer
, 6, iconinfo
->nHeight
);
661 PUT_SHORT(buffer
, 8, iconinfo
->nWidthBytes
);
662 buffer
[10] = iconinfo
->bPlanes
;
663 buffer
[11] = iconinfo
->bBitsPerPixel
;
665 if ((UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, buffer
, 12) ||
666 (UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, AndBits
, sizeAnd
) ||
667 (UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, XorBits
, sizeXor
)) return FALSE
;
669 hProgram
= program
->hNext
;
675 /* write `PMCC' extension */
676 PUT_SHORT(buffer
, 0, 0x8000);
677 PUT_SHORT(buffer
, 2, 0xffff);
678 PUT_SHORT(buffer
, 4, 0x000a);
679 buffer
[6] = 'P', buffer
[7] = 'M';
680 buffer
[8] = 'C', buffer
[9] = 'C';
681 if ((UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, buffer
, 10))
685 hProgram
= group
->hPrograms
;
688 PROGRAM
*program
= LocalLock(hProgram
);
689 LPCSTR lpszWorkDir
= LocalLock(program
->hWorkDir
);
691 /* Working directory */
694 PUT_SHORT(buffer
, 0, 0x8101);
695 PUT_SHORT(buffer
, 2, seqnum
);
696 PUT_SHORT(buffer
, 4, 7 + lstrlen(lpszWorkDir
));
697 if ((UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, buffer
, 6) ||
698 (UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, lpszWorkDir
, lstrlen(lpszWorkDir
) + 1))
703 if (program
->nHotKey
)
705 PUT_SHORT(buffer
, 0, 0x8102);
706 PUT_SHORT(buffer
, 2, seqnum
);
707 PUT_SHORT(buffer
, 4, 8);
708 PUT_SHORT(buffer
, 6, program
->nHotKey
);
709 if ((UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, buffer
, 8)) return FALSE
;
713 if (program
->nCmdShow
)
715 PUT_SHORT(buffer
, 0, 0x8103);
716 PUT_SHORT(buffer
, 2, seqnum
);
717 PUT_SHORT(buffer
, 4, 8);
718 PUT_SHORT(buffer
, 6, program
->nCmdShow
);
719 if ((UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, buffer
, 8)) return FALSE
;
723 hProgram
= program
->hNext
;
726 /* Write `End' extension */
727 PUT_SHORT(buffer
, 0, 0xffff);
728 PUT_SHORT(buffer
, 2, 0xffff);
729 PUT_SHORT(buffer
, 4, 0x0000);
730 if ((UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, buffer
, 6)) return FALSE
;
733 checksum
= GRPFILE_GetChecksum();
734 _llseek(file
, 4, SEEK_SET
);
735 PUT_SHORT(buffer
, 0, checksum
);
736 _lwrite(file
, buffer
, 2);
741 /* Local Variables: */
742 /* c-file-style: "GNU" */