4 * Copyright 1996 Ulrich Schmid
9 #include "wine/winuser16.h"
13 #define MALLOCHUNK 1000
15 #define GET_USHORT(buffer, i)\
16 (((BYTE)((buffer)[(i)]) + 0x100 * (BYTE)((buffer)[(i)+1])))
17 #define GET_SHORT(buffer, i)\
18 (((BYTE)((buffer)[(i)]) + 0x100 * (signed char)((buffer)[(i)+1])))
19 #define PUT_SHORT(buffer, i, s)\
20 (((buffer)[(i)] = (s) & 0xff, (buffer)[(i)+1] = ((s) >> 8) & 0xff))
22 static BOOL
GRPFILE_ReadFileToBuffer(LPCSTR
, HLOCAL
*, INT
*);
23 static HLOCAL
GRPFILE_ScanGroup(LPCSTR
, INT
, LPCSTR
, BOOL
);
24 static HLOCAL
GRPFILE_ScanProgram(LPCSTR
, INT
, LPCSTR
, INT
,
25 LPCSTR
, HLOCAL
,LPCSTR
);
26 static BOOL
GRPFILE_DoWriteGroupFile(HFILE file
, PROGGROUP
*group
);
28 /***********************************************************************
30 * GRPFILE_ModifyFileName
32 * Change extension `.grp' to `.gr'
35 static VOID
GRPFILE_ModifyFileName(LPSTR lpszNewName
, LPCSTR lpszOrigName
,
36 INT nSize
, BOOL bModify
)
38 lstrcpyn(lpszNewName
, lpszOrigName
, nSize
);
39 lpszNewName
[nSize
-1] = '\0';
41 if (!lstrcmpi(lpszNewName
+ strlen(lpszNewName
) - 4, ".grp"))
42 lpszNewName
[strlen(lpszNewName
) - 1] = '\0';
45 /***********************************************************************
47 * GRPFILE_ReadGroupFile
50 HLOCAL
GRPFILE_ReadGroupFile(LPCSTR lpszPath
)
52 CHAR szPath_gr
[MAX_PATHNAME_LEN
];
53 BOOL bFileNameModified
= FALSE
;
55 HLOCAL hBuffer
, hGroup
;
58 /* if `.gr' file exists use that */
59 GRPFILE_ModifyFileName(szPath_gr
, lpszPath
, MAX_PATHNAME_LEN
, TRUE
);
60 if (OpenFile(szPath_gr
, &dummy
, OF_EXIST
) != HFILE_ERROR
)
63 bFileNameModified
= TRUE
;
66 /* Read the whole file into a buffer */
67 if (!GRPFILE_ReadFileToBuffer(lpszPath
, &hBuffer
, &size
))
69 MAIN_MessageBoxIDS_s(IDS_GRPFILE_READ_ERROR_s
, lpszPath
, IDS_ERROR
, MB_YESNO
);
73 /* Interpret buffer */
74 hGroup
= GRPFILE_ScanGroup(LocalLock(hBuffer
), size
,
75 lpszPath
, bFileNameModified
);
77 MAIN_MessageBoxIDS_s(IDS_GRPFILE_READ_ERROR_s
, lpszPath
, IDS_ERROR
, MB_YESNO
);
84 /***********************************************************************
86 * GRPFILE_ReadFileToBuffer
89 static BOOL
GRPFILE_ReadFileToBuffer(LPCSTR path
, HLOCAL
*phBuffer
,
94 HLOCAL hBuffer
, hNewBuffer
;
97 file
=_lopen(path
, OF_READ
);
98 if (file
== HFILE_ERROR
) return FALSE
;
101 hBuffer
= LocalAlloc(LMEM_FIXED
, size
+ MALLOCHUNK
+ 1);
102 if (!hBuffer
) return FALSE
;
103 buffer
= LocalLock(hBuffer
);
105 while ((len
= _lread(file
, buffer
+ size
, MALLOCHUNK
))
109 hNewBuffer
= LocalReAlloc(hBuffer
, size
+ MALLOCHUNK
+ 1,
116 hBuffer
= hNewBuffer
;
117 buffer
= LocalLock(hBuffer
);
122 if (len
== (UINT
)HFILE_ERROR
)
136 /***********************************************************************
140 static HLOCAL
GRPFILE_ScanGroup(LPCSTR buffer
, INT size
,
142 BOOL bModifiedFileName
)
148 INT x
, y
, width
, height
, iconx
, icony
, nCmdShow
;
149 INT number_of_programs
;
150 BOOL bOverwriteFileOk
;
152 if (buffer
[0] != 'P' || buffer
[1] != 'M') return(0);
153 if (buffer
[2] == 'C' && buffer
[3] == 'C')
154 /* original with checksum */
155 bOverwriteFileOk
= FALSE
;
156 else if (buffer
[2] == 'X' && buffer
[3] == 'X')
157 /* modified without checksum */
158 bOverwriteFileOk
= TRUE
;
161 /* checksum = GET_USHORT(buffer, 4) (ignored) */
163 extension
= buffer
+ GET_USHORT(buffer
, 6);
164 if (extension
== buffer
+ size
) extension
= 0;
165 else if (extension
+ 6 > buffer
+ size
) return(0);
167 nCmdShow
= GET_USHORT(buffer
, 8);
168 x
= GET_SHORT(buffer
, 10);
169 y
= GET_SHORT(buffer
, 12);
170 width
= GET_USHORT(buffer
, 14);
171 height
= GET_USHORT(buffer
, 16);
172 iconx
= GET_SHORT(buffer
, 18);
173 icony
= GET_SHORT(buffer
, 20);
174 lpszName
= buffer
+ GET_USHORT(buffer
, 22);
175 if (lpszName
>= buffer
+ size
) return(0);
177 /* unknown bytes 24 - 31 ignored */
179 Unknown bytes should be:
180 wLogPixelsX = GET_SHORT(buffer, 24);
181 wLogPixelsY = GET_SHORT(buffer, 26);
182 byBitsPerPixel = byte at 28;
183 byPlanes = byte at 29;
184 wReserved = GET_SHORT(buffer, 30);
187 hGroup
= GROUP_AddGroup(lpszName
, lpszGrpFile
, nCmdShow
, x
, y
,
188 width
, height
, iconx
, icony
,
189 bModifiedFileName
, bOverwriteFileOk
,
191 if (!hGroup
) return(0);
193 number_of_programs
= GET_USHORT(buffer
, 32);
194 if (2 * number_of_programs
+ 34 > size
) return(0);
195 for (i
=0, seqnum
=0; i
< number_of_programs
; i
++, seqnum
++)
197 LPCSTR program_ptr
= buffer
+ GET_USHORT(buffer
, 34 + 2*i
);
198 if (program_ptr
+ 24 > buffer
+ size
) return(0);
199 if (!GET_USHORT(buffer
, 34 + 2*i
)) continue;
200 if (!GRPFILE_ScanProgram(buffer
, size
, program_ptr
, seqnum
,
201 extension
, hGroup
, lpszGrpFile
))
203 GROUP_DeleteGroup(hGroup
);
208 /* FIXME shouldn't be necessary */
209 GROUP_ShowGroupWindow(hGroup
);
214 /***********************************************************************
215 * GRPFILE_ScanProgram
218 static HLOCAL
GRPFILE_ScanProgram(LPCSTR buffer
, INT size
,
219 LPCSTR program_ptr
, INT seqnum
,
220 LPCSTR extension
, HLOCAL hGroup
,
225 LPCSTR lpszName
, lpszCmdLine
, lpszIconFile
, lpszWorkDir
;
226 LPCSTR iconinfo_ptr
, iconANDbits_ptr
, iconXORbits_ptr
;
227 INT x
, y
, nIconIndex
, iconANDsize
, iconXORsize
;
228 INT nHotKey
, nCmdShow
;
229 CURSORICONINFO iconinfo
;
231 x
= GET_SHORT(program_ptr
, 0);
232 y
= GET_SHORT(program_ptr
, 2);
233 nIconIndex
= GET_USHORT(program_ptr
, 4);
235 /* FIXME is this correct ?? */
236 icontype
= GET_USHORT(program_ptr
, 6);
240 MAIN_MessageBoxIDS_s(IDS_UNKNOWN_FEATURE_s
, lpszGrpFile
,
243 iconXORsize
= GET_USHORT(program_ptr
, 8);
244 iconANDsize
= GET_USHORT(program_ptr
, 10) / 8;
245 iconinfo_ptr
= buffer
+ GET_USHORT(program_ptr
, 12);
246 iconXORbits_ptr
= buffer
+ GET_USHORT(program_ptr
, 14);
247 iconANDbits_ptr
= buffer
+ GET_USHORT(program_ptr
, 16);
248 iconinfo
.ptHotSpot
.x
= GET_USHORT(iconinfo_ptr
, 0);
249 iconinfo
.ptHotSpot
.y
= GET_USHORT(iconinfo_ptr
, 2);
250 iconinfo
.nWidth
= GET_USHORT(iconinfo_ptr
, 4);
251 iconinfo
.nHeight
= GET_USHORT(iconinfo_ptr
, 6);
252 iconinfo
.nWidthBytes
= GET_USHORT(iconinfo_ptr
, 8);
253 iconinfo
.bPlanes
= GET_USHORT(iconinfo_ptr
, 10);
254 iconinfo
.bBitsPerPixel
= GET_USHORT(iconinfo_ptr
, 11);
257 iconANDsize
= GET_USHORT(program_ptr
, 8);
258 iconXORsize
= GET_USHORT(program_ptr
, 10);
259 iconinfo_ptr
= buffer
+ GET_USHORT(program_ptr
, 12);
260 iconANDbits_ptr
= buffer
+ GET_USHORT(program_ptr
, 14);
261 iconXORbits_ptr
= buffer
+ GET_USHORT(program_ptr
, 16);
262 iconinfo
.ptHotSpot
.x
= GET_USHORT(iconinfo_ptr
, 0);
263 iconinfo
.ptHotSpot
.y
= GET_USHORT(iconinfo_ptr
, 2);
264 iconinfo
.nWidth
= GET_USHORT(iconinfo_ptr
, 4);
265 iconinfo
.nHeight
= GET_USHORT(iconinfo_ptr
, 6);
266 iconinfo
.nWidthBytes
= GET_USHORT(iconinfo_ptr
, 8) * 8;
267 iconinfo
.bPlanes
= GET_USHORT(iconinfo_ptr
, 10);
268 iconinfo
.bBitsPerPixel
= GET_USHORT(iconinfo_ptr
, 11);
271 if (iconANDbits_ptr
+ iconANDsize
> buffer
+ size
||
272 iconXORbits_ptr
+ iconXORsize
> buffer
+ size
) return(0);
274 hIcon
= CreateCursorIconIndirect16(Globals
.hInstance
, &iconinfo
,
275 (LPSTR
)iconANDbits_ptr
,
276 (LPSTR
)iconXORbits_ptr
);
278 lpszName
= buffer
+ GET_USHORT(program_ptr
, 18);
279 lpszCmdLine
= buffer
+ GET_USHORT(program_ptr
, 20);
280 lpszIconFile
= buffer
+ GET_USHORT(program_ptr
, 22);
281 if (iconinfo_ptr
+ 6 > buffer
+ size
||
282 lpszName
> buffer
+ size
||
283 lpszCmdLine
> buffer
+ size
||
284 lpszIconFile
> buffer
+ size
) return(0);
286 /* Scan Extensions */
289 nCmdShow
= SW_SHOWNORMAL
;
292 LPCSTR ptr
= extension
;
293 while (ptr
+ 6 <= buffer
+ size
)
295 UINT type
= GET_USHORT(ptr
, 0);
296 UINT number
= GET_USHORT(ptr
, 2);
297 UINT skip
= GET_USHORT(ptr
, 4);
299 if (number
== seqnum
)
304 if (ptr
+ 10 > buffer
+ size
) return(0);
305 if (ptr
[6] != 'P' || ptr
[7] != 'M' ||
306 ptr
[8] != 'C' || ptr
[9] != 'C') return(0);
309 lpszWorkDir
= ptr
+ 6;
312 if (ptr
+ 8 > buffer
+ size
) return(0);
313 nHotKey
= GET_USHORT(ptr
, 6);
316 if (ptr
+ 8 > buffer
+ size
) return(0);
317 nCmdShow
= GET_USHORT(ptr
, 6);
320 MAIN_MessageBoxIDS_s(IDS_UNKNOWN_FEATURE_s
,
321 lpszGrpFile
, IDS_WARNING
, MB_OK
);
329 return (PROGRAM_AddProgram(hGroup
, hIcon
, lpszName
, x
, y
,
330 lpszCmdLine
, lpszIconFile
,
331 nIconIndex
, lpszWorkDir
,
335 /***********************************************************************
337 * GRPFILE_WriteGroupFile
340 BOOL
GRPFILE_WriteGroupFile(HLOCAL hGroup
)
342 CHAR szPath
[MAX_PATHNAME_LEN
];
343 PROGGROUP
*group
= LocalLock(hGroup
);
348 GRPFILE_ModifyFileName(szPath
, LocalLock(group
->hGrpFile
),
350 group
->bFileNameModified
);
352 /* Try not to overwrite original files */
354 /* group->bOverwriteFileOk == TRUE only if a file has the modified format */
355 if (!group
->bOverwriteFileOk
&&
356 OpenFile(szPath
, &dummy
, OF_EXIST
) != HFILE_ERROR
)
358 /* Original file exists, try `.gr' extension */
359 GRPFILE_ModifyFileName(szPath
, LocalLock(group
->hGrpFile
),
360 MAX_PATHNAME_LEN
, TRUE
);
361 if (OpenFile(szPath
, &dummy
, OF_EXIST
) != HFILE_ERROR
)
363 /* File exists. Do not overwrite */
364 MAIN_MessageBoxIDS_s(IDS_FILE_NOT_OVERWRITTEN_s
, szPath
,
368 /* Inform about the modified file name */
370 MAIN_MessageBoxIDS_s(IDS_SAVE_GROUP_AS_s
, szPath
, IDS_INFO
,
371 MB_OKCANCEL
| MB_ICONINFORMATION
))
376 /* Warn about the (possible) incompatibility */
377 CHAR msg
[MAX_PATHNAME_LEN
+ 200];
379 "Group files written by this DRAFT Program Manager "
380 "possibly cannot be read by the Microsoft Program Manager!!\n"
381 "Are you sure to write %s?", szPath
);
382 if (IDOK
!= MessageBox(Globals
.hMainWnd
, msg
, "WARNING",
383 MB_OKCANCEL
| MB_DEFBUTTON2
)) return FALSE
;
387 if (OpenFile(szPath
, &dummy
, OF_EXIST
) == HFILE_ERROR
)
389 CHAR msg
[MAX_PATHNAME_LEN
+ 200];
390 wsprintf(msg
, "Cause of a bug you must now touch the file %s\n", szPath
);
391 MessageBox(Globals
.hMainWnd
, msg
, "", MB_OK
);
395 file
= _lopen(szPath
, OF_WRITE
);
396 if (file
!= HFILE_ERROR
)
398 ret
= GRPFILE_DoWriteGroupFile(file
, group
);
404 MAIN_MessageBoxIDS_s(IDS_FILE_WRITE_ERROR_s
, szPath
, IDS_ERROR
, MB_OK
);
409 /***********************************************************************
411 * GRPFILE_CalculateSizes
414 static VOID
GRPFILE_CalculateSizes(PROGRAM
*program
,
415 INT
*Progs
, INT
*Icons
)
417 CURSORICONINFO
*iconinfo
= LocalLock(program
->hIcon
);
418 INT sizeXor
= iconinfo
->nHeight
* iconinfo
->nWidthBytes
;
419 INT sizeAnd
= iconinfo
->nHeight
* ((iconinfo
->nWidth
+ 15) / 16 * 2);
422 *Progs
+= lstrlen(LocalLock(program
->hName
)) + 1;
423 *Progs
+= lstrlen(LocalLock(program
->hCmdLine
)) + 1;
424 *Progs
+= lstrlen(LocalLock(program
->hIconFile
)) + 1;
426 *Icons
+= 12; /* IconInfo */
431 /***********************************************************************/
432 UINT16 GRPFILE_checksum
;
433 BOOL GRPFILE_checksum_half_word
;
434 BYTE GRPFILE_checksum_last_byte
;
435 /***********************************************************************
437 * GRPFILE_InitChecksum
440 static void GRPFILE_InitChecksum()
442 GRPFILE_checksum
= 0;
443 GRPFILE_checksum_half_word
= 0;
446 /***********************************************************************
448 * GRPFILE_GetChecksum
451 static UINT16
GRPFILE_GetChecksum()
453 return GRPFILE_checksum
;
456 /***********************************************************************
458 * GRPFILE_WriteWithChecksum
460 * Looks crazier than it is:
463 * chksum = cksum - 1. word;
464 * chksum = cksum - 2. word;
467 * if (filelen is even)
473 static UINT
GRPFILE_WriteWithChecksum(HFILE file
, LPCSTR str
, UINT size
)
476 if (GRPFILE_checksum_half_word
) {
477 GRPFILE_checksum
-= GRPFILE_checksum_last_byte
;
479 for (i
=0; i
< size
; i
++) {
480 if (GRPFILE_checksum_half_word
) {
481 GRPFILE_checksum
-= str
[i
] << 8;
483 GRPFILE_checksum
-= str
[i
];
485 GRPFILE_checksum_half_word
^= 1;
488 if (GRPFILE_checksum_half_word
) {
489 GRPFILE_checksum_last_byte
= str
[size
-1];
490 GRPFILE_checksum
+= GRPFILE_checksum_last_byte
;
493 return _lwrite(file
, str
, size
);
497 /***********************************************************************
499 * GRPFILE_DoWriteGroupFile
502 static BOOL
GRPFILE_DoWriteGroupFile(HFILE file
, PROGGROUP
*group
)
506 INT NumProg
, Title
, Progs
, Icons
, Extension
;
507 INT CurrProg
, CurrIcon
, nCmdShow
, ptr
, seqnum
;
509 LPCSTR lpszTitle
= LocalLock(group
->hName
);
513 GRPFILE_InitChecksum();
515 /* Calculate offsets */
519 need_extension
= FALSE
;
520 hProgram
= group
->hPrograms
;
523 PROGRAM
*program
= LocalLock(hProgram
);
524 LPCSTR lpszWorkDir
= LocalLock(program
->hWorkDir
);
527 GRPFILE_CalculateSizes(program
, &Icons
, &Extension
);
529 /* Set a flag if an extension is needed */
530 if (lpszWorkDir
[0] || program
->nHotKey
||
531 program
->nCmdShow
!= SW_SHOWNORMAL
) need_extension
= TRUE
;
533 hProgram
= program
->hNext
;
535 Title
= 34 + NumProg
* 2;
536 Progs
= Title
+ lstrlen(lpszTitle
) + 1;
546 PUT_SHORT(buffer
, 4, 0); /* Checksum zero for now, written later */
547 PUT_SHORT(buffer
, 6, Extension
);
548 /* Update group->nCmdShow */
549 if (IsIconic(group
->hWnd
)) nCmdShow
= SW_SHOWMINIMIZED
;
550 else if (IsZoomed(group
->hWnd
)) nCmdShow
= SW_SHOWMAXIMIZED
;
551 else nCmdShow
= SW_SHOWNORMAL
;
552 PUT_SHORT(buffer
, 8, nCmdShow
);
553 PUT_SHORT(buffer
, 10, group
->x
);
554 PUT_SHORT(buffer
, 12, group
->y
);
555 PUT_SHORT(buffer
, 14, group
->width
);
556 PUT_SHORT(buffer
, 16, group
->height
);
557 PUT_SHORT(buffer
, 18, group
->iconx
);
558 PUT_SHORT(buffer
, 20, group
->icony
);
559 PUT_SHORT(buffer
, 22, Title
);
560 PUT_SHORT(buffer
, 24, 0x0020); /* unknown */
561 PUT_SHORT(buffer
, 26, 0x0020); /* unknown */
562 PUT_SHORT(buffer
, 28, 0x0108); /* unknown */
563 PUT_SHORT(buffer
, 30, 0x0000); /* unknown */
564 PUT_SHORT(buffer
, 32, NumProg
);
566 if ((UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, buffer
, 34)) return FALSE
;
571 hProgram
= group
->hPrograms
;
574 PROGRAM
*program
= LocalLock(hProgram
);
576 PUT_SHORT(buffer
, 0, CurrProg
);
577 if ((UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, buffer
, 2))
580 GRPFILE_CalculateSizes(program
, &CurrProg
, &CurrIcon
);
581 hProgram
= program
->hNext
;
585 if ((UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, lpszTitle
,
586 lstrlen(lpszTitle
) + 1))
589 /* Program entries */
592 hProgram
= group
->hPrograms
;
595 PROGRAM
*program
= LocalLock(hProgram
);
596 CURSORICONINFO
*iconinfo
= LocalLock(program
->hIcon
);
597 LPCSTR Name
= LocalLock(program
->hName
);
598 LPCSTR CmdLine
= LocalLock(program
->hCmdLine
);
599 LPCSTR IconFile
= LocalLock(program
->hIconFile
);
600 INT sizeXor
= iconinfo
->nHeight
* iconinfo
->nWidthBytes
;
601 INT sizeAnd
= iconinfo
->nHeight
* ((iconinfo
->nWidth
+ 15) / 16 * 2);
603 PUT_SHORT(buffer
, 0, program
->x
);
604 PUT_SHORT(buffer
, 2, program
->y
);
605 PUT_SHORT(buffer
, 4, program
->nIconIndex
);
606 PUT_SHORT(buffer
, 6, 0x048c); /* unknown */
607 PUT_SHORT(buffer
, 8, sizeXor
);
608 PUT_SHORT(buffer
, 10, sizeAnd
* 8);
609 PUT_SHORT(buffer
, 12, CurrIcon
);
610 PUT_SHORT(buffer
, 14, CurrIcon
+ 12 + sizeAnd
);
611 PUT_SHORT(buffer
, 16, CurrIcon
+ 12);
613 PUT_SHORT(buffer
, 18, ptr
);
614 ptr
+= lstrlen(Name
) + 1;
615 PUT_SHORT(buffer
, 20, ptr
);
616 ptr
+= lstrlen(CmdLine
) + 1;
617 PUT_SHORT(buffer
, 22, ptr
);
619 if ((UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, buffer
, 24) ||
620 (UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, Name
, lstrlen(Name
) + 1) ||
621 (UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, CmdLine
, lstrlen(CmdLine
) + 1) ||
622 (UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, IconFile
, lstrlen(IconFile
) + 1))
625 GRPFILE_CalculateSizes(program
, &CurrProg
, &CurrIcon
);
626 hProgram
= program
->hNext
;
630 hProgram
= group
->hPrograms
;
633 PROGRAM
*program
= LocalLock(hProgram
);
634 CURSORICONINFO
*iconinfo
= LocalLock(program
->hIcon
);
635 LPVOID XorBits
, AndBits
;
636 INT sizeXor
= iconinfo
->nHeight
* iconinfo
->nWidthBytes
;
637 INT sizeAnd
= iconinfo
->nHeight
* ((iconinfo
->nWidth
+ 15) / 16 * 2);
638 DumpIcon16(LocalLock(program
->hIcon
), 0, &XorBits
, &AndBits
);
640 PUT_SHORT(buffer
, 0, iconinfo
->ptHotSpot
.x
);
641 PUT_SHORT(buffer
, 2, iconinfo
->ptHotSpot
.y
);
642 PUT_SHORT(buffer
, 4, iconinfo
->nWidth
);
643 PUT_SHORT(buffer
, 6, iconinfo
->nHeight
);
644 PUT_SHORT(buffer
, 8, iconinfo
->nWidthBytes
);
645 buffer
[10] = iconinfo
->bPlanes
;
646 buffer
[11] = iconinfo
->bBitsPerPixel
;
648 if ((UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, buffer
, 12) ||
649 (UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, AndBits
, sizeAnd
) ||
650 (UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, XorBits
, sizeXor
)) return FALSE
;
652 hProgram
= program
->hNext
;
657 /* write `PMCC' extension */
658 PUT_SHORT(buffer
, 0, 0x8000);
659 PUT_SHORT(buffer
, 2, 0xffff);
660 PUT_SHORT(buffer
, 4, 0x000a);
661 buffer
[6] = 'P', buffer
[7] = 'M';
662 buffer
[8] = 'C', buffer
[9] = 'C';
663 if ((UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, buffer
, 10))
667 hProgram
= group
->hPrograms
;
670 PROGRAM
*program
= LocalLock(hProgram
);
671 LPCSTR lpszWorkDir
= LocalLock(program
->hWorkDir
);
673 /* Working directory */
676 PUT_SHORT(buffer
, 0, 0x8101);
677 PUT_SHORT(buffer
, 2, seqnum
);
678 PUT_SHORT(buffer
, 4, 7 + lstrlen(lpszWorkDir
));
679 if ((UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, buffer
, 6) ||
680 (UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, lpszWorkDir
, lstrlen(lpszWorkDir
) + 1))
685 if (program
->nHotKey
)
687 PUT_SHORT(buffer
, 0, 0x8102);
688 PUT_SHORT(buffer
, 2, seqnum
);
689 PUT_SHORT(buffer
, 4, 8);
690 PUT_SHORT(buffer
, 6, program
->nHotKey
);
691 if ((UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, buffer
, 8)) return FALSE
;
695 if (program
->nCmdShow
)
697 PUT_SHORT(buffer
, 0, 0x8103);
698 PUT_SHORT(buffer
, 2, seqnum
);
699 PUT_SHORT(buffer
, 4, 8);
700 PUT_SHORT(buffer
, 6, program
->nCmdShow
);
701 if ((UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, buffer
, 8)) return FALSE
;
705 hProgram
= program
->hNext
;
708 /* Write `End' extension */
709 PUT_SHORT(buffer
, 0, 0xffff);
710 PUT_SHORT(buffer
, 2, 0xffff);
711 PUT_SHORT(buffer
, 4, 0x0000);
712 if ((UINT
)HFILE_ERROR
== GRPFILE_WriteWithChecksum(file
, buffer
, 6)) return FALSE
;
715 checksum
= GRPFILE_GetChecksum();
716 _llseek(file
, 4, SEEK_SET
);
717 PUT_SHORT(buffer
, 0, checksum
);
718 _lwrite(file
, buffer
, 2);
723 /* Local Variables: */
724 /* c-file-style: "GNU" */