source: trunk/src/minstall.c

Last change on this file was 2, checked in by ktk, 17 years ago

Initial import

File size: 38.9 KB
Line 
1//
2// MINSTALL/CLI (c) Copyright 2002-2005 Martin Kiewitz
3//
4// This file is part of MINSTALL/CLI for OS/2 / eComStation
5//
6// MINSTALL/CLI is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10//
11// MINSTALL/CLI is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with MINSTALL/CLI. If not, see <http://www.gnu.org/licenses/>.
18//
19
20#define INCL_BASE
21#define INCL_DOSMODULEMGR
22#define INCL_WINMESSAGEMGR
23#define INCL_WINWINDOWMGR
24#include <os2.h>
25#include <malloc.h>
26
27#define INCLUDE_STD_MAIN
28#include <global.h>
29#include <cid.h>
30#include <crcs.h>
31#include <file.h>
32#include <globstr.h>
33#include <msg.h>
34#include <mmi_public.h>
35#include <mmi_msg.h>
36
37CHAR Inkey (void) {
38 KBDKEYINFO UserKey;
39
40 KbdCharIn(&UserKey,0,0);
41 return UserKey.chChar;
42 }
43
44// CID-Mode is set, when we are executed in CID-Mode (/R switch)
45// (CIDCompatibility is set in that case, if response file is old format)
46BOOL MINSTCLI_CIDMode = FALSE;
47ULONG MINSTCLI_ErrorMsgID = 0;
48// CID-Create is set, when being in create-response-file-mode (/C switch)
49// Compatibility is set for original way of creating response files
50BOOL MINSTCLI_CIDCreate = FALSE;
51BOOL MINSTCLI_CIDCompatibility = FALSE;
52// Logfile is set, when log-file is specified /L switch)
53CHAR MINSTCLI_LogFileName[MINSTMAX_PATHLENGTH] = {0};
54// Response file for either CIDmode or CIDrecord
55CHAR MINSTCLI_ResponseFileName[MINSTMAX_PATHLENGTH] = {0};
56ULONG MINSTCLI_ResponseGroups = 0;
57// Source-Path containing CONTROL.scr (only path!)
58CHAR MINSTCLI_SourcePath[MINSTMAX_PATHLENGTH] = {0};
59CHAR MINSTCLI_TargetPath[MINSTMAX_PATHLENGTH] = {0};
60ULONG MINSTCLI_TargetBootDrive = 0;
61
62FILECONTROL RESPONSEFILE;
63PCHAR MINSTCLI_ResponseFilePos;
64ULONG MINSTCLI_ResponseFileLine;
65
66PMINSTPUBGROUP MINSTCLI_PubGroupPtr = 0;
67ULONG MINSTCLI_PubGroupCount = 0;
68
69// /M -> run from MMTEMP??
70// /L:file -> logfile
71// /R:file -> response file mode (CID)
72// /F:file -> points to control.scr file (CLI mode)
73// /C:file -> create response file (for CID)
74
75CHAR MINSTCLI_GetSelectionChar (ULONG SelectionNo) {
76 if (SelectionNo>35) return 0;
77
78 if (SelectionNo<9) {
79 SelectionNo += '1';
80 } else if (SelectionNo==9) {
81 SelectionNo = '0';
82 } else {
83 SelectionNo += 55;
84 }
85 return SelectionNo;
86 }
87
88LONG MINSTCLI_GetSelectionFromUser (ULONG MaxChoice) {
89 CHAR CurChar;
90 LONG CurSelection;
91
92 while (1) {
93 CurChar = toupper(Inkey());
94 if (CurChar==0x1B) { // User pressed ESC
95 return -1;
96 } else if (CurChar==0x0D) { // User pressed ENTER
97 return -2;
98 } else {
99 CurSelection = -1;
100 if ((CurChar>='1') && (CurChar<='9')) {
101 CurSelection = CurChar-'1';
102 } else if (CurChar=='0') {
103 CurSelection = 9;
104 } else if ((CurChar>='A') && (CurChar<='Z')) {
105 CurSelection = CurChar-55;
106 }
107 if (CurSelection!=-1) {
108 if (CurSelection<MaxChoice) return CurSelection;
109 }
110 }
111 }
112 }
113
114BOOL MINSTCLI_UserGroupSelection (void) {
115 PSZ PackageName = 0;
116 PMINSTPUBGROUP CurGroupPtr = 0;
117 ULONG CurGroupNo = 0;
118 ULONG CurPromptNo = 0;
119 PSZ CurOptionPtr = 0;
120 ULONG CurOptionNo = 0;
121 LONG CurChoice = 0;
122 LONG MaxChoice = 0;
123 ULONG CurCardNo = 0;
124 ULONG CardCount = 0;
125 CHAR TempValueStr[2] = {0};
126
127 PackageName = MINSTALL_GetPackageTitlePtr();
128
129 if (MINSTCLI_PubGroupCount) {
130 // First let user choose selection of public groups...
131 while (1) {
132 printf ("\x1B[2J");
133 MSG_Print (MINSTMSG_CLITrailer);
134 printf ("\n");
135 MSG_SetInsertViaPSZ (1, PackageName);
136 MSG_Print (MINSTMSG_CLIActivePackageIs);
137 printf ("\n");
138
139 // Print out all groups...
140 CurGroupNo = 0; CurGroupPtr = MINSTCLI_PubGroupPtr;
141 while (CurGroupNo<MINSTCLI_PubGroupCount) {
142 CurChoice = MINSTCLI_GetSelectionChar(CurGroupNo);
143 printf ("%c - '%s'", CurChoice, CurGroupPtr->Name);
144 if (CurGroupPtr->Selected) {
145 MSG_Print (MINSTMSG_CLIIsSelected);
146 }
147 printf ("\n");
148 CurGroupNo++; CurGroupPtr++;
149 }
150 printf ("\n");
151 MSG_Print (MINSTMSG_CLIChooseGroup);
152
153 CurChoice = MINSTCLI_GetSelectionFromUser(MINSTCLI_PubGroupCount);
154 if (CurChoice==-1) { // User pressed ESC
155 return FALSE;
156 } else if (CurChoice==-2) { // User pressed ENTER
157 break;
158 } else { // Group-Selection
159 // So display group and ask, if user wants to select or deselect it
160 CurGroupNo = 0; CurGroupPtr = MINSTCLI_PubGroupPtr;
161 while (CurGroupNo<CurChoice) {
162 CurGroupNo++; CurGroupPtr++;
163 }
164 if (!CurGroupPtr->SelectionForced) {
165 if (CurGroupPtr->Selected) {
166 MINSTALL_DeSelectGroup (CurGroupPtr->ID);
167 } else {
168 MINSTALL_SelectGroup (CurGroupPtr->ID);
169 }
170 } else {
171 printf ("\n");
172 MSG_Print (MINSTMSG_CLISelectionForced);
173 Inkey();
174 }
175 }
176 }
177
178 // Now let him choose user options per selected group...
179 CurGroupNo = 0; CurGroupPtr = MINSTCLI_PubGroupPtr;
180 while (CurGroupNo<MINSTCLI_PubGroupCount) {
181 if (CurGroupPtr->Selected) {
182 if (CurGroupPtr->MaxCardCount>0) {
183 printf ("\x1B[2J");
184 MSG_Print (MINSTMSG_CLITrailer);
185 printf ("\n");
186 MSG_SetInsertViaPSZ (1, PackageName);
187 MSG_Print (MINSTMSG_CLIActivePackageIs);
188 MSG_SetInsertViaPSZ (1, CurGroupPtr->Name);
189 MSG_Print (MINSTMSG_CLIActiveGroupIs);
190 printf ("\n");
191
192 ultoa (CurGroupPtr->MaxCardCount, TempValueStr, 10);
193 MSG_SetInsertViaPSZ (1, TempValueStr);
194 MSG_Print (MINSTMSG_CLICardSelect);
195 while (1) {
196 CurChoice = Inkey();
197 if (CurChoice==0x1B) {
198 return FALSE;
199 } else if (CurChoice=='0') {
200 CardCount = 0; break;
201 } else if ((CurChoice>='1') && (CurChoice<='9')) {
202 CardCount = CurChoice-'0';
203 if (CardCount<=CurGroupPtr->MaxCardCount)
204 break;
205 }
206 }
207 // User chose CardCount, so set it for MINSTALL.DLL
208 MINSTALL_SetCARDINFOCardCountForGroup (CurGroupPtr->ID, CardCount);
209
210 CurCardNo = 1;
211 while (CurCardNo<=CardCount) {
212 // Give user selection over user prompts per Card
213 if (CurGroupPtr->PromptsCount) {
214 // Set Insert 2 (contains Card-Number)
215 while (1) {
216 // Display Prompt-Selection...
217 printf ("\x1B[2J");
218 MSG_Print (MINSTMSG_CLITrailer);
219 printf ("\n");
220 MSG_SetInsertViaPSZ (1, PackageName);
221 MSG_Print (MINSTMSG_CLIActivePackageIs);
222 MSG_SetInsertViaPSZ (1, CurGroupPtr->Name);
223 MSG_Print (MINSTMSG_CLIActiveGroupIs);
224 ultoa (CurCardNo, TempValueStr, 10);
225 MSG_SetInsertViaPSZ (1, TempValueStr);
226 MSG_Print (MINSTMSG_CLIActiveCardNoIs);
227 printf ("\n");
228
229 // List all prompt-titles including current selection
230 CurPromptNo = 0;
231 while (CurPromptNo<CurGroupPtr->PromptsCount) {
232 CurChoice = MINSTCLI_GetSelectionChar(CurPromptNo);
233 CurOptionNo = MINSTALL_GetCARDINFOChoiceForGroup (CurGroupPtr->ID, CurCardNo, CurPromptNo+1);
234 CurOptionPtr = CurGroupPtr->PromptChoiceStrings[CurPromptNo];
235 while (CurOptionNo>1) {
236 CurOptionPtr = STRING_SkipASCIIZ(CurOptionPtr, NULL);
237 CurOptionNo--;
238 }
239 printf ("%c - %s\x1B[80D\x1B[54C%s\n", CurChoice, CurGroupPtr->PromptTitlePtr[CurPromptNo], CurOptionPtr);
240 CurPromptNo++;
241 }
242 printf ("\n");
243 MSG_Print (MINSTMSG_CLIChoosePrompt);
244
245 CurChoice = MINSTCLI_GetSelectionFromUser(CurGroupPtr->PromptsCount);
246 if (CurChoice==-1) { // User pressed ESC
247 return FALSE;
248 } else if (CurChoice==-2) { // User pressed ENTER
249 break;
250 } else { // Prompt-Selection
251 CurPromptNo = CurChoice;
252
253 while (1) {
254 // So show prompt and let user choose
255 printf ("\x1B[2J");
256 MSG_Print (MINSTMSG_CLITrailer);
257 printf ("\n");
258 MSG_SetInsertViaPSZ (1, PackageName);
259 MSG_Print (MINSTMSG_CLIActivePackageIs);
260 MSG_SetInsertViaPSZ (1, CurGroupPtr->Name);
261 MSG_Print (MINSTMSG_CLIActiveGroupIs);
262 ultoa (CurCardNo, TempValueStr, 10);
263 MSG_SetInsertViaPSZ (1, TempValueStr);
264 MSG_Print (MINSTMSG_CLIActiveCardNoIs);
265 MSG_SetInsertViaPSZ (1, CurGroupPtr->PromptTitlePtr[CurPromptNo]);
266 MSG_Print (MINSTMSG_CLIActivePromptIs);
267 printf ("\n");
268
269 // List all prompt-selections...
270 CurOptionNo = 0; CurOptionPtr = CurGroupPtr->PromptChoiceStrings[CurPromptNo];
271 while (CurOptionNo<CurGroupPtr->PromptChoiceCount[CurPromptNo]) {
272 CurChoice = MINSTCLI_GetSelectionChar(CurOptionNo);
273 printf ("%c - '%s'\n", CurChoice, CurOptionPtr);
274 CurOptionPtr = STRING_SkipASCIIZ(CurOptionPtr, NULL);
275 CurOptionNo++;
276 }
277
278 printf ("\n");
279 MSG_Print (MINSTMSG_CLIChooseOption);
280
281 CurChoice = MINSTCLI_GetSelectionFromUser(CurGroupPtr->PromptChoiceCount[CurPromptNo]);
282 if (CurChoice==-1) { // User pressed ESC
283 break;
284 } else { // Prompt-Selection
285 MINSTALL_SetCARDINFOChoiceForGroup (CurGroupPtr->ID, CurCardNo, CurPromptNo+1, CurChoice+1);
286 break;
287 }
288 }
289 }
290 }
291 }
292 CurCardNo++;
293 }
294 }
295 }
296 CurGroupNo++; CurGroupPtr++;
297 }
298 }
299
300 printf ("\n");
301 // Dont ask user for confirmation, if we create a response file only
302 if ((MINSTCLI_CIDCreate) && (!MINSTCLI_CIDCompatibility))
303 return TRUE;
304 // Otherwise ask just for security...
305 MSG_Print (MINSTMSG_CLISureToInstallPackage);
306 if (Inkey()==0x0D)
307 return TRUE;
308 return FALSE;
309 }
310
311VOID MINSTCID_CreateResponseFile (void) {
312 FILE *ResponseFile = 0;
313 PMINSTPUBGROUP CurGroupPtr = MINSTCLI_PubGroupPtr;
314 ULONG CurGroupNo = 0;
315 ULONG TotalSelectedGroups = 0;
316 PSZ SourcePathPtr = 0;
317 CHAR SourcePath[MINSTMAX_PATHLENGTH] = {0};
318 PSZ TargetPathPtr = 0;
319 CHAR TargetPath[MINSTMAX_PATHLENGTH] = {0};
320 PSZ CustomDataPtr = 0;
321 CHAR CustomData[MINSTMAX_CUSTOMDATALENGTH];
322 ULONG MaxLength = 0;
323
324 ResponseFile = fopen(MINSTCLI_ResponseFileName, "w+");
325 if (ResponseFile) {
326 fprintf (ResponseFile, "/* Response file generated by Multimedia Installer CLI/CID */\n\n");
327 fprintf (ResponseFile, "MMINSTALL = (\n");
328
329 // Get current Source and Target-Path from MINSTALL...
330 SourcePathPtr = MINSTALL_GetSourcePathPtr();
331 TargetPathPtr = MINSTALL_GetTargetPathPtr();
332
333 MaxLength = MINSTMAX_PATHLENGTH;
334 if (STRING_BuildEscaped(SourcePath, &MaxLength, SourcePathPtr))
335 fprintf (ResponseFile, " SOURCE = \"%s\"\n", SourcePath);
336 MaxLength = MINSTMAX_PATHLENGTH;
337 if (STRING_BuildEscaped(TargetPath, &MaxLength, TargetPathPtr))
338 fprintf (ResponseFile, " TARGET = \"%s\"\n", TargetPath);
339 fprintf (ResponseFile, " TARGETBOOT = \"\"\n\n");
340
341 while (CurGroupNo<MINSTCLI_PubGroupCount) {
342 if (CurGroupPtr->Selected)
343 TotalSelectedGroups++;
344 CurGroupNo++; CurGroupPtr++;
345 }
346 fprintf (ResponseFile, " GROUPS[%d] = (\n", TotalSelectedGroups);
347
348 CurGroupNo = 0; CurGroupPtr = MINSTCLI_PubGroupPtr;
349 while (CurGroupNo<MINSTCLI_PubGroupCount) {
350 if (CurGroupPtr->Selected) {
351 fprintf (ResponseFile, " ( GROUPID = %d\n", CurGroupPtr->ID);
352
353 MaxLength = MINSTMAX_PATHLENGTH;
354 CustomDataPtr = MINSTALL_GetPublicGroupCustomDataPtr(CurGroupPtr->ID);
355 STRING_BuildEscaped(CustomData, &MaxLength, CustomDataPtr);
356 fprintf (ResponseFile, " CUSTOMDATA = \"%s\"\n", CustomData);
357 fprintf (ResponseFile, " )\n");
358 }
359 CurGroupNo++; CurGroupPtr++;
360 }
361
362 fprintf (ResponseFile, " )\n");
363 fprintf (ResponseFile, " )\n");
364 fclose (ResponseFile);
365 ResponseFile = 0;
366
367 MSG_Print (MINSTMSG_CLIResponseFileCreated);
368 }
369 }
370
371ULONG MINSTCLI_GetNextRespParmID (PCHAR *CurPosPtr, PCHAR EndPos, PULONG CurLineNoPtr, PLONG ArrayCountPtr) {
372 PCHAR StartPos = *CurPosPtr;
373 PCHAR CurPos = StartPos;
374 CHAR CurChar = *CurPos;
375 ULONG ParamID;
376
377 // Isolate till space or '='...
378 StartPos = CurPos;
379 while (CurPos<EndPos) {
380 *CurPos = toupper(CurChar);
381 if ((CurChar==0x0D) || (CurChar==' ') || (CurChar=='[') || (CurChar=='=')) {
382 ParamID = CRC32_GetFromString(StartPos, CurPos-StartPos);
383 *CurPosPtr = CurPos;
384 if (!(CurChar = STRING_GetValidChar(CurPosPtr, EndPos, CurLineNoPtr))) {
385 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; return 0; }
386 if (CurChar=='[') {
387 // We got an array here...
388 *CurPosPtr += 1;
389 if (!(*CurPosPtr = STRING_GetNumericValue ((PULONG)ArrayCountPtr, *CurPosPtr, EndPos))) {
390 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; return 0; }
391 if (**CurPosPtr!=']') {
392 MSG_Print (MINSTMSG_CLIResponseFileIsInvalid); return 0; }
393 *CurPosPtr += 1;
394 if (STRING_GetValidChar(CurPosPtr, EndPos, CurLineNoPtr)!='=') {
395 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; return 0; }
396 } else if (CurChar!='=') {
397 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; return 0;
398 } else {
399 *ArrayCountPtr = -1;
400 }
401 *CurPosPtr += 1;
402 // Now seek to next valid char...
403 if (!STRING_GetValidChar(CurPosPtr, EndPos, CurLineNoPtr)) {
404 MINSTCLI_ErrorMsgID = MINSTMSG_UnexpectedEndOfFile; return 0; }
405 return ParamID;
406 }
407 CurPos++; CurChar = *CurPos;
408 }
409 // Experienced End-Of-Buffer...
410 *CurPosPtr = CurPos; MINSTCLI_ErrorMsgID = MINSTMSG_UnexpectedEndOfFile;
411 return 0;
412 }
413
414BOOL MINSTCLI_ReadResponseHeader (void) {
415 PCHAR StartPos;
416 PCHAR EndPos = RESPONSEFILE.BufferEndPtr;
417 PCHAR CurPos = MINSTCLI_ResponseFilePos;
418 ULONG CurLineNo = MINSTCLI_ResponseFileLine;
419 LONG ArrayCount = -1;
420 CHAR CurChar;
421 ULONG CRC32;
422 ULONG GotParms = 0;
423 BOOL HeaderDone = FALSE;
424 CHAR TargetBootPath[MINSTMAX_PATHLENGTH] = {0};
425 ULONG TargetBootPathLen = 0;
426
427 if (!STRING_GetValidChar (&CurPos, EndPos, &CurLineNo))
428 return FALSE; // No more valid chars, so done...
429
430 // Get first Parameter-ID...
431 CRC32 = MINSTCLI_GetNextRespParmID (&CurPos, EndPos, &CurLineNo, &ArrayCount);
432
433 if (CRC32==0xF6AFBBDF) { // Is 'MMINSTALL'?
434 // So, we found new response file format...
435 MINSTCLI_CIDCompatibility = FALSE;
436
437 if (*CurPos!='(') {
438 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid;
439 } else {
440 CurPos++;
441
442 while ((CurChar = STRING_GetValidChar(&CurPos, EndPos, &CurLineNo))!=0) {
443 if (CurChar==')') {
444 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; break; }
445 CRC32 = MINSTCLI_GetNextRespParmID (&CurPos, EndPos, &CurLineNo, &ArrayCount);
446 switch (CRC32) {
447 case 0xAF72B8F5: // SOURCE - defines source path
448 if (ArrayCount!=-1) {
449 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; break; }
450 if (!(GotParms & 0x01)) {
451 CurPos = STRING_GetString(MINSTCLI_SourcePath, MINSTMAX_PATHLENGTH, CurPos, EndPos);
452 if (!CurPos) {
453 MINSTCLI_ErrorMsgID = MINSTMSG_UnexpectedEndOfFile; }
454 GotParms |= 0x01;
455 } else {
456 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; }
457 break;
458 case 0xB697E87A: // TARGET - defines target path
459 if (ArrayCount!=-1) {
460 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; break; }
461 if (!(GotParms & 0x02)) {
462 CurPos = STRING_GetString(MINSTCLI_TargetPath, MINSTMAX_PATHLENGTH, CurPos, EndPos);
463 if (!CurPos) {
464 MINSTCLI_ErrorMsgID = MINSTMSG_UnexpectedEndOfFile; }
465 GotParms |= 0x02;
466 } else {
467 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; }
468 break;
469 case 0xCF0988F4: // TARGETBOOT - defines target boot-drive
470 if (ArrayCount!=-1) {
471 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; break; }
472 if (!(GotParms & 0x04)) {
473 CurPos = STRING_GetString(TargetBootPath, MINSTMAX_PATHLENGTH, CurPos, EndPos);
474 if (!CurPos) {
475 MINSTCLI_ErrorMsgID = MINSTMSG_UnexpectedEndOfFile; }
476 TargetBootPathLen = strlen(TargetBootPath);
477 if (TargetBootPathLen==2) {
478 // If 2 chars specified, 2nd one has to be ':' and 1st one
479 // is supposed to be the drive letter
480 if (TargetBootPath[1]!=':') {
481 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; break; }
482 // We only set TargetBootDrive once. If multiple packages
483 // are installed, they *will* use the same TargetBootDrive
484 // anyway.
485 if (!MINSTCLI_TargetBootDrive) {
486 MINSTCLI_TargetBootDrive = TargetBootPath[0]-0x40;
487 if ((MINSTCLI_TargetBootDrive<1) || (MINSTCLI_TargetBootDrive>26)) {
488 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; break; }
489 }
490 } else if (TargetBootPathLen) {
491 // If not 2 chars or no chars -> error!
492 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; break; }
493 GotParms |= 0x04;
494 } else {
495 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; }
496 break;
497 case 0x0095FEF6: // GROUPS...
498 if (ArrayCount==-1) {
499 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; break; }
500 GotParms |= 0x08;
501 if (*CurPos!='(') {
502 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; break; }
503 CurPos++;
504 // We got the info we needed...
505 MINSTCLI_ResponseGroups = ArrayCount; HeaderDone = TRUE;
506 break;
507 default:
508 MINSTCLI_ErrorMsgID = MINSTMSG_BadCommand;
509 }
510
511 if ((MINSTCLI_ErrorMsgID) || (HeaderDone)) break;
512 }
513
514 // Check, if we got SOURCE, TARGET, TARGETBOOT and GROUPS...
515 if (GotParms!=0x0F) {
516 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; }
517 }
518
519 } else {
520 // Oh, Oh, we possibly have to old ugly IBM format...
521 MINSTCLI_CIDCompatibility = TRUE;
522 while (CRC32) {
523 if (ArrayCount!=-1) { // Someone has defined array? NoWay
524 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; break; }
525 switch (CRC32) {
526 case 0xAEB9F0B1: // MMINSTSOURCE - defines source path
527 if (!(GotParms & 0x01)) {
528 CurPos = STRING_GetString(MINSTCLI_SourcePath, MINSTMAX_PATHLENGTH, CurPos, EndPos);
529 if (!CurPos) {
530 MINSTCLI_ErrorMsgID = MINSTMSG_UnexpectedEndOfFile; }
531 GotParms |= 0x01;
532 } else {
533 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; }
534 break;
535 case 0xB75CA03E: // MMINSTTARGET - defines target *drive*
536 if (!(GotParms & 0x02)) {
537 CurPos = STRING_GetString(MINSTCLI_TargetPath, MINSTMAX_PATHLENGTH, CurPos, EndPos);
538 if (!CurPos) {
539 MINSTCLI_ErrorMsgID = MINSTMSG_UnexpectedEndOfFile; }
540 // Add ':\MMOS2' to the Target-Path
541 strcpy (MINSTCLI_TargetPath+1, ":\\MMOS2");
542 GotParms |= 0x02;
543 } else {
544 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; }
545 break;
546 case 0x975037BD: // CHANGECONFIG - compatibility accept only...
547 CurPos = STRING_SkipString (CurPos, EndPos);
548 if (!CurPos) {
549 MINSTCLI_ErrorMsgID = MINSTMSG_UnexpectedEndOfFile; }
550 break;
551 case 0x015EB6B2: // MMINSTGROUPS - Lists groups & custom data
552 // Check, if Source and Target are defined, then exit
553 GotParms |= 0x04;
554 CurChar = STRING_GetValidChar(&CurPos, EndPos, &CurLineNo);
555 if (CurChar!='(') {
556 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; break; }
557 CurPos++; HeaderDone = TRUE; // We got the info we needed...
558 break;
559 default:
560 MINSTCLI_ErrorMsgID = MINSTMSG_BadCommand;
561 }
562 if ((MINSTCLI_ErrorMsgID) || (HeaderDone)) break;
563
564 // No more chars? -> so break!
565 if (!STRING_GetValidChar (&CurPos, EndPos, &CurLineNo)) {
566 MINSTCLI_ErrorMsgID = MINSTMSG_UnexpectedEndOfFile; break; }
567
568 // Get next Parameter-ID...
569 CRC32 = MINSTCLI_GetNextRespParmID (&CurPos, EndPos, &CurLineNo, &ArrayCount);
570 }
571
572 // Check, if we got SOURCE, TARGET and GROUPS...
573 if (GotParms!=0x07) {
574 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; }
575 }
576
577 if (MINSTCLI_ErrorMsgID) {
578 MSG_SetInsertFileLocation (1, RESPONSEFILE.Name, CurLineNo);
579 MSG_Print (MINSTCLI_ErrorMsgID);
580 return FALSE;
581 }
582
583 // Remember those variables for later...
584 MINSTCLI_ResponseFilePos = CurPos;
585 MINSTCLI_ResponseFileLine = CurLineNo;
586 return TRUE;
587 }
588
589BOOL MINSTCLI_ReadResponseData (void) {
590 PCHAR StartPos;
591 PCHAR EndPos = RESPONSEFILE.BufferEndPtr;
592 PCHAR CurPos = MINSTCLI_ResponseFilePos;
593 ULONG CurLineNo = MINSTCLI_ResponseFileLine;
594 LONG ArrayCount = -1;
595 CHAR CurChar;
596 ULONG CRC32;
597 ULONG GroupID = 0;
598 ULONG GroupNo = 0;
599 ULONG GotParms = 0;
600 CHAR CustomData[MINSTMAX_CUSTOMDATALENGTH];
601
602 if (!MINSTCLI_CIDCompatibility) {
603 // ============================================== We use new format...
604 for (GroupNo=0; GroupNo<MINSTCLI_ResponseGroups; GroupNo++) {
605 CurChar = STRING_GetValidChar(&CurPos, EndPos, &CurLineNo);
606 if (CurChar!='(') {
607 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; break; }
608 CurPos++;
609
610 GotParms = 0;
611 while (1) {
612 if (!(CurChar = STRING_GetValidChar(&CurPos, EndPos, &CurLineNo))) {
613 MINSTCLI_ErrorMsgID = MINSTMSG_UnexpectedEndOfFile; break; }
614 if (CurChar==')') {
615 CurPos++; break; } // End-Of-Parm-List
616 CRC32 = MINSTCLI_GetNextRespParmID(&CurPos, EndPos, &CurLineNo, &ArrayCount);
617 switch (CRC32) {
618 case 0x47405208: // GROUPID
619 if (ArrayCount!=-1) {
620 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; break; }
621 if (!(GotParms & 0x01)) {
622 if (!(CurPos = STRING_GetNumericValue(&GroupID, CurPos, EndPos))) {
623 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; break; }
624 GotParms |= 0x01;
625 }
626 break;
627 case 0x46BE0CE7: // CUSTOMDATA
628 if (ArrayCount!=-1) {
629 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; break; }
630 if (!(GotParms & 0x02)) {
631 if (!(CurPos = STRING_GetString(CustomData, MINSTMAX_CUSTOMDATALENGTH, CurPos, EndPos))) {
632 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; break; }
633 GotParms |= 0x02;
634 }
635 break;
636 default:
637 MINSTCLI_ErrorMsgID = MINSTMSG_BadCommand;
638 }
639 }
640 if (MINSTCLI_ErrorMsgID) break;
641
642 if (GotParms!=0x03) {
643 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; break; }
644
645 // Select that group...
646 MINSTALL_SelectGroup (GroupID);
647 // And set CustomData...
648 if (!MINSTALL_SetPublicGroupCustomData(GroupID, CustomData)) {
649 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; break; }
650 }
651 if (!MINSTCLI_ErrorMsgID) {
652 CurChar = STRING_GetValidChar(&CurPos, EndPos, &CurLineNo);
653 if (CurChar==')') {
654 CurPos++; CurChar = STRING_GetValidChar(&CurPos, EndPos, &CurLineNo);
655 if (CurChar==')') {
656 CurPos++;
657 } else {
658 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; }
659 } else {
660 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; }
661 }
662
663 } else {
664 // ============================================== We use old format...
665 while (1) {
666 if (!(CurChar = STRING_GetValidChar (&CurPos, EndPos, &CurLineNo))) {
667 MINSTCLI_ErrorMsgID = MINSTMSG_UnexpectedEndOfFile; break; }
668 if (CurChar==')') {
669 CurPos++; break; } // End-Of-Parm-List encountered
670
671 StartPos = CurPos;
672 if (!MINSTCLI_GetNextRespParmID(&CurPos, EndPos, &CurLineNo, &ArrayCount)) {
673 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; }
674
675 if ((CurPos-StartPos<6) || (strncmp(StartPos, "GROUP.", 6)!=0)) {
676 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; break; }
677 StartPos += 6;
678 if (!STRING_GetNumericValue(&GroupID, StartPos, CurPos)) {
679 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; break; }
680
681 CurPos = STRING_GetString(CustomData, MINSTMAX_CUSTOMDATALENGTH, CurPos, EndPos);
682 if (!CurPos) {
683 MINSTCLI_ErrorMsgID = MINSTMSG_UnexpectedEndOfFile; }
684
685 // Select that group...
686 MINSTALL_SelectGroup (GroupID);
687 // And set CustomData...
688 if (!MINSTALL_SetPublicGroupCustomData(GroupID, CustomData)) {
689 MINSTCLI_ErrorMsgID = MINSTMSG_CLIResponseFileIsInvalid; break; }
690 }
691 }
692
693 if (MINSTCLI_ErrorMsgID) {
694 MSG_SetInsertFileLocation (1, RESPONSEFILE.Name, CurLineNo);
695 MSG_Print (MINSTCLI_ErrorMsgID);
696 return FALSE;
697 }
698
699 // Remember those variables for later...
700 MINSTCLI_ResponseFilePos = CurPos;
701 MINSTCLI_ResponseFileLine = CurLineNo;
702 return TRUE;
703 }
704
705USHORT maincode (int argc, char *argv[]) {
706 HAB OurPMHandle = 0;
707 HMQ OurMSGQHandle = 0;
708 PSZ ErrorMsgPtr = 0;
709
710 PPIB pib;
711 PTIB tib;
712
713 STARTDATA StartData;
714 ULONG PIDOfSession = 0;
715 PID PIDOfProcess = 0;
716
717 ULONG CurArgument = 0;
718 ULONG ArgumentLen = 0;
719 PCHAR StartPos = 0;
720 PCHAR CurPos = 0;
721 CHAR CurChar;
722
723 BOOL BadParm = FALSE;
724 BOOL BadUsage = FALSE;
725 BOOL BadCombo = FALSE;
726 BOOL DisplaySyntax = FALSE;
727
728 USHORT ReturnCode;
729 PSZ ReturnCodeDescription;
730
731 // Make ourself an PM application...
732 DosGetInfoBlocks (&tib, &pib);
733 pib->pib_ultype = 3;
734
735 // Initialize with message-file...
736 if (!MSG_Init ("minstall.msg"))
737 return FALSE;
738
739 MSG_Print (MINSTMSG_CLITrailer);
740
741 CurArgument = 1;
742 while (CurArgument<argc) {
743 StartPos = argv[CurArgument];
744 ArgumentLen = strlen(StartPos);
745
746 if ((*StartPos=='/') && (ArgumentLen>1)) {
747 StartPos++; ArgumentLen--;
748 CurChar = toupper(*StartPos++); ArgumentLen--;
749
750 switch (CurChar) {
751 case 'C': // /C: record to response file
752 if ((MINSTCLI_CIDMode) || (MINSTCLI_CIDCreate))
753 BadCombo = TRUE;
754 if ((ArgumentLen>1) && (*StartPos==':')) {
755 MINSTCLI_CIDCreate = TRUE; MINSTCLI_CIDCompatibility = TRUE;
756 if (!STRING_CopyPSZ(MINSTCLI_ResponseFileName, MINSTMAX_PATHLENGTH, StartPos+1))
757 BadUsage = TRUE;
758 } else if ((ArgumentLen>2) && (*StartPos++=='2') && (*StartPos==':')) {
759 ArgumentLen--;
760 MINSTCLI_CIDCreate = TRUE;
761 if (!STRING_CopyPSZ(MINSTCLI_ResponseFileName, MINSTMAX_PATHLENGTH, StartPos+1))
762 BadUsage = TRUE;
763 } else BadUsage = TRUE;
764 break;
765 case 'F': // /F: specifies control.scr
766 if ((ArgumentLen>1) && (*StartPos==':')) {
767 StartPos++; ArgumentLen--;
768 strupr (StartPos);
769 if (ArgumentLen>=12) {
770 CurPos = StartPos+ArgumentLen-12;
771 if (strcmp(CurPos, "\\CONTROL.SCR")==0) {
772 ArgumentLen -= 12;
773 }
774 }
775 if (!STRING_Copy(MINSTCLI_SourcePath, MINSTMAX_PATHLENGTH, StartPos, StartPos+ArgumentLen))
776 BadUsage = TRUE;
777 } else BadUsage = TRUE;
778 break;
779 case 'L': // /L: specifies logfile
780 if ((ArgumentLen>1) && (*StartPos==':')) {
781 if (!STRING_CopyPSZ(MINSTCLI_LogFileName, MINSTMAX_PATHLENGTH, StartPos+1))
782 BadUsage = TRUE;
783 } else BadUsage = TRUE;
784 break;
785 case 'R': // /R: specifies response file (CID)
786 if ((MINSTCLI_CIDMode) || (MINSTCLI_CIDCreate))
787 BadCombo = TRUE;
788 if ((ArgumentLen>1) && (*StartPos==':')) {
789 MINSTCLI_CIDMode = TRUE;
790 if (!STRING_CopyPSZ(MINSTCLI_ResponseFileName, MINSTMAX_PATHLENGTH, StartPos+1))
791 BadUsage = TRUE;
792 } else BadUsage = TRUE;
793 break;
794 case 'M': // MMTEMP?!?!?!
795 // Accepted only for compatibility
796 break;
797 case '?':
798 DisplaySyntax = TRUE;
799 break;
800 case '*': // Makes MINSTALL use CLI interface
801 break;
802 default:
803 BadParm = TRUE;
804 }
805 } else BadParm = TRUE;
806
807 if (BadParm) {
808 MSG_SetInsertViaPSZ (1, argv[CurArgument]);
809 MSG_Print (MINSTMSG_CLIUnknownParameter);
810 return CIDRET_IncorrectProgramInvocation;
811 }
812 if (BadUsage) {
813 MSG_SetInsertViaString (1, argv[CurArgument], 2);
814 MSG_Print (MINSTMSG_CLIInvalidUsageOfParm);
815 return CIDRET_IncorrectProgramInvocation;
816 }
817 if (BadCombo) {
818 MSG_Print (MINSTMSG_CLICantUseInCombinationParm);
819 return CIDRET_IncorrectProgramInvocation;
820 }
821
822 CurArgument++;
823 }
824
825 // ======================================================= Display Syntax...
826 if (DisplaySyntax) {
827 MSG_Print (MINSTMSG_CLISyntaxExplanation); return 0; }
828
829 if (argc<2) {
830 // User did not specify any command-line options, so try to execute
831 // MINSTPM.EXE, if possible. If this works, exit directly. Otherwise
832 // continue with normal CLI processing.
833
834 memset(&StartData, 0, sizeof(StartData));
835 StartData.Length = sizeof(StartData);
836 StartData.PgmName = "minstpm.exe";
837 StartData.SessionType = SSF_TYPE_PM;
838 rc = DosStartSession (&StartData, &PIDOfSession, &PIDOfProcess);
839 if (rc==0) {
840 MSG_Print (MINSTMSG_CLIGaveControlToGUI); return 0; }
841 }
842
843 if (MINSTCLI_SourcePath[0]==0) {
844 // Set default SourcePath, if not already set...
845 if (!FILE_GetCurrentPath(MINSTCLI_SourcePath, MINSTMAX_PATHLENGTH))
846 return CIDRET_UnexpectedCondition;
847 }
848
849 // We need to initialize with PM and get a Message Queue for MINSTALL.DLL...
850 if (!(OurPMHandle = WinInitialize(0))) {
851 MSG_Print (MINSTMSG_CLICouldNotInitPM);
852 return CIDRET_UnexpectedCondition; }
853 if (!(OurMSGQHandle = WinCreateMsgQueue(OurPMHandle, 0))) {
854 MSG_Print (MINSTMSG_CLICouldNotInitMsgQueue);
855 return CIDRET_UnexpectedCondition; }
856
857 // Are we in CID-Mode?
858 if (MINSTCLI_CIDMode) { // ======================================== CID-Mode
859 MSG_Print (MINSTMSG_CLIExecutingInCIDMode);
860 // Open response file and process it...
861 strcpy (RESPONSEFILE.Name, MINSTCLI_ResponseFileName);
862 if (!FILE_LoadFileControl(&RESPONSEFILE, 131767)) {
863 MSG_SetInsertViaPSZ (1, MINSTCLI_ResponseFileName);
864 MSG_Print (MINSTMSG_CouldNotLoad);
865 return CIDRET_DataResourceNotFound; }
866 // Remove remarks, TAB-Stops and other crap from file...
867 FILE_PreProcessControlFile(&RESPONSEFILE);
868 MINSTCLI_ResponseFilePos = RESPONSEFILE.BufferPtr;
869
870 // Now read in header (or exit, if EOF)
871 while (MINSTCLI_ReadResponseHeader()) {
872 // We init per package, because options may change (TargetPath/etc.)
873 if (!MINSTALL_Init (MINSTCLI_TargetBootDrive, OurPMHandle, OurMSGQHandle, MINSTCLI_TargetPath, MINSTCLI_LogFileName))
874 break;
875 if (!MINSTALL_InitPackage(MINSTCLI_SourcePath))
876 break;
877 // Get pointer to Public-Group Array
878 MINSTCLI_PubGroupCount = MINSTALL_GetPublicGroupArrayPtr (&MINSTCLI_PubGroupPtr);
879 // Now read in response file data and configure groups automatically
880 if (!MINSTCLI_ReadResponseData())
881 break;
882 // Finally install this package...
883 if (!MINSTALL_InstallPackage())
884 break;
885 // We need to CleanUp at anytime...
886 MINSTALL_CleanUp();
887 // MINSTALL.DLL will only delete log-file on first Init(). Afterwards
888 // data will just get appended, so this here will work.
889 }
890 FILE_UnLoadFileControl(&RESPONSEFILE);
891
892 } else { // ====================================================== CLI-Mode
893 // Initialize MINSTALL...
894 if (MINSTALL_Init (0, OurPMHandle, OurMSGQHandle, "", MINSTCLI_LogFileName)) {
895 // Now initialize the package...
896 if (MINSTALL_InitPackage(MINSTCLI_SourcePath)) {
897 // Get pointer to Public-Group Array
898 MINSTCLI_PubGroupCount = MINSTALL_GetPublicGroupArrayPtr (&MINSTCLI_PubGroupPtr);
899
900 // Let user select...
901 if (MINSTCLI_UserGroupSelection()) {
902 if ((MINSTCLI_CIDCreate) && (!MINSTCLI_CIDCompatibility)) {
903 // Generate a CID file w/o installation (no compatibility)
904 MINSTCID_CreateResponseFile();
905 } else {
906 if (MINSTALL_InstallPackage()) {
907 // So, if CID file requested (using compatibility), we
908 // install the package and create it now...
909 if ((MINSTCLI_CIDCreate) && (MINSTCLI_CIDCompatibility)) {
910 MINSTCID_CreateResponseFile();
911 }
912 }
913 }
914 }
915 }
916 }
917 }
918 // If there was an error, print it out...
919 if ((ErrorMsgPtr = MINSTALL_GetErrorMsgPtr())!=0) {
920 printf (ErrorMsgPtr); }
921
922 if (MINSTCLI_ErrorMsgID) {
923 ReturnCode = CIDRET_IncorrectProgramInvocation;
924 ReturnCodeDescription = "CID: Incorrect program invocation";
925 } else {
926 // Get CID-Returncode from MINSTALL.DLL
927 ReturnCode = MINSTALL_GetErrorMsgCIDCode();
928 ReturnCodeDescription = MINSTALL_GetErrorMsgCIDCodeDescription();
929 }
930
931 // We need to CleanUp at anytime... (wouldnt be required on CID)
932 MINSTALL_CleanUp();
933
934 // Clean Up Message Queue and PM...
935 WinDestroyMsgQueue (OurMSGQHandle);
936 WinTerminate (OurPMHandle);
937 printf ("Return-Code %X (%s)\n", ReturnCode, ReturnCodeDescription);
938 return ReturnCode;
939 }
Note: See TracBrowser for help on using the repository browser.