source: branches/branch-1-0/src/helpers/xprf2.c@ 231

Last change on this file since 231 was 229, checked in by umoeller, 23 years ago

Sources as of 1.0.0.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 21.0 KB
Line 
1
2/*
3 *@@sourcefile xprf2.c:
4 * copy-profile functions which use the replacement
5 * profile functions in xprf.c.
6 *
7 * This can be used for a bomb-proof "save system profiles"
8 * (see xprfSaveINIs).
9 *
10 * Usage: All OS/2 programs.
11 *
12 * Function prefixes:
13 * -- xprf* replacement profile (INI) functions
14 *
15 * Note: Version numbering in this file relates to XWorkplace version
16 * numbering.
17 *
18 *@@header "helpers\xprf.h"
19 *@@added V0.9.5 (2000-08-10) [umoeller]
20 */
21
22/*
23 * Copyright (C) 2000 Ulrich M”ller.
24 * This file is part of the "XWorkplace helpers" source package.
25 * This is free software; you can redistribute it and/or modify
26 * it under the terms of the GNU General Public License as published
27 * by the Free Software Foundation, in version 2 as it comes in the
28 * "COPYING" file of the XWorkplace main distribution.
29 * This program is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * GNU General Public License for more details.
33 */
34
35#define OS2EMX_PLAIN_CHAR
36 // this is needed for "os2emx.h"; if this is defined,
37 // emx will define PSZ as _signed_ char, otherwise
38 // as unsigned char
39
40#define INCL_DOSERRORS
41#define INCL_WINSHELLDATA
42#include <os2.h>
43
44#include <stdlib.h>
45#include <stdio.h>
46#include <string.h>
47
48#include "setup.h" // code generation and debugging options
49
50#include "helpers\dosh.h"
51#include "helpers\prfh.h"
52#include "helpers\stringh.h"
53#include "helpers\xprf.h"
54
55#pragma hdrstop
56
57/*
58 *@@category: Helpers\Profile (INI) replacement functions
59 */
60
61/* ******************************************************************
62 *
63 * Copy API Functions
64 *
65 ********************************************************************/
66
67/*
68 *@@ xprfCopyKey:
69 * copies a single key from an Prf* HINI to an xprf* PXINI.
70 * hiniTarget must therefore have been opened using
71 * xprfOpenProfile.
72 *
73 * This returns 0 (NO_ERROR) if copying succeeded. Otherwise either
74 * an OS/2 error code (ERROR_*) or one of the profile error
75 * codes defined in prfh.h is returned.
76 */
77
78APIRET xprfCopyKey(HINI hiniSource, // in: source profile (can be HINI_USER or HINI_SYSTEM)
79 PCSZ pszSourceApp, // in: source application
80 PCSZ pszKey, // in: source/target key
81 PXINI hiniTarget, // in: target profile opened with xprfOpenProfile
82 PCSZ pszTargetApp) // in: target app
83{
84 ULONG ulSizeOfData = 0;
85 APIRET arc = NO_ERROR;
86
87 if (PrfQueryProfileSize(hiniSource,
88 (PSZ)pszSourceApp,
89 (PSZ)pszKey,
90 &ulSizeOfData))
91 {
92 PSZ pData = 0;
93
94 // copy data
95 if (ulSizeOfData == 0)
96 {
97 // data size == 0: this shouldn't really happen,
98 // but if it does, we'll just create a NULL string.
99 // Users have reported that some INI files seem to
100 // contain those "empty" keys. I don't see how these
101 // can exist, but they seem to...
102 pData = (PSZ)malloc(1);
103 *pData = 0;
104 }
105 else
106 pData = (PSZ)malloc(ulSizeOfData);
107
108 if (pData)
109 {
110 fflush(stdout);
111 if (PrfQueryProfileData(hiniSource,
112 (PSZ)pszSourceApp,
113 (PSZ)pszKey,
114 pData,
115 &ulSizeOfData))
116 {
117 arc = xprfWriteProfileData(hiniTarget,
118 pszTargetApp,
119 pszKey,
120 pData,
121 ulSizeOfData);
122 }
123 else
124 arc = PRFERR_READ;
125
126 free(pData);
127 }
128 else
129 arc = ERROR_NOT_ENOUGH_MEMORY;
130 }
131 else
132 arc = PRFERR_DATASIZE;
133
134 return arc;
135}
136
137/*
138 *@@ xprfCopyKey2:
139 * copies a single key from an xprf* PXINI to a Prf* HINI.
140 * hiniSource must therefore have been opened using
141 * xprfOpenProfile.
142 *
143 * This returns 0 (NO_ERROR) if copying succeeded. Otherwise either
144 * an OS/2 error code (ERROR_*) or one of the profile error
145 * codes defined in prfh.h is returned.
146 *
147 *@@added V1.0.0 (2002-09-17) [umoeller]
148 */
149
150APIRET xprfCopyKey2(PXINI hiniSource, // in: source profile (can be HINI_USER or HINI_SYSTEM)
151 PCSZ pszSourceApp, // in: source application
152 PCSZ pszKey, // in: source/target key
153 HINI hiniTarget, // in: target profile opened with xprfOpenProfile
154 PCSZ pszTargetApp) // in: target app
155{
156 ULONG ulSizeOfData = 0;
157 APIRET arc = NO_ERROR;
158
159 if (xprfQueryProfileSize(hiniSource, pszSourceApp, pszKey, &ulSizeOfData))
160 {
161 PSZ pData = 0;
162
163 // copy data
164 if (ulSizeOfData == 0)
165 {
166 // data size == 0: this shouldn't really happen,
167 // but if it does, we'll just create a NULL string.
168 // Users have reported that some INI files seem to
169 // contain those "empty" keys. I don't see how these
170 // can exist, but they seem to...
171 pData = (PSZ)malloc(1);
172 *pData = 0;
173 }
174 else
175 pData = (PSZ)malloc(ulSizeOfData);
176
177 if (pData)
178 {
179 fflush(stdout);
180 if (xprfQueryProfileData(hiniSource,
181 pszSourceApp,
182 pszKey,
183 pData,
184 &ulSizeOfData))
185 {
186 if (!PrfWriteProfileData(hiniTarget,
187 (PSZ)pszTargetApp,
188 (PSZ)pszKey,
189 pData,
190 ulSizeOfData))
191 arc = PRFERR_WRITE;
192 }
193 else
194 arc = PRFERR_READ;
195
196 free(pData);
197 }
198 else
199 arc = ERROR_NOT_ENOUGH_MEMORY;
200 }
201 else
202 arc = PRFERR_DATASIZE;
203
204 return arc;
205}
206
207/*
208 *@@ xprfCopyApp:
209 * copies a single application from a Prf* HINI to an xprf* PXINI.
210 * hiniTarget must therefore have been opened using
211 * xprfOpenProfile.
212 *
213 * This calls xprfCopyKey for each key in the application.
214 *
215 * This returns 0 (NO_ERROR) if copying succeeded. Otherwise either
216 * an OS/2 error code (ERROR_*) or one of the profile error
217 * codes defined in prfh.h is returned.
218 */
219
220APIRET xprfCopyApp(HINI hiniSource, // in: source profile (can be HINI_USER or HINI_SYSTEM)
221 PCSZ pszSourceApp, // in: source application
222 PXINI hiniTarget, // in: target profile opened with xprfOpenProfile
223 PCSZ pszTargetApp, // in: name of pszSourceApp in hiniTarget
224 PSZ pszErrorKey) // out: failing key in case of error; ptr can be NULL
225{
226 APIRET arc = NO_ERROR;
227 PSZ pszKeysList = NULL;
228
229 if (pszErrorKey)
230 *pszErrorKey = 0;
231
232 if (!(arc = prfhQueryKeysForApp(hiniSource,
233 pszSourceApp,
234 &pszKeysList)))
235 {
236 PSZ pKey2 = pszKeysList;
237
238 while (*pKey2 != 0)
239 {
240 // copy this key
241 if (arc = xprfCopyKey(hiniSource,
242 pszSourceApp,
243 pKey2,
244 hiniTarget,
245 pszTargetApp))
246 {
247 // error: copy failing key to buffer
248 if (pszErrorKey)
249 strcpy(pszErrorKey, pKey2);
250 break;
251 }
252
253 pKey2 += strlen(pKey2)+1;
254 } // end while (*pKey2 != 0)
255
256 free (pszKeysList);
257 }
258 else
259 arc = PRFERR_KEYSLIST;
260
261 return arc;
262}
263
264/*
265 *@@ xprfCopyApp2:
266 * copies a single application from an xprf* PXINI to a Prf* HINI.
267 * hiniTarget must therefore have been opened using
268 * xprfOpenProfile.
269 *
270 * This calls xprfCopyKey2 for each key in the application.
271 *
272 * This returns 0 (NO_ERROR) if copying succeeded. Otherwise either
273 * an OS/2 error code (ERROR_*) or one of the profile error
274 * codes defined in prfh.h is returned.
275 *
276 *@@added V1.0.0 (2002-09-17) [umoeller]
277 */
278
279APIRET xprfCopyApp2(PXINI hiniSource, // in: source profile (can be HINI_USER or HINI_SYSTEM)
280 PCSZ pszSourceApp, // in: source application
281 HINI hiniTarget, // in: target profile opened with xprfOpenProfile
282 PCSZ pszTargetApp, // in: name of pszSourceApp in hiniTarget
283 PSZ pszErrorKey) // out: failing key in case of error; ptr can be NULL
284{
285 APIRET arc = NO_ERROR;
286 PSZ pszKeysList = NULL;
287
288 if (pszErrorKey)
289 *pszErrorKey = 0;
290
291 if (!(arc = xprfQueryKeysForApp(hiniSource,
292 pszSourceApp,
293 &pszKeysList)))
294 {
295 PSZ pKey2 = pszKeysList;
296
297 while (*pKey2 != 0)
298 {
299 // copy this key
300 if (arc = xprfCopyKey2(hiniSource,
301 pszSourceApp,
302 pKey2,
303 hiniTarget,
304 pszTargetApp))
305 {
306 // error: copy failing key to buffer
307 if (pszErrorKey)
308 strcpy(pszErrorKey, pKey2);
309 break;
310 }
311
312 pKey2 += strlen(pKey2)+1;
313 } // end while (*pKey2 != 0)
314
315 free (pszKeysList);
316 }
317 else
318 arc = PRFERR_KEYSLIST;
319
320 return arc;
321}
322
323/*
324 *@@ xprfCopyProfile:
325 * this copies an entire profile.
326 *
327 * The source profile must have been opened using the
328 * regular OS/2 PrfOpenProfile. You can also specify
329 * HINI_USER or HINI_SYSTEM.
330 *
331 * pszNew specifies the file name for the new profile.
332 * This must end in *.INI. The new profile is opened
333 * using xprfOpenProfile, so see additional remarks there.
334 *
335 * This returns 0 (NO_ERROR) on success. Otherwise either
336 * an OS/2 error code (ERROR_*) or one of the profile error
337 * codes defined in prfh.h is returned.
338 */
339
340APIRET xprfCopyProfile(HINI hOld, // in: source profile (can be HINI_USER or HINI_SYSTEM)
341 PCSZ pszNew, // in: new filename (can be fully qualified)
342 PFN_PRF_PROGRESS pfnProgressCallback,
343 ULONG ulUser, // in: passed to pfnProgressCallback
344 ULONG ulCount, // in: index of INI being copied (0 <= ulCount <= ulMax)
345 ULONG ulMax, // in: maximum index (for progress); 0 means 1 INI, 1 means 2 INIs, ...
346 PSZ pszFailingApp) // out: failing app on error
347{
348 APIRET arc = NO_ERROR;
349 PXINI pxiniNew = NULL;
350 ULONG ulSizeOfAppsList;
351
352 if (pszFailingApp)
353 *pszFailingApp = 0;
354
355 if (!pszNew)
356 arc = ERROR_INVALID_PARAMETER;
357 else
358 {
359 DosDelete((PSZ)pszNew);
360
361 // open new profile
362 if (!(arc = xprfOpenProfile(pszNew,
363 &pxiniNew)))
364 {
365 // get size of applications list
366 if (!PrfQueryProfileSize(hOld, NULL, NULL, &ulSizeOfAppsList))
367 arc = PRFERR_APPSLIST;
368 else
369 if (ulSizeOfAppsList == 0)
370 arc = PRFERR_APPSLIST;
371
372 if (arc == NO_ERROR)
373 {
374 // get applications list
375 PSZ pApps = (PSZ)malloc(ulSizeOfAppsList);
376 PSZ pApp2 = pApps;
377 if (!PrfQueryProfileData(hOld,
378 NULL,
379 NULL,
380 pApps,
381 &ulSizeOfAppsList))
382 arc = PRFERR_APPSLIST;
383
384 // applications loop
385
386 while ( (*pApp2 != 0)
387 && (arc == NO_ERROR)
388 )
389 {
390 CHAR szErrorKey[1000];
391
392 // copy application (this will call prfhCopyKey in turn)
393 if (arc = xprfCopyApp(hOld,
394 pApp2,
395 pxiniNew,
396 pApp2,
397 szErrorKey))
398 {
399 if (pszFailingApp)
400 strhncpy0(pszFailingApp, pApp2, CCHMAXPATH);
401 }
402 else if (pfnProgressCallback)
403 {
404 ULONG ulNow2, ulMax2;
405 ulNow2 = ((1000*(pApp2-pApps)) / ulSizeOfAppsList) + (ulCount*1000);
406 ulMax2 = (ulMax+1)*1000;
407 if (!pfnProgressCallback(ulUser, ulNow2, ulMax2))
408 // aborted:
409 arc = PRFERR_ABORTED;
410 }
411
412 // go for next app
413 pApp2 += strlen(pApp2)+1;
414
415 } // end while (*pApp2 != 0) && MBID_NOERROR
416
417 if (pApps)
418 free(pApps);
419 }
420
421 xprfCloseProfile(pxiniNew);
422
423 // progress
424 if (pfnProgressCallback)
425 pfnProgressCallback(ulUser, (ulCount+1) * 1000, (ulMax+1) * 1000);
426 }
427 }
428
429 return arc;
430}
431
432/*
433 *@@ xprfSaveINIs:
434 * this rewrites the OS/2 user and system profiles
435 * (OS2.INI and OS2SYS.INI) to disk. This is done
436 * by doing the following:
437 *
438 * -- First, both profiles are dumped into two temporary
439 * profiles (using xprfCopyProfile on each of them).
440 * These are put into the same directory as the source
441 * profiles (?:\OS2 normally) with a file name extension
442 * of OS2*.XFL.
443 *
444 * -- Only if that succeeded, the original profiles are
445 * renamed to OS2*.BAK. Existing OS2*.BAK files are
446 * deleted.
447 *
448 * -- If that succeded, the temporary OS2*.XFL files are
449 * renamed to OS2*.INI.
450 *
451 * This is now used during XShutdown to dump the system
452 * profiles before shutting down the system. As opposed to
453 * prfhSaveINIs, which was previously used, this does not
454 * use the Prf* functions for the target profiles so that
455 * those ugly "Error saving INI files" errors are less likely.
456 *
457 * This returns 0 (NO_ERROR) if copying succeeded. Otherwise either
458 * an OS/2 error code (ERROR_*) or one of the profile error
459 * codes defined in prfh.h is returned.
460 */
461
462APIRET xprfSaveINIs(HAB hab, // in: anchor block
463 PFN_PRF_PROGRESS pfnProgressCallback,
464 ULONG ulUser,
465 PSZ pszFailingINI,
466 PSZ pszFailingApp,
467 PSZ pszFailingKey)
468{
469 PRFPROFILE Profiles;
470 APIRET arc = NO_ERROR;
471
472 // FILESTATUS3 fs3;
473 CHAR szSysNew[CCHMAXPATH],
474 szUserNew[CCHMAXPATH],
475 szSysBackup[CCHMAXPATH],
476 szUserBackup[CCHMAXPATH];
477
478 /*
479 * get system profiles:
480 *
481 */
482
483 Profiles.cchUserName = Profiles.cchSysName = 0;
484 if (!PrfQueryProfile(hab, &Profiles))
485 arc = PRFERR_QUERY;
486 else
487 {
488 Profiles.pszUserName = (PSZ)malloc(Profiles.cchUserName);
489 Profiles.pszSysName = (PSZ)malloc(Profiles.cchSysName);
490 if ( (Profiles.pszSysName == NULL)
491 || (Profiles.pszUserName == NULL)
492 )
493 arc = PRFERR_QUERY;
494 else
495 if (!PrfQueryProfile(hab, &Profiles))
496 arc = PRFERR_QUERY;
497 }
498
499 if (arc == NO_ERROR)
500 {
501 PSZ _p;
502
503 /*
504 * create new profile names:
505 * same as old profiles, but with *.XFL ext.
506 */
507
508 // system INI
509 strcpy(szSysBackup, Profiles.pszSysName);
510 strcpy(szSysNew, Profiles.pszSysName);
511 _p = strhistr(szSysBackup, ".INI");
512 if (!_p)
513 arc = PRFERR_INVALID_FILE_NAME;
514 else
515 strcpy(_p, ".BAK");
516 _p = strhistr(szSysNew, ".INI");
517 if (!_p)
518 arc = PRFERR_INVALID_FILE_NAME;
519 else
520 strcpy(_p, ".XFL");
521
522 // user INI
523 strcpy(szUserBackup, Profiles.pszUserName);
524 strcpy(szUserNew, Profiles.pszUserName);
525 _p = strhistr(szUserBackup, ".INI");
526 if (!_p)
527 arc = PRFERR_INVALID_FILE_NAME;
528 else
529 strcpy(_p, ".BAK");
530 _p = strhistr(szUserNew, ".INI");
531 if (!_p)
532 arc = PRFERR_INVALID_FILE_NAME;
533 else
534 strcpy(_p, ".XFL");
535
536 /*
537 * create OS2SYS.XFL:
538 *
539 */
540
541 if (arc == NO_ERROR)
542 {
543 if (pszFailingINI)
544 strcpy(pszFailingINI,
545 szSysNew);
546
547 arc = xprfCopyProfile(HINI_SYSTEM,
548 szSysNew, // new filename
549 pfnProgressCallback,
550 ulUser,
551 0,
552 1,
553 pszFailingApp);
554 }
555
556 /*
557 * create OS2SYS.XFL:
558 *
559 */
560
561 if (arc == NO_ERROR)
562 {
563 if (pszFailingINI)
564 strcpy(pszFailingINI,
565 szUserNew);
566
567 arc = xprfCopyProfile(HINI_USER,
568 szUserNew, // new filename
569 pfnProgressCallback,
570 ulUser,
571 1,
572 1,
573 pszFailingApp);
574 }
575 }
576
577 /*
578 * renaming stuff for OS2SYS.INI
579 *
580 */
581
582 if (arc == NO_ERROR)
583 {
584 // attrib -r -s -h -a OS2SYS.BAK
585 doshSetPathAttr(szSysBackup, FILE_NORMAL);
586 // delete OS2SYS.BAK
587 DosDelete(szSysBackup);
588 // attrib -r -s -h -a OS2SYS.INI
589 doshSetPathAttr(Profiles.pszSysName, FILE_NORMAL);
590 // REN OS2SYS.INI OS2SYS.BAK
591 DosMove(Profiles.pszSysName, szSysBackup);
592 }
593
594 /*
595 * renaming stuff for OS2.INI
596 *
597 */
598
599 if (arc == NO_ERROR)
600 {
601 // attrib -r -s -h -a OS2SYS.BAK
602 doshSetPathAttr(szUserBackup, FILE_NORMAL);
603 // delete OS2SYS.BAK
604 DosDelete(szUserBackup);
605 // attrib -r -s -h -a OS2SYS.INI
606 doshSetPathAttr(Profiles.pszUserName, FILE_NORMAL);
607 // REN OS2SYS.INI OS2SYS.BAK
608 DosMove(Profiles.pszUserName, szUserBackup);
609 }
610
611 if (arc == NO_ERROR)
612 {
613 // finally, replace system profiles
614 if (!(arc = DosMove(szSysNew, Profiles.pszSysName)))
615 {
616 if (arc = DosMove(szUserNew, Profiles.pszUserName))
617 {
618 if (pszFailingINI)
619 strcpy(pszFailingINI,
620 szUserNew);
621 }
622 }
623 else
624 {
625 if (pszFailingINI)
626 strcpy(pszFailingINI,
627 szSysNew);
628 }
629 }
630
631 if (Profiles.pszSysName)
632 free(Profiles.pszSysName);
633 if (Profiles.pszUserName)
634 free(Profiles.pszUserName);
635
636 return arc;
637}
638
639// testing
640
641#ifdef __BUILD_XPRF2_MAIN__
642
643BOOL _Optlink fnCallback(ULONG ulUser, ULONG ulNow, ULONG ulMax)
644{
645 printf("\r done %03d%%", ulNow * 100 / ulMax);
646 return (TRUE);
647}
648
649int main(int argc, char* argv[])
650{
651 APIRET arc = 2;
652
653 HAB hab = WinInitialize(0);
654
655 CHAR szFailingINI[CCHMAXPATH] = "",
656 szFailingApp[CCHMAXPATH] = "",
657 szFailingKey[CCHMAXPATH] = "";
658
659 arc = xprfSaveINIs(hab,
660 NULL,
661 0,
662 szFailingINI,
663 szFailingApp,
664 szFailingKey);
665
666 printf("xprfCopyProfile returned %d ('%s', '%s', '%s'.\n",
667 arc,
668 szFailingINI,
669 szFailingApp,
670 szFailingKey);
671
672 WinTerminate(hab);
673
674 return arc;
675}
676
677#endif
678
Note: See TracBrowser for help on using the repository browser.