~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/programs/progman/grpfile.c

Version: ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  1 /*
  2  * Program Manager
  3  *
  4  * Copyright 1996 Ulrich Schmid
  5  *           1997 Peter Schlaile
  6  *
  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.
 11  *
 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.
 16  *
 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 20  */
 21 
 22 #define WIN32_LEAN_AND_MEAN
 23 
 24 #include "windows.h"
 25 #include "wine/winuser16.h"
 26 #include "progman.h"
 27 #include "mmsystem.h"
 28 
 29 #define MALLOCHUNK 1000
 30 
 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))
 37 
 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);
 43 
 44 /***********************************************************************
 45  *
 46  *           GRPFILE_ModifyFileName
 47  *
 48  *  Change extension `.grp' to `.gr'
 49  */
 50 
 51 static VOID GRPFILE_ModifyFileName(LPSTR lpszNewName, LPCSTR lpszOrigName,
 52                                    INT nSize, BOOL bModify)
 53 {
 54   lstrcpyn(lpszNewName, lpszOrigName, nSize);
 55   lpszNewName[nSize-1] = '\0';
 56   if (!bModify) return;
 57   if (!lstrcmpi(lpszNewName + strlen(lpszNewName) - 4, ".grp"))
 58     lpszNewName[strlen(lpszNewName) - 1] = '\0';
 59 }
 60 
 61 /***********************************************************************
 62  *
 63  *           GRPFILE_ReadGroupFile
 64  */
 65 
 66 HLOCAL GRPFILE_ReadGroupFile(LPCSTR lpszPath)
 67 {
 68   CHAR   szPath_gr[MAX_PATHNAME_LEN];
 69   BOOL   bFileNameModified = FALSE;
 70   OFSTRUCT dummy;
 71   HLOCAL hBuffer, hGroup;
 72   INT    size;
 73 
 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)
 77     {
 78       lpszPath = szPath_gr;
 79       bFileNameModified = TRUE;
 80     }
 81 
 82   /* Read the whole file into a buffer */
 83   if (!GRPFILE_ReadFileToBuffer(lpszPath, &hBuffer, &size))
 84     {
 85       MAIN_MessageBoxIDS_s(IDS_GRPFILE_READ_ERROR_s, lpszPath, IDS_ERROR, MB_YESNO);
 86       return(0);
 87     }
 88 
 89   /* Interpret buffer */
 90   hGroup = GRPFILE_ScanGroup(LocalLock(hBuffer), size,
 91                              lpszPath, bFileNameModified);
 92   if (!hGroup)
 93     MAIN_MessageBoxIDS_s(IDS_GRPFILE_READ_ERROR_s, lpszPath, IDS_ERROR, MB_YESNO);
 94 
 95   LocalFree(hBuffer);
 96 
 97   return(hGroup);
 98 }
 99 
100 /***********************************************************************
101  *
102  *           GRPFILE_ReadFileToBuffer
103  */
104 
105 static BOOL GRPFILE_ReadFileToBuffer(LPCSTR path, HLOCAL *phBuffer,
106                                      INT *piSize)
107 {
108   UINT    len, size;
109   LPSTR  buffer;
110   HLOCAL hBuffer, hNewBuffer;
111   HFILE  file;
112 
113   file=_lopen(path, OF_READ);
114   if (file == HFILE_ERROR) return FALSE;
115 
116   size = 0;
117   hBuffer = LocalAlloc(LMEM_FIXED, size + MALLOCHUNK + 1);
118   if (!hBuffer) return FALSE;
119   buffer = LocalLock(hBuffer);
120 
121   while ((len = _lread(file, buffer + size, MALLOCHUNK))
122          == MALLOCHUNK)
123     {
124       size += len;
125       hNewBuffer = LocalReAlloc(hBuffer, size + MALLOCHUNK + 1,
126                                 LMEM_FIXED);
127       if (!hNewBuffer)
128         {
129           LocalFree(hBuffer);
130           return FALSE;
131         }
132       hBuffer = hNewBuffer;
133       buffer = LocalLock(hBuffer);
134     }
135 
136   _lclose(file);
137 
138   if (len == (UINT)HFILE_ERROR)
139     {
140       LocalFree(hBuffer);
141       return FALSE;
142     }
143 
144   size += len;
145   buffer[size] = 0;
146 
147   *phBuffer = hBuffer;
148   *piSize   = size;
149   return TRUE;
150 }
151 
152 /***********************************************************************
153  *           GRPFILE_ScanGroup
154  */
155 
156 static HLOCAL GRPFILE_ScanGroup(LPCSTR buffer, INT size,
157                                 LPCSTR lpszGrpFile,
158                                 BOOL bModifiedFileName)
159 {
160   HLOCAL  hGroup;
161   INT     i, seqnum;
162   LPCSTR  extension;
163   LPCSTR  lpszName;
164   INT     x, y, width, height, iconx, icony, nCmdShow;
165   INT     number_of_programs;
166   BOOL    bOverwriteFileOk;
167 
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;
175   else return(0);
176 
177   /* checksum = GET_USHORT(buffer, 4)   (ignored) */
178 
179   extension = buffer + GET_USHORT(buffer, 6);
180   if (extension == buffer + size) extension = 0;
181   else if (extension + 6 > buffer + size) return(0);
182 
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);
192 
193   /* unknown bytes 24 - 31 ignored */
194   /*
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);
201     */
202 
203   hGroup = GROUP_AddGroup(lpszName, lpszGrpFile, nCmdShow, x, y,
204                           width, height, iconx, icony,
205                           bModifiedFileName, bOverwriteFileOk,
206                           TRUE);
207   if (!hGroup) return(0);
208 
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++)
212     {
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))
218         {
219           GROUP_DeleteGroup(hGroup);
220           return(0);
221         }
222     }
223 
224   /* FIXME shouldn't be necessary */
225   GROUP_ShowGroupWindow(hGroup);
226 
227   return hGroup;
228 }
229 
230 /***********************************************************************
231  *           GRPFILE_ScanProgram
232  */
233 
234 static HLOCAL GRPFILE_ScanProgram(LPCSTR buffer, INT size,
235                                   LPCSTR program_ptr, INT seqnum,
236                                   LPCSTR extension, HLOCAL hGroup,
237                                   LPCSTR lpszGrpFile)
238 {
239   INT    icontype;
240   HICON  hIcon;
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;
246 
247   x               = GET_SHORT(program_ptr, 0);
248   y               = GET_SHORT(program_ptr, 2);
249   nIconIndex      = GET_USHORT(program_ptr, 4);
250 
251   /* FIXME is this correct ?? */
252   icontype = GET_USHORT(program_ptr,  6);
253   switch (icontype)
254     {
255     default:
256       MAIN_MessageBoxIDS_s(IDS_UNKNOWN_FEATURE_s, lpszGrpFile,
257                            IDS_WARNING, MB_OK);
258     case 0x048c:
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);
271       break;
272     case 0x000c:
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);
285     }
286 
287   if (iconANDbits_ptr + iconANDsize > buffer + size ||
288       iconXORbits_ptr + iconXORsize > buffer + size) return(0);
289 
290   hIcon = CreateIcon( Globals.hInstance, iconinfo.nWidth, iconinfo.nHeight,
291                       iconinfo.bPlanes, iconinfo.bBitsPerPixel,
292                       iconANDbits_ptr, iconXORbits_ptr );
293 
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);
301 
302   /* Scan Extensions */
303   lpszWorkDir = "";
304   nHotKey     = 0;
305   nCmdShow    = SW_SHOWNORMAL;
306   if (extension)
307     {
308       LPCSTR ptr = extension;
309       while (ptr + 6 <= buffer + size)
310         {
311           UINT type   = GET_USHORT(ptr, 0);
312           UINT number = GET_USHORT(ptr, 2);
313           UINT skip   = GET_USHORT(ptr, 4);
314 
315           if (number == seqnum)
316             {
317               switch (type)
318                 {
319                 case 0x8000:
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);
323                   break;
324                 case 0x8101:
325                   lpszWorkDir = ptr + 6;
326                   break;
327                 case 0x8102:
328                   if (ptr + 8 > buffer + size) return(0);
329                   nHotKey = GET_USHORT(ptr, 6);
330                   break;
331                 case 0x8103:
332                   if (ptr + 8 > buffer + size) return(0);
333                   nCmdShow = GET_USHORT(ptr, 6);
334                   break;
335                 default:
336                   MAIN_MessageBoxIDS_s(IDS_UNKNOWN_FEATURE_s,
337                                        lpszGrpFile, IDS_WARNING, MB_OK);
338                 }
339             }
340           if (!skip) break;
341           ptr += skip;
342         }
343     }
344 
345   return (PROGRAM_AddProgram(hGroup, hIcon, lpszName, x, y,
346                              lpszCmdLine, lpszIconFile,
347                              nIconIndex, lpszWorkDir,
348                              nHotKey, nCmdShow));
349 }
350 
351 /***********************************************************************
352  *
353  *           GRPFILE_WriteGroupFile
354  */
355 
356 BOOL GRPFILE_WriteGroupFile(HLOCAL hGroup)
357 {
358   CHAR szPath[MAX_PATHNAME_LEN];
359   PROGGROUP *group = LocalLock(hGroup);
360   OFSTRUCT dummy;
361   HFILE file;
362   BOOL ret;
363 
364   GRPFILE_ModifyFileName(szPath, LocalLock(group->hGrpFile),
365                          MAX_PATHNAME_LEN,
366                          group->bFileNameModified);
367 
368   /* Try not to overwrite original files */
369 
370   /* group->bOverwriteFileOk == TRUE only if a file has the modified format */
371   if (!group->bOverwriteFileOk &&
372       OpenFile(szPath, &dummy, OF_EXIST) != HFILE_ERROR)
373     {
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)
378         {
379           /* File exists. Do not overwrite */
380           MAIN_MessageBoxIDS_s(IDS_FILE_NOT_OVERWRITTEN_s, szPath,
381                                IDS_INFO, MB_OK);
382           return FALSE;
383         }
384       /* Inform about the modified file name */
385       if (IDCANCEL ==
386           MAIN_MessageBoxIDS_s(IDS_SAVE_GROUP_AS_s, szPath, IDS_INFO,
387                                MB_OKCANCEL | MB_ICONINFORMATION))
388         return FALSE;
389     }
390 
391   {
392     /* Warn about the (possible) incompatibility */
393     CHAR msg[MAX_PATHNAME_LEN + 200];
394     wsprintf(msg,
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;
400   }
401 
402   /* Open file */
403   file = _lcreat(szPath, 0);
404   if (file != HFILE_ERROR)
405     {
406       ret = GRPFILE_DoWriteGroupFile(file, group);
407       _lclose(file);
408     }
409   else ret = FALSE;
410 
411   if (!ret)
412     MAIN_MessageBoxIDS_s(IDS_FILE_WRITE_ERROR_s, szPath, IDS_ERROR, MB_OK);
413 
414   return(ret);
415 }
416 
417 /***********************************************************************
418  *
419  *           GRPFILE_CalculateSizes
420  */
421 
422 static VOID GRPFILE_CalculateSizes(PROGRAM *program,
423                                    INT *Progs, INT *Icons)
424 {
425   CURSORICONINFO *iconinfo = LocalLock(program->hIcon);
426   INT sizeXor = iconinfo->nHeight * iconinfo->nWidthBytes;
427   INT sizeAnd = iconinfo->nHeight * ((iconinfo->nWidth + 15) / 16 * 2);
428 
429   *Progs += 24;
430   *Progs += lstrlen(LocalLock(program->hName)) + 1;
431   *Progs += lstrlen(LocalLock(program->hCmdLine)) + 1;
432   *Progs += lstrlen(LocalLock(program->hIconFile)) + 1;
433 
434   *Icons += 12; /* IconInfo */
435   *Icons += sizeAnd;
436   *Icons += sizeXor;
437 }
438 
439 /***********************************************************************/
440 UINT16 GRPFILE_checksum;
441 BOOL GRPFILE_checksum_half_word;
442 BYTE GRPFILE_checksum_last_byte;
443 /***********************************************************************
444  *
445  *           GRPFILE_InitChecksum
446  */
447 
448 static void GRPFILE_InitChecksum(void)
449 {
450         GRPFILE_checksum = 0;
451         GRPFILE_checksum_half_word = 0;
452 }
453 
454 /***********************************************************************
455  *
456  *           GRPFILE_GetChecksum
457  */
458 
459 static UINT16 GRPFILE_GetChecksum(void)
460 {
461         return GRPFILE_checksum;
462 }
463 
464 /***********************************************************************
465  *
466  *           GRPFILE_WriteWithChecksum
467  *
468  * Looks crazier than it is:
469  *
470  * chksum = 0;
471  * chksum = cksum - 1. word;
472  * chksum = cksum - 2. word;
473  * ...
474  *
475  * if (filelen is even)
476  *      great I'm finished
477  * else
478  *      ignore last byte
479  */
480 
481 static UINT GRPFILE_WriteWithChecksum(HFILE file, LPCSTR str, UINT size)
482 {
483         UINT i;
484         if (GRPFILE_checksum_half_word) {
485                 GRPFILE_checksum -= GRPFILE_checksum_last_byte;
486         }
487         for (i=0; i < size; i++) {
488                 if (GRPFILE_checksum_half_word) {
489                         GRPFILE_checksum -= str[i] << 8;
490                 } else {
491                         GRPFILE_checksum -= str[i];
492                 }
493                 GRPFILE_checksum_half_word ^= 1;
494         }
495 
496         if (GRPFILE_checksum_half_word) {
497                 GRPFILE_checksum_last_byte = str[size-1];
498                 GRPFILE_checksum += GRPFILE_checksum_last_byte;
499         }
500 
501         return _lwrite(file, str, size);
502 }
503 
504 
505 /***********************************************************************
506  *
507  *           GRPFILE_DoWriteGroupFile
508  */
509 
510 static BOOL GRPFILE_DoWriteGroupFile(HFILE file, PROGGROUP *group)
511 {
512   CHAR buffer[34];
513   HLOCAL hProgram;
514   INT    NumProg, Title, Progs, Icons, Extension;
515   INT    CurrProg, CurrIcon, nCmdShow, ptr, seqnum;
516   BOOL   need_extension;
517   LPCSTR lpszTitle = LocalLock(group->hName);
518 
519   UINT16 checksum;
520 
521   GRPFILE_InitChecksum();
522 
523   /* Calculate offsets */
524   NumProg = 0;
525   Icons   = 0;
526   Extension = 0;
527   need_extension = FALSE;
528   hProgram = group->hPrograms;
529   while(hProgram)
530     {
531       PROGRAM *program = LocalLock(hProgram);
532       LPCSTR lpszWorkDir = LocalLock(program->hWorkDir);
533 
534       NumProg++;
535       GRPFILE_CalculateSizes(program, &Icons, &Extension);
536 
537       /* Set a flag if an extension is needed */
538       if (lpszWorkDir[0] || program->nHotKey ||
539           program->nCmdShow != SW_SHOWNORMAL) need_extension = TRUE;
540 
541       hProgram = program->hNext;
542     }
543   Title      = 34 + NumProg * 2;
544   Progs      = Title + lstrlen(lpszTitle) + 1;
545   Icons     += Progs;
546   Extension += Icons;
547 
548   /* Header */
549   buffer[0] = 'P';
550   buffer[1] = 'M';
551   buffer[2] = 'C';
552   buffer[3] = 'C';
553 
554   PUT_SHORT(buffer,  4, 0); /* Checksum zero for now, written later */
555   PUT_SHORT(buffer,  6, Extension);
556   /* Update group->nCmdShow */
557   if (IsIconic(group->hWnd))      nCmdShow = SW_SHOWMINIMIZED;
558   else if (IsZoomed(group->hWnd)) nCmdShow = SW_SHOWMAXIMIZED;
559   else                            nCmdShow = SW_SHOWNORMAL;
560   PUT_SHORT(buffer,  8, nCmdShow);
561   PUT_SHORT(buffer, 10, group->x);
562   PUT_SHORT(buffer, 12, group->y);
563   PUT_SHORT(buffer, 14, group->width);
564   PUT_SHORT(buffer, 16, group->height);
565   PUT_SHORT(buffer, 18, group->iconx);
566   PUT_SHORT(buffer, 20, group->icony);
567   PUT_SHORT(buffer, 22, Title);
568   PUT_SHORT(buffer, 24, 0x0020); /* unknown */
569   PUT_SHORT(buffer, 26, 0x0020); /* unknown */
570   PUT_SHORT(buffer, 28, 0x0108); /* unknown */
571   PUT_SHORT(buffer, 30, 0x0000); /* unknown */
572   PUT_SHORT(buffer, 32, NumProg);
573 
574   if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 34)) return FALSE;
575 
576   /* Program table */
577   CurrProg = Progs;
578   CurrIcon = Icons;
579   hProgram = group->hPrograms;
580   while(hProgram)
581     {
582       PROGRAM *program = LocalLock(hProgram);
583 
584       PUT_SHORT(buffer, 0, CurrProg);
585       if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 2))
586               return FALSE;
587 
588       GRPFILE_CalculateSizes(program, &CurrProg, &CurrIcon);
589       hProgram = program->hNext;
590     }
591 
592   /* Title */
593   if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, lpszTitle,
594                                                lstrlen(lpszTitle) + 1))
595     return FALSE;
596 
597   /* Program entries */
598   CurrProg = Progs;
599   CurrIcon = Icons;
600   hProgram = group->hPrograms;
601   while(hProgram)
602     {
603       PROGRAM *program = LocalLock(hProgram);
604       CURSORICONINFO *iconinfo = LocalLock(program->hIcon);
605       LPCSTR Name     = LocalLock(program->hName);
606       LPCSTR CmdLine  = LocalLock(program->hCmdLine);
607       LPCSTR IconFile = LocalLock(program->hIconFile);
608       INT sizeXor = iconinfo->nHeight * iconinfo->nWidthBytes;
609       INT sizeAnd = iconinfo->nHeight * ((iconinfo->nWidth + 15) / 16 * 2);
610 
611       PUT_SHORT(buffer,  0, program->x);
612       PUT_SHORT(buffer,  2, program->y);
613       PUT_SHORT(buffer,  4, program->nIconIndex);
614       PUT_SHORT(buffer,  6, 0x048c);            /* unknown */
615       PUT_SHORT(buffer,  8, sizeXor);
616       PUT_SHORT(buffer, 10, sizeAnd * 8);
617       PUT_SHORT(buffer, 12, CurrIcon);
618       PUT_SHORT(buffer, 14, CurrIcon + 12 + sizeAnd);
619       PUT_SHORT(buffer, 16, CurrIcon + 12);
620       ptr = CurrProg + 24;
621       PUT_SHORT(buffer, 18, ptr);
622       ptr += lstrlen(Name) + 1;
623       PUT_SHORT(buffer, 20, ptr);
624       ptr += lstrlen(CmdLine) + 1;
625       PUT_SHORT(buffer, 22, ptr);
626 
627       if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 24) ||
628           (UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, Name, lstrlen(Name) + 1) ||
629           (UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, CmdLine, lstrlen(CmdLine) + 1) ||
630           (UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, IconFile, lstrlen(IconFile) + 1))
631         return FALSE;
632 
633       GRPFILE_CalculateSizes(program, &CurrProg, &CurrIcon);
634       hProgram = program->hNext;
635     }
636 
637   /* Icons */
638 #if 0  /* FIXME: this is broken anyway */
639   hProgram = group->hPrograms;
640   while(hProgram)
641     {
642       PROGRAM *program = LocalLock(hProgram);
643       CURSORICONINFO *iconinfo = LocalLock(program->hIcon);
644       LPVOID XorBits, AndBits;
645       INT sizeXor = iconinfo->nHeight * iconinfo->nWidthBytes;
646       INT sizeAnd = iconinfo->nHeight * ((iconinfo->nWidth + 15) / 16 * 2);
647       /* DumpIcon16(LocalLock(program->hIcon), 0, &XorBits, &AndBits);*/
648 
649       PUT_SHORT(buffer, 0, iconinfo->ptHotSpot.x);
650       PUT_SHORT(buffer, 2, iconinfo->ptHotSpot.y);
651       PUT_SHORT(buffer, 4, iconinfo->nWidth);
652       PUT_SHORT(buffer, 6, iconinfo->nHeight);
653       PUT_SHORT(buffer, 8, iconinfo->nWidthBytes);
654       buffer[10] = iconinfo->bPlanes;
655       buffer[11] = iconinfo->bBitsPerPixel;
656 
657       if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 12) ||
658           (UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, AndBits, sizeAnd) ||
659           (UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, XorBits, sizeXor)) return FALSE;
660 
661       hProgram = program->hNext;
662     }
663 #endif
664 
665   if (need_extension)
666     {
667       /* write `PMCC' extension */
668       PUT_SHORT(buffer, 0, 0x8000);
669       PUT_SHORT(buffer, 2, 0xffff);
670       PUT_SHORT(buffer, 4, 0x000a);
671       buffer[6] = 'P', buffer[7] = 'M';
672       buffer[8] = 'C', buffer[9] = 'C';
673       if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 10))
674               return FALSE;
675 
676       seqnum = 0;
677       hProgram = group->hPrograms;
678       while(hProgram)
679         {
680           PROGRAM *program = LocalLock(hProgram);
681           LPCSTR lpszWorkDir = LocalLock(program->hWorkDir);
682 
683           /* Working directory */
684           if (lpszWorkDir[0])
685             {
686               PUT_SHORT(buffer, 0, 0x8101);
687               PUT_SHORT(buffer, 2, seqnum);
688               PUT_SHORT(buffer, 4, 7 + lstrlen(lpszWorkDir));
689               if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 6) ||
690                   (UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, lpszWorkDir, lstrlen(lpszWorkDir) + 1))
691                 return FALSE;
692             }
693 
694           /* Hot key */
695           if (program->nHotKey)
696             {
697               PUT_SHORT(buffer, 0, 0x8102);
698               PUT_SHORT(buffer, 2, seqnum);
699               PUT_SHORT(buffer, 4, 8);
700               PUT_SHORT(buffer, 6, program->nHotKey);
701               if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 8)) return FALSE;
702             }
703 
704           /* Show command */
705           if (program->nCmdShow)
706             {
707               PUT_SHORT(buffer, 0, 0x8103);
708               PUT_SHORT(buffer, 2, seqnum);
709               PUT_SHORT(buffer, 4, 8);
710               PUT_SHORT(buffer, 6, program->nCmdShow);
711               if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 8)) return FALSE;
712             }
713 
714           seqnum++;
715           hProgram = program->hNext;
716         }
717 
718       /* Write `End' extension */
719       PUT_SHORT(buffer, 0, 0xffff);
720       PUT_SHORT(buffer, 2, 0xffff);
721       PUT_SHORT(buffer, 4, 0x0000);
722       if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 6)) return FALSE;
723     }
724 
725   checksum = GRPFILE_GetChecksum();
726   _llseek(file, 4, SEEK_SET);
727   PUT_SHORT(buffer, 0, checksum);
728   _lwrite(file, buffer, 2);
729 
730   return TRUE;
731 }
732 
733 /* Local Variables:    */
734 /* c-file-style: "GNU" */
735 /* End:                */
736 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.