xref: /reactos/base/shell/progman/grpfile.c (revision c2c66aff)
1*c2c66affSColin Finck /*
2*c2c66affSColin Finck  * Program Manager
3*c2c66affSColin Finck  *
4*c2c66affSColin Finck  * Copyright 1996 Ulrich Schmid
5*c2c66affSColin Finck  *           1997 Peter Schlaile
6*c2c66affSColin Finck  *
7*c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
8*c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
9*c2c66affSColin Finck  * License as published by the Free Software Foundation; either
10*c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
11*c2c66affSColin Finck  *
12*c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
13*c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14*c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15*c2c66affSColin Finck  * Lesser General Public License for more details.
16*c2c66affSColin Finck  *
17*c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
18*c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
19*c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20*c2c66affSColin Finck  */
21*c2c66affSColin Finck 
22*c2c66affSColin Finck #include "progman.h"
23*c2c66affSColin Finck 
24*c2c66affSColin Finck #if 0
25*c2c66affSColin Finck #define MALLOCHUNK 1000
26*c2c66affSColin Finck 
27*c2c66affSColin Finck #define GET_USHORT(buffer, i)\
28*c2c66affSColin Finck   (((BYTE)((buffer)[(i)]) + 0x100 * (BYTE)((buffer)[(i)+1])))
29*c2c66affSColin Finck #define GET_SHORT(buffer, i)\
30*c2c66affSColin Finck   (((BYTE)((buffer)[(i)]) + 0x100 * (signed char)((buffer)[(i)+1])))
31*c2c66affSColin Finck #define PUT_SHORT(buffer, i, s)\
32*c2c66affSColin Finck   (((buffer)[(i)] = (s) & 0xff, (buffer)[(i)+1] = ((s) >> 8) & 0xff))
33*c2c66affSColin Finck 
34*c2c66affSColin Finck static BOOL   GRPFILE_ReadFileToBuffer(LPCSTR, HLOCAL*, INT*);
35*c2c66affSColin Finck static HLOCAL GRPFILE_ScanGroup(LPCSTR, INT, LPCSTR, BOOL);
36*c2c66affSColin Finck static HLOCAL GRPFILE_ScanProgram(LPCSTR, INT, LPCSTR, INT,
37*c2c66affSColin Finck 				  LPCSTR, HLOCAL,LPCSTR);
38*c2c66affSColin Finck static BOOL GRPFILE_DoWriteGroupFile(HFILE file, PROGGROUP *group);
39*c2c66affSColin Finck #endif
40*c2c66affSColin Finck 
41*c2c66affSColin Finck /***********************************************************************
42*c2c66affSColin Finck  *
43*c2c66affSColin Finck  *           GRPFILE_ModifyFileName
44*c2c66affSColin Finck  *
45*c2c66affSColin Finck  *  Change extension `.grp' to `.gr'
46*c2c66affSColin Finck  */
47*c2c66affSColin Finck 
48*c2c66affSColin Finck #if 0
49*c2c66affSColin Finck static VOID GRPFILE_ModifyFileName(LPSTR lpszNewName, LPCSTR lpszOrigName,
50*c2c66affSColin Finck 				   INT nSize, BOOL bModify)
51*c2c66affSColin Finck {
52*c2c66affSColin Finck   lstrcpynA(lpszNewName, lpszOrigName, nSize);
53*c2c66affSColin Finck   lpszNewName[nSize-1] = '\0';
54*c2c66affSColin Finck   if (!bModify) return;
55*c2c66affSColin Finck   if (!lstrcmpiA(lpszNewName + strlen(lpszNewName) - 4, ".grp"))
56*c2c66affSColin Finck     lpszNewName[strlen(lpszNewName) - 1] = '\0';
57*c2c66affSColin Finck }
58*c2c66affSColin Finck #endif
59*c2c66affSColin Finck 
60*c2c66affSColin Finck /***********************************************************************
61*c2c66affSColin Finck  *
62*c2c66affSColin Finck  *           GRPFILE_ReadGroupFile
63*c2c66affSColin Finck  */
64*c2c66affSColin Finck 
GRPFILE_ReadGroupFile(LPCWSTR lpszPath,BOOL bIsCommonGroup)65*c2c66affSColin Finck DWORD GRPFILE_ReadGroupFile(LPCWSTR lpszPath, BOOL bIsCommonGroup)
66*c2c66affSColin Finck {
67*c2c66affSColin Finck #if 0
68*c2c66affSColin Finck   CHAR   szPath_gr[MAX_PATHNAME_LEN];
69*c2c66affSColin Finck   BOOL   bFileNameModified = FALSE;
70*c2c66affSColin Finck   OFSTRUCT dummy;
71*c2c66affSColin Finck   HLOCAL hBuffer, hGroup;
72*c2c66affSColin Finck   INT    size;
73*c2c66affSColin Finck 
74*c2c66affSColin Finck   /* if `.gr' file exists use that */
75*c2c66affSColin Finck   GRPFILE_ModifyFileName(szPath_gr, lpszPath, MAX_PATHNAME_LEN, TRUE);
76*c2c66affSColin Finck   if (OpenFile(szPath_gr, &dummy, OF_EXIST) != HFILE_ERROR)
77*c2c66affSColin Finck     {
78*c2c66affSColin Finck       lpszPath = szPath_gr;
79*c2c66affSColin Finck       bFileNameModified = TRUE;
80*c2c66affSColin Finck     }
81*c2c66affSColin Finck 
82*c2c66affSColin Finck   /* Read the whole file into a buffer */
83*c2c66affSColin Finck   if (!GRPFILE_ReadFileToBuffer(lpszPath, &hBuffer, &size))
84*c2c66affSColin Finck     {
85*c2c66affSColin Finck       MAIN_MessageBoxIDS_s(IDS_GRPFILE_READ_ERROR_s, lpszPath, IDS_ERROR, MB_YESNO);
86*c2c66affSColin Finck       return(0);
87*c2c66affSColin Finck     }
88*c2c66affSColin Finck 
89*c2c66affSColin Finck   /* Interpret buffer */
90*c2c66affSColin Finck   hGroup = GRPFILE_ScanGroup(LocalLock(hBuffer), size,
91*c2c66affSColin Finck 			     lpszPath, bFileNameModified);
92*c2c66affSColin Finck   if (!hGroup)
93*c2c66affSColin Finck     MAIN_MessageBoxIDS_s(IDS_GRPFILE_READ_ERROR_s, lpszPath, IDS_ERROR, MB_YESNO);
94*c2c66affSColin Finck 
95*c2c66affSColin Finck   LocalFree(hBuffer);
96*c2c66affSColin Finck 
97*c2c66affSColin Finck   return(hGroup);
98*c2c66affSColin Finck 
99*c2c66affSColin Finck #else
100*c2c66affSColin Finck     return ERROR_SUCCESS;
101*c2c66affSColin Finck #endif
102*c2c66affSColin Finck }
103*c2c66affSColin Finck 
104*c2c66affSColin Finck /***********************************************************************
105*c2c66affSColin Finck  *
106*c2c66affSColin Finck  *           GRPFILE_ReadFileToBuffer
107*c2c66affSColin Finck  */
108*c2c66affSColin Finck 
109*c2c66affSColin Finck #if 0
110*c2c66affSColin Finck static BOOL GRPFILE_ReadFileToBuffer(LPCSTR path, HLOCAL *phBuffer,
111*c2c66affSColin Finck 				     INT *piSize)
112*c2c66affSColin Finck {
113*c2c66affSColin Finck   UINT    len, size;
114*c2c66affSColin Finck   LPSTR  buffer;
115*c2c66affSColin Finck   HLOCAL hBuffer, hNewBuffer;
116*c2c66affSColin Finck   HFILE  file;
117*c2c66affSColin Finck 
118*c2c66affSColin Finck   file=_lopen(path, OF_READ);
119*c2c66affSColin Finck   if (file == HFILE_ERROR) return FALSE;
120*c2c66affSColin Finck 
121*c2c66affSColin Finck   size = 0;
122*c2c66affSColin Finck   hBuffer = LocalAlloc(LMEM_FIXED, MALLOCHUNK + 1);
123*c2c66affSColin Finck   if (!hBuffer) return FALSE;
124*c2c66affSColin Finck   buffer = LocalLock(hBuffer);
125*c2c66affSColin Finck 
126*c2c66affSColin Finck   while ((len = _lread(file, buffer + size, MALLOCHUNK))
127*c2c66affSColin Finck 	 == MALLOCHUNK)
128*c2c66affSColin Finck     {
129*c2c66affSColin Finck       size += len;
130*c2c66affSColin Finck       hNewBuffer = LocalReAlloc(hBuffer, size + MALLOCHUNK + 1,
131*c2c66affSColin Finck 				LMEM_MOVEABLE);
132*c2c66affSColin Finck       if (!hNewBuffer)
133*c2c66affSColin Finck 	{
134*c2c66affSColin Finck 	  LocalFree(hBuffer);
135*c2c66affSColin Finck 	  return FALSE;
136*c2c66affSColin Finck 	}
137*c2c66affSColin Finck       hBuffer = hNewBuffer;
138*c2c66affSColin Finck       buffer = LocalLock(hBuffer);
139*c2c66affSColin Finck     }
140*c2c66affSColin Finck 
141*c2c66affSColin Finck   _lclose(file);
142*c2c66affSColin Finck 
143*c2c66affSColin Finck   if (len == (UINT)HFILE_ERROR)
144*c2c66affSColin Finck     {
145*c2c66affSColin Finck       LocalFree(hBuffer);
146*c2c66affSColin Finck       return FALSE;
147*c2c66affSColin Finck     }
148*c2c66affSColin Finck 
149*c2c66affSColin Finck   size += len;
150*c2c66affSColin Finck   buffer[size] = 0;
151*c2c66affSColin Finck 
152*c2c66affSColin Finck   *phBuffer = hBuffer;
153*c2c66affSColin Finck   *piSize   = size;
154*c2c66affSColin Finck   return TRUE;
155*c2c66affSColin Finck }
156*c2c66affSColin Finck #endif
157*c2c66affSColin Finck 
158*c2c66affSColin Finck /***********************************************************************
159*c2c66affSColin Finck  *           GRPFILE_ScanGroup
160*c2c66affSColin Finck  */
161*c2c66affSColin Finck 
162*c2c66affSColin Finck #if 0
163*c2c66affSColin Finck static HLOCAL GRPFILE_ScanGroup(LPCSTR buffer, INT size,
164*c2c66affSColin Finck 				LPCSTR lpszGrpFile,
165*c2c66affSColin Finck 				BOOL bModifiedFileName)
166*c2c66affSColin Finck {
167*c2c66affSColin Finck   HLOCAL  hGroup;
168*c2c66affSColin Finck   INT     i, seqnum;
169*c2c66affSColin Finck   LPCSTR  extension;
170*c2c66affSColin Finck   LPCSTR  lpszName;
171*c2c66affSColin Finck   INT     x, y, width, height, iconx, icony, nCmdShow;
172*c2c66affSColin Finck   INT     number_of_programs;
173*c2c66affSColin Finck   BOOL    bOverwriteFileOk;
174*c2c66affSColin Finck 
175*c2c66affSColin Finck   if (buffer[0] != 'P' || buffer[1] != 'M') return(0);
176*c2c66affSColin Finck   if (buffer[2] == 'C' && buffer[3] == 'C')
177*c2c66affSColin Finck     /* original with checksum */
178*c2c66affSColin Finck     bOverwriteFileOk = FALSE;
179*c2c66affSColin Finck   else if (buffer[2] == 'X' && buffer[3] == 'X')
180*c2c66affSColin Finck     /* modified without checksum */
181*c2c66affSColin Finck     bOverwriteFileOk = TRUE;
182*c2c66affSColin Finck   else return(0);
183*c2c66affSColin Finck 
184*c2c66affSColin Finck   /* checksum = GET_USHORT(buffer, 4)   (ignored) */
185*c2c66affSColin Finck 
186*c2c66affSColin Finck   extension = buffer + GET_USHORT(buffer, 6);
187*c2c66affSColin Finck   if (extension == buffer + size) extension = 0;
188*c2c66affSColin Finck   else if (extension + 6 > buffer + size) return(0);
189*c2c66affSColin Finck 
190*c2c66affSColin Finck   nCmdShow = GET_USHORT(buffer,  8);
191*c2c66affSColin Finck   x        = GET_SHORT(buffer,  10);
192*c2c66affSColin Finck   y        = GET_SHORT(buffer,  12);
193*c2c66affSColin Finck   width    = GET_USHORT(buffer, 14);
194*c2c66affSColin Finck   height   = GET_USHORT(buffer, 16);
195*c2c66affSColin Finck   iconx    = GET_SHORT(buffer,  18);
196*c2c66affSColin Finck   icony    = GET_SHORT(buffer,  20);
197*c2c66affSColin Finck   lpszName = buffer + GET_USHORT(buffer, 22);
198*c2c66affSColin Finck   if (lpszName >= buffer + size) return(0);
199*c2c66affSColin Finck 
200*c2c66affSColin Finck   /* unknown bytes 24 - 31 ignored */
201*c2c66affSColin Finck   /*
202*c2c66affSColin Finck     Unknown bytes should be:
203*c2c66affSColin Finck     wLogPixelsX = GET_SHORT(buffer, 24);
204*c2c66affSColin Finck     wLogPixelsY = GET_SHORT(buffer, 26);
205*c2c66affSColin Finck     byBitsPerPixel = byte at 28;
206*c2c66affSColin Finck     byPlanes     = byte at 29;
207*c2c66affSColin Finck     wReserved   = GET_SHORT(buffer, 30);
208*c2c66affSColin Finck     */
209*c2c66affSColin Finck 
210*c2c66affSColin Finck   hGroup = GROUP_AddGroup(lpszName, lpszGrpFile, nCmdShow, x, y,
211*c2c66affSColin Finck 			  width, height, iconx, icony,
212*c2c66affSColin Finck 			  bModifiedFileName, bOverwriteFileOk,
213*c2c66affSColin Finck 			  TRUE);
214*c2c66affSColin Finck   if (!hGroup) return(0);
215*c2c66affSColin Finck 
216*c2c66affSColin Finck   number_of_programs = GET_USHORT(buffer, 32);
217*c2c66affSColin Finck   if (2 * number_of_programs + 34 > size) return(0);
218*c2c66affSColin Finck   for (i=0, seqnum=0; i < number_of_programs; i++, seqnum++)
219*c2c66affSColin Finck     {
220*c2c66affSColin Finck       LPCSTR program_ptr = buffer + GET_USHORT(buffer, 34 + 2*i);
221*c2c66affSColin Finck       if (program_ptr + 24 > buffer + size) return(0);
222*c2c66affSColin Finck       if (!GET_USHORT(buffer, 34 + 2*i)) continue;
223*c2c66affSColin Finck       if (!GRPFILE_ScanProgram(buffer, size, program_ptr, seqnum,
224*c2c66affSColin Finck 			       extension, hGroup, lpszGrpFile))
225*c2c66affSColin Finck 	{
226*c2c66affSColin Finck 	  GROUP_DeleteGroup(hGroup);
227*c2c66affSColin Finck 	  return(0);
228*c2c66affSColin Finck 	}
229*c2c66affSColin Finck     }
230*c2c66affSColin Finck 
231*c2c66affSColin Finck   /* FIXME shouldn't be necessary */
232*c2c66affSColin Finck   GROUP_ShowGroupWindow(hGroup);
233*c2c66affSColin Finck 
234*c2c66affSColin Finck   return hGroup;
235*c2c66affSColin Finck }
236*c2c66affSColin Finck #endif
237*c2c66affSColin Finck 
238*c2c66affSColin Finck /***********************************************************************
239*c2c66affSColin Finck  *           GRPFILE_ScanProgram
240*c2c66affSColin Finck  */
241*c2c66affSColin Finck 
242*c2c66affSColin Finck #if 0
243*c2c66affSColin Finck static HLOCAL GRPFILE_ScanProgram(LPCSTR buffer, INT size,
244*c2c66affSColin Finck 				  LPCSTR program_ptr, INT seqnum,
245*c2c66affSColin Finck 				  LPCSTR extension, HLOCAL hGroup,
246*c2c66affSColin Finck 				  LPCSTR lpszGrpFile)
247*c2c66affSColin Finck {
248*c2c66affSColin Finck   INT    icontype;
249*c2c66affSColin Finck   HICON  hIcon;
250*c2c66affSColin Finck   LPCSTR lpszName, lpszCmdLine, lpszIconFile, lpszWorkDir;
251*c2c66affSColin Finck   LPCSTR iconinfo_ptr, iconANDbits_ptr, iconXORbits_ptr;
252*c2c66affSColin Finck   INT    x, y, nIconIndex, iconANDsize, iconXORsize;
253*c2c66affSColin Finck   INT    nHotKey, nCmdShow;
254*c2c66affSColin Finck   UINT width, height, planes, bpp;
255*c2c66affSColin Finck 
256*c2c66affSColin Finck   x               = GET_SHORT(program_ptr, 0);
257*c2c66affSColin Finck   y               = GET_SHORT(program_ptr, 2);
258*c2c66affSColin Finck   nIconIndex      = GET_USHORT(program_ptr, 4);
259*c2c66affSColin Finck 
260*c2c66affSColin Finck   /* FIXME is this correct ?? */
261*c2c66affSColin Finck   icontype = GET_USHORT(program_ptr,  6);
262*c2c66affSColin Finck   switch (icontype)
263*c2c66affSColin Finck     {
264*c2c66affSColin Finck     default:
265*c2c66affSColin Finck       MAIN_MessageBoxIDS_s(IDS_UNKNOWN_FEATURE_s, lpszGrpFile,
266*c2c66affSColin Finck 			   IDS_WARNING, MB_OK);
267*c2c66affSColin Finck     case 0x048c:
268*c2c66affSColin Finck       iconXORsize     = GET_USHORT(program_ptr,  8);
269*c2c66affSColin Finck       iconANDsize     = GET_USHORT(program_ptr, 10) / 8;
270*c2c66affSColin Finck       iconinfo_ptr    = buffer + GET_USHORT(program_ptr, 12);
271*c2c66affSColin Finck       iconXORbits_ptr = buffer + GET_USHORT(program_ptr, 14);
272*c2c66affSColin Finck       iconANDbits_ptr = buffer + GET_USHORT(program_ptr, 16);
273*c2c66affSColin Finck       width           = GET_USHORT(iconinfo_ptr, 4);
274*c2c66affSColin Finck       height          = GET_USHORT(iconinfo_ptr, 6);
275*c2c66affSColin Finck       planes          = GET_USHORT(iconinfo_ptr, 10);
276*c2c66affSColin Finck       bpp             = GET_USHORT(iconinfo_ptr, 11);
277*c2c66affSColin Finck       break;
278*c2c66affSColin Finck     case 0x000c:
279*c2c66affSColin Finck       iconANDsize     = GET_USHORT(program_ptr,  8);
280*c2c66affSColin Finck       iconXORsize     = GET_USHORT(program_ptr, 10);
281*c2c66affSColin Finck       iconinfo_ptr    = buffer + GET_USHORT(program_ptr, 12);
282*c2c66affSColin Finck       iconANDbits_ptr = buffer + GET_USHORT(program_ptr, 14);
283*c2c66affSColin Finck       iconXORbits_ptr = buffer + GET_USHORT(program_ptr, 16);
284*c2c66affSColin Finck       width           = GET_USHORT(iconinfo_ptr, 4);
285*c2c66affSColin Finck       height          = GET_USHORT(iconinfo_ptr, 6);
286*c2c66affSColin Finck       planes          = GET_USHORT(iconinfo_ptr, 10);
287*c2c66affSColin Finck       bpp             = GET_USHORT(iconinfo_ptr, 11);
288*c2c66affSColin Finck     }
289*c2c66affSColin Finck 
290*c2c66affSColin Finck   if (iconANDbits_ptr + iconANDsize > buffer + size ||
291*c2c66affSColin Finck       iconXORbits_ptr + iconXORsize > buffer + size) return(0);
292*c2c66affSColin Finck 
293*c2c66affSColin Finck   hIcon = CreateIcon(Globals.hInstance, width, height, planes, bpp, (PBYTE)iconANDbits_ptr, (PBYTE)iconXORbits_ptr);
294*c2c66affSColin Finck 
295*c2c66affSColin Finck   lpszName        = buffer + GET_USHORT(program_ptr, 18);
296*c2c66affSColin Finck   lpszCmdLine     = buffer + GET_USHORT(program_ptr, 20);
297*c2c66affSColin Finck   lpszIconFile    = buffer + GET_USHORT(program_ptr, 22);
298*c2c66affSColin Finck   if (iconinfo_ptr + 6 > buffer + size ||
299*c2c66affSColin Finck       lpszName         > buffer + size ||
300*c2c66affSColin Finck       lpszCmdLine      > buffer + size ||
301*c2c66affSColin Finck       lpszIconFile     > buffer + size) return(0);
302*c2c66affSColin Finck 
303*c2c66affSColin Finck   /* Scan Extensions */
304*c2c66affSColin Finck   lpszWorkDir = "";
305*c2c66affSColin Finck   nHotKey     = 0;
306*c2c66affSColin Finck   nCmdShow    = SW_SHOWNORMAL;
307*c2c66affSColin Finck   if (extension)
308*c2c66affSColin Finck     {
309*c2c66affSColin Finck       LPCSTR ptr = extension;
310*c2c66affSColin Finck       while (ptr + 6 <= buffer + size)
311*c2c66affSColin Finck 	{
312*c2c66affSColin Finck 	  UINT type   = GET_USHORT(ptr, 0);
313*c2c66affSColin Finck 	  UINT number = GET_USHORT(ptr, 2);
314*c2c66affSColin Finck 	  UINT skip   = GET_USHORT(ptr, 4);
315*c2c66affSColin Finck 
316*c2c66affSColin Finck 	  if (number == seqnum)
317*c2c66affSColin Finck 	    {
318*c2c66affSColin Finck 	      switch (type)
319*c2c66affSColin Finck 		{
320*c2c66affSColin Finck 		case 0x8000:
321*c2c66affSColin Finck 		  if (ptr + 10 > buffer + size) return(0);
322*c2c66affSColin Finck 		  if (ptr[6] != 'P' || ptr[7] != 'M' ||
323*c2c66affSColin Finck 		      ptr[8] != 'C' || ptr[9] != 'C') return(0);
324*c2c66affSColin Finck 		  break;
325*c2c66affSColin Finck 		case 0x8101:
326*c2c66affSColin Finck 		  lpszWorkDir = ptr + 6;
327*c2c66affSColin Finck 		  break;
328*c2c66affSColin Finck 		case 0x8102:
329*c2c66affSColin Finck 		  if (ptr + 8 > buffer + size) return(0);
330*c2c66affSColin Finck 		  nHotKey = GET_USHORT(ptr, 6);
331*c2c66affSColin Finck 		  break;
332*c2c66affSColin Finck 		case 0x8103:
333*c2c66affSColin Finck 		  if (ptr + 8 > buffer + size) return(0);
334*c2c66affSColin Finck 		  nCmdShow = GET_USHORT(ptr, 6);
335*c2c66affSColin Finck 		  break;
336*c2c66affSColin Finck 		default:
337*c2c66affSColin Finck 		  MAIN_MessageBoxIDS_s(IDS_UNKNOWN_FEATURE_s,
338*c2c66affSColin Finck 				       lpszGrpFile, IDS_WARNING, MB_OK);
339*c2c66affSColin Finck 		}
340*c2c66affSColin Finck 	    }
341*c2c66affSColin Finck 	  if (!skip) break;
342*c2c66affSColin Finck 	  ptr += skip;
343*c2c66affSColin Finck 	}
344*c2c66affSColin Finck     }
345*c2c66affSColin Finck 
346*c2c66affSColin Finck   return (PROGRAM_AddProgram(hGroup, hIcon, lpszName, x, y,
347*c2c66affSColin Finck 			     lpszCmdLine, lpszIconFile,
348*c2c66affSColin Finck 			     nIconIndex, lpszWorkDir,
349*c2c66affSColin Finck 			     nHotKey, nCmdShow));
350*c2c66affSColin Finck }
351*c2c66affSColin Finck #endif
352*c2c66affSColin Finck 
353*c2c66affSColin Finck /***********************************************************************
354*c2c66affSColin Finck  *
355*c2c66affSColin Finck  *           GRPFILE_WriteGroupFile
356*c2c66affSColin Finck  */
357*c2c66affSColin Finck 
GRPFILE_WriteGroupFile(PROGGROUP * hGroup)358*c2c66affSColin Finck BOOL GRPFILE_WriteGroupFile(PROGGROUP* hGroup)
359*c2c66affSColin Finck {
360*c2c66affSColin Finck #if 0
361*c2c66affSColin Finck   CHAR szPath[MAX_PATHNAME_LEN];
362*c2c66affSColin Finck   PROGGROUP *group = LocalLock(hGroup);
363*c2c66affSColin Finck   OFSTRUCT dummy;
364*c2c66affSColin Finck   HFILE file;
365*c2c66affSColin Finck   BOOL ret;
366*c2c66affSColin Finck 
367*c2c66affSColin Finck   GRPFILE_ModifyFileName(szPath, LocalLock(group->hGrpFile),
368*c2c66affSColin Finck 			 MAX_PATHNAME_LEN,
369*c2c66affSColin Finck 			 group->bFileNameModified);
370*c2c66affSColin Finck 
371*c2c66affSColin Finck   /* Try not to overwrite original files */
372*c2c66affSColin Finck 
373*c2c66affSColin Finck   /* group->bOverwriteFileOk == TRUE only if a file has the modified format */
374*c2c66affSColin Finck   if (!group->bOverwriteFileOk &&
375*c2c66affSColin Finck       OpenFile(szPath, &dummy, OF_EXIST) != HFILE_ERROR)
376*c2c66affSColin Finck     {
377*c2c66affSColin Finck       /* Original file exists, try `.gr' extension */
378*c2c66affSColin Finck       GRPFILE_ModifyFileName(szPath, LocalLock(group->hGrpFile),
379*c2c66affSColin Finck 			     MAX_PATHNAME_LEN, TRUE);
380*c2c66affSColin Finck       if (OpenFile(szPath, &dummy, OF_EXIST) != HFILE_ERROR)
381*c2c66affSColin Finck 	{
382*c2c66affSColin Finck 	  /* File exists. Do not overwrite */
383*c2c66affSColin Finck 	  MAIN_MessageBoxIDS_s(IDS_FILE_NOT_OVERWRITTEN_s, szPath,
384*c2c66affSColin Finck 			       IDS_INFO, MB_OK);
385*c2c66affSColin Finck 	  return FALSE;
386*c2c66affSColin Finck 	}
387*c2c66affSColin Finck       /* Inform about the modified file name */
388*c2c66affSColin Finck       if (IDCANCEL ==
389*c2c66affSColin Finck 	  MAIN_MessageBoxIDS_s(IDS_SAVE_GROUP_AS_s, szPath, IDS_INFO,
390*c2c66affSColin Finck 			       MB_OKCANCEL | MB_ICONINFORMATION))
391*c2c66affSColin Finck 	return FALSE;
392*c2c66affSColin Finck     }
393*c2c66affSColin Finck 
394*c2c66affSColin Finck   {
395*c2c66affSColin Finck     /* Warn about the (possible) incompatibility */
396*c2c66affSColin Finck     CHAR msg[MAX_PATHNAME_LEN + 200];
397*c2c66affSColin Finck     wsprintfA(msg,
398*c2c66affSColin Finck 	     "Group files written by this DRAFT Program Manager "
399*c2c66affSColin Finck 	     "possibly cannot be read by the Microsoft Program Manager!!\n"
400*c2c66affSColin Finck 	     "Are you sure to write %s?", szPath);
401*c2c66affSColin Finck     if (IDOK != MessageBoxA(Globals.hMainWnd, msg, "WARNING",
402*c2c66affSColin Finck                             MB_OKCANCEL | MB_DEFBUTTON2)) return FALSE;
403*c2c66affSColin Finck   }
404*c2c66affSColin Finck 
405*c2c66affSColin Finck   /* Open file */
406*c2c66affSColin Finck   file = _lcreat(szPath, 0);
407*c2c66affSColin Finck   if (file != HFILE_ERROR)
408*c2c66affSColin Finck     {
409*c2c66affSColin Finck       ret = GRPFILE_DoWriteGroupFile(file, group);
410*c2c66affSColin Finck       _lclose(file);
411*c2c66affSColin Finck     }
412*c2c66affSColin Finck   else ret = FALSE;
413*c2c66affSColin Finck 
414*c2c66affSColin Finck   if (!ret)
415*c2c66affSColin Finck     MAIN_MessageBoxIDS_s(IDS_FILE_WRITE_ERROR_s, szPath, IDS_ERROR, MB_OK);
416*c2c66affSColin Finck 
417*c2c66affSColin Finck   return(ret);
418*c2c66affSColin Finck 
419*c2c66affSColin Finck #else
420*c2c66affSColin Finck     return TRUE;
421*c2c66affSColin Finck #endif
422*c2c66affSColin Finck }
423*c2c66affSColin Finck 
424*c2c66affSColin Finck #if 0
425*c2c66affSColin Finck 
426*c2c66affSColin Finck /***********************************************************************
427*c2c66affSColin Finck  *
428*c2c66affSColin Finck  *           GRPFILE_CalculateSizes
429*c2c66affSColin Finck  */
430*c2c66affSColin Finck 
431*c2c66affSColin Finck static VOID GRPFILE_CalculateSizes(PROGRAM *program, INT *Progs, INT *Icons,
432*c2c66affSColin Finck                                    UINT *sizeAnd, UINT *sizeXor)
433*c2c66affSColin Finck {
434*c2c66affSColin Finck   ICONINFO info;
435*c2c66affSColin Finck   BITMAP bmp;
436*c2c66affSColin Finck 
437*c2c66affSColin Finck   GetIconInfo( program->hIcon, &info );
438*c2c66affSColin Finck   GetObjectW( info.hbmMask, sizeof(bmp), &bmp );
439*c2c66affSColin Finck   *sizeAnd = bmp.bmHeight * ((bmp.bmWidth + 15) / 16 * 2);
440*c2c66affSColin Finck   GetObjectW( info.hbmColor, sizeof(bmp), &bmp );
441*c2c66affSColin Finck   *sizeXor = bmp.bmHeight * bmp.bmWidthBytes;
442*c2c66affSColin Finck   DeleteObject( info.hbmMask );
443*c2c66affSColin Finck   DeleteObject( info.hbmColor );
444*c2c66affSColin Finck 
445*c2c66affSColin Finck   *Progs += 24;
446*c2c66affSColin Finck   *Progs += strlen(LocalLock(program->hName)) + 1;
447*c2c66affSColin Finck   *Progs += strlen(LocalLock(program->hCmdLine)) + 1;
448*c2c66affSColin Finck   *Progs += strlen(LocalLock(program->hIconFile)) + 1;
449*c2c66affSColin Finck 
450*c2c66affSColin Finck   *Icons += 12; /* IconInfo */
451*c2c66affSColin Finck   *Icons += *sizeAnd;
452*c2c66affSColin Finck   *Icons += *sizeXor;
453*c2c66affSColin Finck }
454*c2c66affSColin Finck 
455*c2c66affSColin Finck /***********************************************************************/
456*c2c66affSColin Finck UINT16 GRPFILE_checksum;
457*c2c66affSColin Finck BOOL GRPFILE_checksum_half_word;
458*c2c66affSColin Finck BYTE GRPFILE_checksum_last_byte;
459*c2c66affSColin Finck /***********************************************************************
460*c2c66affSColin Finck  *
461*c2c66affSColin Finck  *           GRPFILE_InitChecksum
462*c2c66affSColin Finck  */
463*c2c66affSColin Finck 
464*c2c66affSColin Finck static void GRPFILE_InitChecksum(void)
465*c2c66affSColin Finck {
466*c2c66affSColin Finck 	GRPFILE_checksum = 0;
467*c2c66affSColin Finck 	GRPFILE_checksum_half_word = 0;
468*c2c66affSColin Finck }
469*c2c66affSColin Finck 
470*c2c66affSColin Finck /***********************************************************************
471*c2c66affSColin Finck  *
472*c2c66affSColin Finck  *           GRPFILE_GetChecksum
473*c2c66affSColin Finck  */
474*c2c66affSColin Finck 
475*c2c66affSColin Finck static UINT16 GRPFILE_GetChecksum(void)
476*c2c66affSColin Finck {
477*c2c66affSColin Finck 	return GRPFILE_checksum;
478*c2c66affSColin Finck }
479*c2c66affSColin Finck 
480*c2c66affSColin Finck /***********************************************************************
481*c2c66affSColin Finck  *
482*c2c66affSColin Finck  *           GRPFILE_WriteWithChecksum
483*c2c66affSColin Finck  *
484*c2c66affSColin Finck  * Looks crazier than it is:
485*c2c66affSColin Finck  *
486*c2c66affSColin Finck  * chksum = 0;
487*c2c66affSColin Finck  * chksum = cksum - 1. word;
488*c2c66affSColin Finck  * chksum = cksum - 2. word;
489*c2c66affSColin Finck  * ...
490*c2c66affSColin Finck  *
491*c2c66affSColin Finck  * if (filelen is even)
492*c2c66affSColin Finck  *      great I'm finished
493*c2c66affSColin Finck  * else
494*c2c66affSColin Finck  *      ignore last byte
495*c2c66affSColin Finck  */
496*c2c66affSColin Finck 
497*c2c66affSColin Finck static UINT GRPFILE_WriteWithChecksum(HFILE file, LPCSTR str, UINT size)
498*c2c66affSColin Finck {
499*c2c66affSColin Finck 	UINT i;
500*c2c66affSColin Finck 	if (GRPFILE_checksum_half_word) {
501*c2c66affSColin Finck 		GRPFILE_checksum -= GRPFILE_checksum_last_byte;
502*c2c66affSColin Finck 	}
503*c2c66affSColin Finck 	for (i=0; i < size; i++) {
504*c2c66affSColin Finck 		if (GRPFILE_checksum_half_word) {
505*c2c66affSColin Finck 			GRPFILE_checksum -= str[i] << 8;
506*c2c66affSColin Finck 		} else {
507*c2c66affSColin Finck 			GRPFILE_checksum -= str[i];
508*c2c66affSColin Finck 		}
509*c2c66affSColin Finck 		GRPFILE_checksum_half_word ^= 1;
510*c2c66affSColin Finck 	}
511*c2c66affSColin Finck 
512*c2c66affSColin Finck 	if (GRPFILE_checksum_half_word) {
513*c2c66affSColin Finck 		GRPFILE_checksum_last_byte = str[size-1];
514*c2c66affSColin Finck 		GRPFILE_checksum += GRPFILE_checksum_last_byte;
515*c2c66affSColin Finck 	}
516*c2c66affSColin Finck 
517*c2c66affSColin Finck 	return _lwrite(file, str, size);
518*c2c66affSColin Finck }
519*c2c66affSColin Finck 
520*c2c66affSColin Finck 
521*c2c66affSColin Finck /***********************************************************************
522*c2c66affSColin Finck  *
523*c2c66affSColin Finck  *           GRPFILE_DoWriteGroupFile
524*c2c66affSColin Finck  */
525*c2c66affSColin Finck 
526*c2c66affSColin Finck static BOOL GRPFILE_DoWriteGroupFile(HFILE file, PROGGROUP *group)
527*c2c66affSColin Finck {
528*c2c66affSColin Finck   CHAR buffer[34];
529*c2c66affSColin Finck   HLOCAL hProgram;
530*c2c66affSColin Finck   INT    NumProg, Title, Progs, Icons, Extension;
531*c2c66affSColin Finck   INT    CurrProg, CurrIcon, nCmdShow, ptr, seqnum;
532*c2c66affSColin Finck 
533*c2c66affSColin Finck   UINT sizeAnd, sizeXor;
534*c2c66affSColin Finck 
535*c2c66affSColin Finck   BOOL   need_extension;
536*c2c66affSColin Finck   LPCSTR lpszTitle = LocalLock(group->hName);
537*c2c66affSColin Finck 
538*c2c66affSColin Finck   UINT16 checksum;
539*c2c66affSColin Finck 
540*c2c66affSColin Finck   GRPFILE_InitChecksum();
541*c2c66affSColin Finck 
542*c2c66affSColin Finck   /* Calculate offsets */
543*c2c66affSColin Finck   NumProg = 0;
544*c2c66affSColin Finck   Icons   = 0;
545*c2c66affSColin Finck   Extension = 0;
546*c2c66affSColin Finck   need_extension = FALSE;
547*c2c66affSColin Finck   hProgram = group->hPrograms;
548*c2c66affSColin Finck   while(hProgram)
549*c2c66affSColin Finck     {
550*c2c66affSColin Finck       PROGRAM *program = LocalLock(hProgram);
551*c2c66affSColin Finck       LPCSTR lpszWorkDir = LocalLock(program->hWorkDir);
552*c2c66affSColin Finck 
553*c2c66affSColin Finck       NumProg++;
554*c2c66affSColin Finck       GRPFILE_CalculateSizes(program, &Icons, &Extension, &sizeAnd, &sizeXor);
555*c2c66affSColin Finck 
556*c2c66affSColin Finck       /* Set a flag if an extension is needed */
557*c2c66affSColin Finck       if (lpszWorkDir[0] || program->nHotKey ||
558*c2c66affSColin Finck 	  program->nCmdShow != SW_SHOWNORMAL) need_extension = TRUE;
559*c2c66affSColin Finck 
560*c2c66affSColin Finck       hProgram = program->hNext;
561*c2c66affSColin Finck     }
562*c2c66affSColin Finck   Title      = 34 + NumProg * 2;
563*c2c66affSColin Finck   Progs      = Title + strlen(lpszTitle) + 1;
564*c2c66affSColin Finck   Icons     += Progs;
565*c2c66affSColin Finck   Extension += Icons;
566*c2c66affSColin Finck 
567*c2c66affSColin Finck   /* Header */
568*c2c66affSColin Finck   buffer[0] = 'P';
569*c2c66affSColin Finck   buffer[1] = 'M';
570*c2c66affSColin Finck   buffer[2] = 'C';
571*c2c66affSColin Finck   buffer[3] = 'C';
572*c2c66affSColin Finck 
573*c2c66affSColin Finck   PUT_SHORT(buffer,  4, 0); /* Checksum zero for now, written later */
574*c2c66affSColin Finck   PUT_SHORT(buffer,  6, Extension);
575*c2c66affSColin Finck   /* Update group->nCmdShow */
576*c2c66affSColin Finck   if (IsIconic(group->hWnd))      nCmdShow = SW_SHOWMINIMIZED;
577*c2c66affSColin Finck   else if (IsZoomed(group->hWnd)) nCmdShow = SW_SHOWMAXIMIZED;
578*c2c66affSColin Finck   else                            nCmdShow = SW_SHOWNORMAL;
579*c2c66affSColin Finck   PUT_SHORT(buffer,  8, nCmdShow);
580*c2c66affSColin Finck   PUT_SHORT(buffer, 10, group->x);
581*c2c66affSColin Finck   PUT_SHORT(buffer, 12, group->y);
582*c2c66affSColin Finck   PUT_SHORT(buffer, 14, group->width);
583*c2c66affSColin Finck   PUT_SHORT(buffer, 16, group->height);
584*c2c66affSColin Finck   PUT_SHORT(buffer, 18, group->iconx);
585*c2c66affSColin Finck   PUT_SHORT(buffer, 20, group->icony);
586*c2c66affSColin Finck   PUT_SHORT(buffer, 22, Title);
587*c2c66affSColin Finck   PUT_SHORT(buffer, 24, 0x0020); /* unknown */
588*c2c66affSColin Finck   PUT_SHORT(buffer, 26, 0x0020); /* unknown */
589*c2c66affSColin Finck   PUT_SHORT(buffer, 28, 0x0108); /* unknown */
590*c2c66affSColin Finck   PUT_SHORT(buffer, 30, 0x0000); /* unknown */
591*c2c66affSColin Finck   PUT_SHORT(buffer, 32, NumProg);
592*c2c66affSColin Finck 
593*c2c66affSColin Finck   if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 34)) return FALSE;
594*c2c66affSColin Finck 
595*c2c66affSColin Finck   /* Program table */
596*c2c66affSColin Finck   CurrProg = Progs;
597*c2c66affSColin Finck   CurrIcon = Icons;
598*c2c66affSColin Finck   hProgram = group->hPrograms;
599*c2c66affSColin Finck   while(hProgram)
600*c2c66affSColin Finck     {
601*c2c66affSColin Finck       PROGRAM *program = LocalLock(hProgram);
602*c2c66affSColin Finck 
603*c2c66affSColin Finck       PUT_SHORT(buffer, 0, CurrProg);
604*c2c66affSColin Finck       if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 2))
605*c2c66affSColin Finck 	      return FALSE;
606*c2c66affSColin Finck 
607*c2c66affSColin Finck       GRPFILE_CalculateSizes(program, &CurrProg, &CurrIcon, &sizeAnd, &sizeXor);
608*c2c66affSColin Finck       hProgram = program->hNext;
609*c2c66affSColin Finck     }
610*c2c66affSColin Finck 
611*c2c66affSColin Finck   /* Title */
612*c2c66affSColin Finck   if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, lpszTitle, strlen(lpszTitle) + 1))
613*c2c66affSColin Finck     return FALSE;
614*c2c66affSColin Finck 
615*c2c66affSColin Finck   /* Program entries */
616*c2c66affSColin Finck   CurrProg = Progs;
617*c2c66affSColin Finck   CurrIcon = Icons;
618*c2c66affSColin Finck   hProgram = group->hPrograms;
619*c2c66affSColin Finck   while(hProgram)
620*c2c66affSColin Finck     {
621*c2c66affSColin Finck       PROGRAM *program = LocalLock(hProgram);
622*c2c66affSColin Finck       LPCSTR Name     = LocalLock(program->hName);
623*c2c66affSColin Finck       LPCSTR CmdLine  = LocalLock(program->hCmdLine);
624*c2c66affSColin Finck       LPCSTR IconFile = LocalLock(program->hIconFile);
625*c2c66affSColin Finck       INT next_prog = CurrProg;
626*c2c66affSColin Finck       INT next_icon = CurrIcon;
627*c2c66affSColin Finck 
628*c2c66affSColin Finck       GRPFILE_CalculateSizes(program, &next_prog, &next_icon, &sizeAnd, &sizeXor);
629*c2c66affSColin Finck       PUT_SHORT(buffer,  0, program->x);
630*c2c66affSColin Finck       PUT_SHORT(buffer,  2, program->y);
631*c2c66affSColin Finck       PUT_SHORT(buffer,  4, program->nIconIndex);
632*c2c66affSColin Finck       PUT_SHORT(buffer,  6, 0x048c);            /* unknown */
633*c2c66affSColin Finck       PUT_SHORT(buffer,  8, sizeXor);
634*c2c66affSColin Finck       PUT_SHORT(buffer, 10, sizeAnd * 8);
635*c2c66affSColin Finck       PUT_SHORT(buffer, 12, CurrIcon);
636*c2c66affSColin Finck       PUT_SHORT(buffer, 14, CurrIcon + 12 + sizeAnd);
637*c2c66affSColin Finck       PUT_SHORT(buffer, 16, CurrIcon + 12);
638*c2c66affSColin Finck       ptr = CurrProg + 24;
639*c2c66affSColin Finck       PUT_SHORT(buffer, 18, ptr);
640*c2c66affSColin Finck       ptr += strlen(Name) + 1;
641*c2c66affSColin Finck       PUT_SHORT(buffer, 20, ptr);
642*c2c66affSColin Finck       ptr += strlen(CmdLine) + 1;
643*c2c66affSColin Finck       PUT_SHORT(buffer, 22, ptr);
644*c2c66affSColin Finck 
645*c2c66affSColin Finck       if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 24) ||
646*c2c66affSColin Finck 	  (UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, Name, strlen(Name) + 1) ||
647*c2c66affSColin Finck 	  (UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, CmdLine, strlen(CmdLine) + 1) ||
648*c2c66affSColin Finck 	  (UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, IconFile, strlen(IconFile) + 1))
649*c2c66affSColin Finck 	return FALSE;
650*c2c66affSColin Finck 
651*c2c66affSColin Finck       CurrProg = next_prog;
652*c2c66affSColin Finck       CurrIcon = next_icon;
653*c2c66affSColin Finck       hProgram = program->hNext;
654*c2c66affSColin Finck     }
655*c2c66affSColin Finck 
656*c2c66affSColin Finck   /* Icons */
657*c2c66affSColin Finck #if 0  /* FIXME: this is broken anyway */
658*c2c66affSColin Finck   hProgram = group->hPrograms;
659*c2c66affSColin Finck   while(hProgram)
660*c2c66affSColin Finck     {
661*c2c66affSColin Finck       PROGRAM *program = LocalLock(hProgram);
662*c2c66affSColin Finck       CURSORICONINFO *iconinfo = LocalLock(program->hIcon);
663*c2c66affSColin Finck       LPVOID XorBits, AndBits;
664*c2c66affSColin Finck       INT sizeXor = iconinfo->nHeight * iconinfo->nWidthBytes;
665*c2c66affSColin Finck       INT sizeAnd = iconinfo->nHeight * ((iconinfo->nWidth + 15) / 16 * 2);
666*c2c66affSColin Finck       /* DumpIcon16(LocalLock(program->hIcon), 0, &XorBits, &AndBits);*/
667*c2c66affSColin Finck 
668*c2c66affSColin Finck       PUT_SHORT(buffer, 0, iconinfo->ptHotSpot.x);
669*c2c66affSColin Finck       PUT_SHORT(buffer, 2, iconinfo->ptHotSpot.y);
670*c2c66affSColin Finck       PUT_SHORT(buffer, 4, iconinfo->nWidth);
671*c2c66affSColin Finck       PUT_SHORT(buffer, 6, iconinfo->nHeight);
672*c2c66affSColin Finck       PUT_SHORT(buffer, 8, iconinfo->nWidthBytes);
673*c2c66affSColin Finck       buffer[10] = iconinfo->bPlanes;
674*c2c66affSColin Finck       buffer[11] = iconinfo->bBitsPerPixel;
675*c2c66affSColin Finck 
676*c2c66affSColin Finck       if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 12) ||
677*c2c66affSColin Finck 	  (UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, AndBits, sizeAnd) ||
678*c2c66affSColin Finck 	  (UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, XorBits, sizeXor)) return FALSE;
679*c2c66affSColin Finck 
680*c2c66affSColin Finck       hProgram = program->hNext;
681*c2c66affSColin Finck     }
682*c2c66affSColin Finck #endif
683*c2c66affSColin Finck 
684*c2c66affSColin Finck   if (need_extension)
685*c2c66affSColin Finck     {
686*c2c66affSColin Finck       /* write `PMCC' extension */
687*c2c66affSColin Finck       PUT_SHORT(buffer, 0, 0x8000);
688*c2c66affSColin Finck       PUT_SHORT(buffer, 2, 0xffff);
689*c2c66affSColin Finck       PUT_SHORT(buffer, 4, 0x000a);
690*c2c66affSColin Finck       buffer[6] = 'P', buffer[7] = 'M';
691*c2c66affSColin Finck       buffer[8] = 'C', buffer[9] = 'C';
692*c2c66affSColin Finck       if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 10))
693*c2c66affSColin Finck 	      return FALSE;
694*c2c66affSColin Finck 
695*c2c66affSColin Finck       seqnum = 0;
696*c2c66affSColin Finck       hProgram = group->hPrograms;
697*c2c66affSColin Finck       while(hProgram)
698*c2c66affSColin Finck 	{
699*c2c66affSColin Finck 	  PROGRAM *program = LocalLock(hProgram);
700*c2c66affSColin Finck 	  LPCSTR lpszWorkDir = LocalLock(program->hWorkDir);
701*c2c66affSColin Finck 
702*c2c66affSColin Finck 	  /* Working directory */
703*c2c66affSColin Finck 	  if (lpszWorkDir[0])
704*c2c66affSColin Finck 	    {
705*c2c66affSColin Finck 	      PUT_SHORT(buffer, 0, 0x8101);
706*c2c66affSColin Finck 	      PUT_SHORT(buffer, 2, seqnum);
707*c2c66affSColin Finck 	      PUT_SHORT(buffer, 4, 7 + strlen(lpszWorkDir));
708*c2c66affSColin Finck 	      if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 6) ||
709*c2c66affSColin Finck 		  (UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, lpszWorkDir, strlen(lpszWorkDir) + 1))
710*c2c66affSColin Finck 		return FALSE;
711*c2c66affSColin Finck 	    }
712*c2c66affSColin Finck 
713*c2c66affSColin Finck 	  /* Hot key */
714*c2c66affSColin Finck 	  if (program->nHotKey)
715*c2c66affSColin Finck 	    {
716*c2c66affSColin Finck 	      PUT_SHORT(buffer, 0, 0x8102);
717*c2c66affSColin Finck 	      PUT_SHORT(buffer, 2, seqnum);
718*c2c66affSColin Finck 	      PUT_SHORT(buffer, 4, 8);
719*c2c66affSColin Finck 	      PUT_SHORT(buffer, 6, program->nHotKey);
720*c2c66affSColin Finck 	      if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 8)) return FALSE;
721*c2c66affSColin Finck 	    }
722*c2c66affSColin Finck 
723*c2c66affSColin Finck 	  /* Show command */
724*c2c66affSColin Finck 	  if (program->nCmdShow)
725*c2c66affSColin Finck 	    {
726*c2c66affSColin Finck 	      PUT_SHORT(buffer, 0, 0x8103);
727*c2c66affSColin Finck 	      PUT_SHORT(buffer, 2, seqnum);
728*c2c66affSColin Finck 	      PUT_SHORT(buffer, 4, 8);
729*c2c66affSColin Finck 	      PUT_SHORT(buffer, 6, program->nCmdShow);
730*c2c66affSColin Finck 	      if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 8)) return FALSE;
731*c2c66affSColin Finck 	    }
732*c2c66affSColin Finck 
733*c2c66affSColin Finck 	  seqnum++;
734*c2c66affSColin Finck 	  hProgram = program->hNext;
735*c2c66affSColin Finck 	}
736*c2c66affSColin Finck 
737*c2c66affSColin Finck       /* Write `End' extension */
738*c2c66affSColin Finck       PUT_SHORT(buffer, 0, 0xffff);
739*c2c66affSColin Finck       PUT_SHORT(buffer, 2, 0xffff);
740*c2c66affSColin Finck       PUT_SHORT(buffer, 4, 0x0000);
741*c2c66affSColin Finck       if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 6)) return FALSE;
742*c2c66affSColin Finck     }
743*c2c66affSColin Finck 
744*c2c66affSColin Finck   checksum = GRPFILE_GetChecksum();
745*c2c66affSColin Finck   _llseek(file, 4, SEEK_SET);
746*c2c66affSColin Finck   PUT_SHORT(buffer, 0, checksum);
747*c2c66affSColin Finck   _lwrite(file, buffer, 2);
748*c2c66affSColin Finck 
749*c2c66affSColin Finck   return TRUE;
750*c2c66affSColin Finck }
751*c2c66affSColin Finck 
752*c2c66affSColin Finck #endif
753