test: almisc.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# almisc.c

Go to the documentation of this file.

    00001 #include "precomp.h"
    00002 #pragma hdrstop
    00003
    00004
    00005 //
    00006 // Internal function definitions
    00007 //
    00008
    00009 ARC_STATUS
    00010 AlpFreeComponents(
    00011     IN PCHAR *EnvVarComponents
    00012     );
    00013
    00014 BOOLEAN
    00015 AlpMatchComponent(
    00016     IN PCHAR Value1,
    00017     IN PCHAR Value2
    00018     );
    00019
    00020 //
    00021 // Function implementations
    00022 //
    00023
    00024
    00025 ARC_STATUS
    00026 AlGetEnvVarComponents (
    00027     IN  PCHAR  EnvValue,
    00028     OUT PCHAR  **EnvVarComponents,
    00029     OUT PULONG PNumComponents
    00030     )
    00031
    00032 /*++
    00033
    00034 Routine Description:
    00035
    00036     This routine takes an environment variable string and turns it into
    00037     the constituent value strings:
    00038
    00039     Example EnvValue = "Value1;Value2;Value3" is turned into:
    00040
    00041     "Value1", "Value2", "Value3"
    00042
    00043     The following are valid value strings:
    00044
    00045     1. "     "                                      :one null value is found
    00046     2. ";;;;    "                                   :five null values are found
    00047     3. " ;Value1    ;   Value2;Value3;;;;;;;   ;"   :12 value strings are found,
    00048                                                     :9 of which are null
    00049
    00050     If an invalid component (contains embedded white space) is found in the
    00051     string then this routine attempts to resynch to the next value, no error
    00052     is returned, and a the first part of the invalid value is returned for the
    00053     bad component.
    00054
    00055     1.  "    Value1;Bad   Value2; Value3"           : 2 value strings are found
    00056
    00057     The value strings returned suppress all whitespace before and after the
    00058     value.
    00059
    00060
    00061 Arguments:
    00062
    00063     EnvValue:  ptr to zero terminated environment value string
    00064
    00065     EnvVarComponents: ptr to a PCHAR * variable to receive the buffer of
    00066                       ptrs to the constituent value strings.
    00067
    00068     PNumComponents: ptr to a ULONG to receive the number of value strings found
    00069
    00070 Return Value:
    00071
    00072     The function returns the following error codes:
    00073          EACCES if EnvValue is NULL
    00074          ENOMEM if the memory allocation fails
    00075
    00076
    00077     The function returns the following success codes:
    00078          ESUCCESS.
    00079
    00080     When the function returns ESUCCESS:
    00081          - *PNumComponent field gets the number of value strings found
    00082          - if the number is non zero the *EnvVarComponents field gets the
    00083            ptr to the buffer containing ptrs to value strings
    00084
    00085 --*/
    00086
    00087
    00088 {
    00089     PCHAR pchStart, pchEnd, pchNext;
    00090     PCHAR pchComponents[MAX_COMPONENTS + 1];
    00091     ULONG NumComponents, i;
    00092     PCHAR pch;
    00093     ULONG size;
    00094
    00095     //
    00096     // Validate the EnvValue
    00097     //
    00098     if (EnvValue == NULL) {
    00099         return (EACCES);
    00100     }
    00101
    00102     //
    00103     // Initialise the ptr array with nulls
    00104     //
    00105     for (i = 0; i < (MAX_COMPONENTS+1); i++) {
    00106         pchComponents[i] = NULL;
    00107     }
    00108
    00109     //
    00110     // Initialise ptrs to search components
    00111     //
    00112     pchStart      = EnvValue;
    00113     NumComponents = 0;
    00114
    00115
    00116     //
    00117     // search till either pchStart reaches the end or till max components
    00118     // is reached, the below has been programmed from a dfsa.
    00119     //
    00120     while (*pchStart && NumComponents < MAX_COMPONENTS) {
    00121
    00122         //
    00123         // STATE 1: find the beginning of next variable value
    00124         //
    00125         while (*pchStart!=0 && isspace(*pchStart)) {
    00126             pchStart++;
    00127         }
    00128
    00129
    00130         if (*pchStart == 0) {
    00131             break;
    00132         }
    00133
    00134         //
    00135         // STATE 2: In the midst of a value
    00136         //
    00137         pchEnd = pchStart;
    00138         while (*pchEnd!=0 && !isspace(*pchEnd) && *pchEnd!=';') {
    00139             pchEnd++;
    00140         }
    00141
    00142         //
    00143         // STATE 3: spit out the value found
    00144         //
    00145
    00146         size = pchEnd - pchStart;
    00147         if ((pch = AlAllocateHeap(size+1)) == NULL) {
    00148             AlpFreeComponents(pchComponents);
    00149             return (ENOMEM);
    00150         }
    00151         strncpy (pch, pchStart, size);
    00152         pch[size]=0;
    00153         pchComponents[NumComponents++]=pch;
    00154
    00155         //
    00156         // STATE 4: variable value end has been reached, find the beginning
    00157         // of the next value
    00158         //
    00159         if ((pchNext = strchr(pchEnd, ';')) == NULL) {
    00160             break; // out of the big while loop because we are done
    00161         }
    00162
    00163         //
    00164         // Advance beyond the semicolon.
    00165         //
    00166
    00167         pchNext++;
    00168
    00169         //
    00170         // reinitialise to begin STATE 1
    00171         //
    00172         pchStart = pchNext;
    00173
    00174     } // end while.
    00175
    00176     //
    00177     // Get memory to hold an environment pointer and return that
    00178     //
    00179
    00180     if ( NumComponents!=0 ) {
    00181         PCHAR *pch;
    00182
    00183         if ((pch = (PCHAR *)AlAllocateHeap((NumComponents+1)*sizeof(PCHAR))) == NULL) {
    00184             AlpFreeComponents(pchComponents);
    00185             return (ENOMEM);
    00186         }
    00187
    00188         //
    00189         // the last one is NULL because we initialised the array with NULLs
    00190         //
    00191
    00192         for ( i = 0; i <= NumComponents; i++) {
    00193             pch[i] = pchComponents[i];
    00194         }
    00195
    00196
    00197         *EnvVarComponents = pch;
    00198     }
    00199
    00200     //
    00201     // Update the number of elements field and return success
    00202     //
    00203     *PNumComponents = NumComponents;
    00204     return (ESUCCESS);
    00205 }
    00206
    00207
    00208 ARC_STATUS
    00209 AlFreeEnvVarComponents (
    00210     IN PCHAR *EnvVarComponents
    00211     )
    00212 /*++
    00213
    00214 Routine Description:
    00215
    00216     This routine frees up all the components in the ptr array and frees
    00217     up the storage for the ptr array itself too
    00218
    00219 Arguments:
    00220
    00221     EnvVarComponents: the ptr to the PCHAR * Buffer
    00222
    00223 Return Value:
    00224
    00225     ESUCCESS if freeing successful
    00226     EACCES   if memory ptr invalid
    00227
    00228
    00229
    00230 --*/
    00231
    00232
    00233 {
    00234     ARC_STATUS Status;
    00235
    00236     //
    00237     // if the pointer is NULL just return success
    00238     //
    00239     if (EnvVarComponents == NULL) {
    00240         return (ESUCCESS);
    00241     }
    00242
    00243     //
    00244     // free all the components first, if error in freeing return
    00245     //
    00246     Status = AlpFreeComponents(EnvVarComponents);
    00247     if (Status != ESUCCESS) {
    00248         return Status;
    00249     }
    00250
    00251     //
    00252     // free the component holder too
    00253     //
    00254     if( AlDeallocateHeap(EnvVarComponents) != NULL) {
    00255         return (EACCES);
    00256     }
    00257     else {
    00258         return (ESUCCESS);
    00259     }
    00260
    00261 }
    00262
    00263
    00264 ARC_STATUS
    00265 AlpFreeComponents(
    00266     IN PCHAR *EnvVarComponents
    00267     )
    00268
    00269 /*++
    00270
    00271 Routine Description:
    00272
    00273    This routine frees up only the components in the ptr array, but doesn't
    00274    free the ptr array storage itself.
    00275
    00276 Arguments:
    00277
    00278     EnvVarComponents: the ptr to the PCHAR * Buffer
    00279
    00280 Return Value:
    00281
    00282     ESUCCESS if freeing successful
    00283     EACCES   if memory ptr invalid
    00284
    00285 --*/
    00286
    00287 {
    00288
    00289     //
    00290     // get all the components and free them
    00291     //
    00292     while (*EnvVarComponents != NULL) {
    00293         if(AlDeallocateHeap(*EnvVarComponents++) != NULL) {
    00294             return(EACCES);
    00295         }
    00296     }
    00297
    00298     return(ESUCCESS);
    00299 }
    00300
    00301
    00302 BOOLEAN
    00303 AlpMatchComponent(
    00304     IN PCHAR Value1,
    00305     IN PCHAR Value2
    00306     )
    00307
    00308 /*++
    00309
    00310 Routine Description:
    00311
    00312     This routine compares two components to see if they are equal.  This is
    00313     essentially comparing strings except that leading zeros are stripped from
    00314     key values.
    00315
    00316 Arguments:
    00317
    00318     Value1 - Supplies a pointer to the first value to match.
    00319
    00320     Value2 - Supplies a pointer to the second value to match.
    00321
    00322
    00323 Return Value:
    00324
    00325     If the components match, TRUE is returned, otherwise FALSE is returned.
    00326
    00327 --*/
    00328
    00329 {
    00330     while ((*Value1 != 0) && (*Value2 != 0)) {
    00331         if (tolower(*Value1) != tolower(*Value2)) {
    00332             return FALSE;
    00333         }
    00334
    00335         if (*Value1 == '(') {
    00336             do {
    00337                 *Value1++;
    00338             } while (*Value1 == '0');
    00339         } else {
    00340             *Value1++;
    00341         }
    00342
    00343         if (*Value2 == '(') {
    00344             do {
    00345                 *Value2++;
    00346             } while (*Value2 == '0');
    00347         } else {
    00348             *Value2++;
    00349         }
    00350     }
    00351
    00352     if ((*Value1 == 0) && (*Value2 == 0)) {
    00353         return TRUE;
    00354     }
    00355
    00356     return FALSE;
    00357 }
    00358
    00359
    00360 BOOLEAN
    00361 AlFindNextMatchComponent(
    00362     IN PCHAR EnvValue,
    00363     IN PCHAR MatchValue,
    00364     IN ULONG StartComponent,
    00365     OUT PULONG MatchComponent OPTIONAL
    00366     )
    00367
    00368 /*++
    00369
    00370 Routine Description:
    00371
    00372     This routine compares each component of EnvValue, starting with
    00373     StartComponent, until a match is found or there are no more components.
    00374
    00375 Arguments:
    00376
    00377     EnvValue - Supplies a pointer to the environment variable value.
    00378
    00379     MatchValue - Supplies a pointer to the value to match.
    00380
    00381     StartComponent - Supplies the component number to start the match.
    00382
    00383     MatchComponent - Supplies an optional pointer to a variable to receive
    00384                      the number of the component that matched.
    00385
    00386 Return Value:
    00387
    00388     If a match is found, TRUE is returned, otherwise FALSE is returned.
    00389
    00390 --*/
    00391
    00392 {
    00393     ARC_STATUS Status;
    00394     PCHAR *EnvVarComponents;
    00395     ULONG NumComponents;
    00396     ULONG Index;
    00397     BOOLEAN Match;
    00398
    00399
    00400     Status = AlGetEnvVarComponents(EnvValue, &EnvVarComponents, &NumComponents);
    00401
    00402     if (Status != ESUCCESS) {
    00403         return FALSE;
    00404     }
    00405
    00406     Match = FALSE;
    00407     for (Index = StartComponent ; Index < NumComponents ; Index++ ) {
    00408         if (AlpMatchComponent(EnvVarComponents[Index], MatchValue)) {
    00409             Match = TRUE;
    00410             break;
    00411         }
    00412     }
    00413
    00414     if (ARGUMENT_PRESENT(MatchComponent)) {
    00415         *MatchComponent = Index;
    00416     }
    00417
    00418     AlFreeEnvVarComponents(EnvVarComponents);
    00419     return Match;
    00420 }
    00421
    00422
    00423 ARC_STATUS
    00424 AlAddSystemPartition(
    00425     IN PCHAR NewSystemPartition
    00426     )
    00427
    00428 /*++
    00429
    00430 Routine Description:
    00431
    00432     This routine adds a system partition to the SystemPartition environment
    00433     variable, and updates the Osloader, OsloadPartition, OsloadFilename,
    00434     and OsloadOptions variables.
    00435
    00436 Arguments:
    00437
    00438     SystemPartition - Supplies a pointer to the pathname of the system
    00439                       partition to add.
    00440
    00441 Return Value:
    00442
    00443     If the system partition was successfully added, ESUCCESS is returned,
    00444     otherwise an error code is returned.
    00445
    00446     BUGBUG - This program is simplistic and doesn't attempt to make sure all
    00447     the variables are consistent.  It also doesn't fail gracefully.
    00448
    00449 --*/
    00450
    00451 {
    00452     ARC_STATUS Status;
    00453     PCHAR SystemPartition;
    00454     CHAR TempValue[MAXIMUM_ENVIRONMENT_VALUE];
    00455     //PCHAR Osloader;
    00456     //PCHAR OsloadPartition;
    00457     //PCHAR OsloadFilename;
    00458     //PCHAR OsloadOptions;
    00459
    00460     //
    00461     // Get the system partition environment variable.
    00462     //
    00463
    00464     SystemPartition = ArcGetEnvironmentVariable("SystemPartition");
    00465
    00466     //
    00467     // If the variable doesn't exist, add it and exit.
    00468     //
    00469
    00470     if (SystemPartition == NULL) {
    00471         if(strlen(NewSystemPartition) < MAXIMUM_ENVIRONMENT_VALUE) {
    00472             Status = ArcSetEnvironmentVariable("SystemPartition",
    00473                                                NewSystemPartition);
    00474         } else {
    00475             Status = E2BIG;
    00476         }
    00477         return Status;
    00478     }
    00479
    00480     //
    00481     // If the variable exists, add the new partition to the end.
    00482     //
    00483     if(strlen(SystemPartition)+strlen(NewSystemPartition)+2 > MAXIMUM_ENVIRONMENT_VALUE) {
    00484         return(E2BIG);
    00485     }
    00486
    00487     strcpy(TempValue, SystemPartition);
    00488     strcat(TempValue, ";");
    00489     strcat(TempValue, NewSystemPartition);
    00490     Status = ArcSetEnvironmentVariable("SystemPartition",
    00491                                        TempValue);
    00492
    00493     if (Status != ESUCCESS) {
    00494         return Status;
    00495     }
    00496
    00497 #if 0
    00498     //
    00499     // Add semicolons to the end of each of the associated variables.
    00500     // If they don't exist add them.
    00501     //
    00502
    00503     //
    00504     // Get the Osloader environment variable and add a semicolon to the end.
    00505     //
    00506
    00507     Osloader = ArcGetEnvironmentVariable("Osloader");
    00508     if (Osloader == NULL) {
    00509         *TempValue = 0;
    00510     } else {
    00511         strcpy(TempValue, Osloader);
    00512     }
    00513     strcat(TempValue, ";");
    00514     Status = ArcSetEnvironmentVariable("Osloader",TempValue);
    00515
    00516     if (Status != ESUCCESS) {
    00517         return Status;
    00518     }
    00519
    00520     //
    00521     // Get the OsloadPartition environment variable and add a semicolon to the end.
    00522     //
    00523
    00524     OsloadPartition = ArcGetEnvironmentVariable("OsloadPartition");
    00525     if (OsloadPartition == NULL) {
    00526         *TempValue = 0;
    00527     } else {
    00528         strcpy(TempValue, OsloadPartition);
    00529     }
    00530     strcat(TempValue, ";");
    00531     Status = ArcSetEnvironmentVariable("OsloadPartition",TempValue);
    00532
    00533     if (Status != ESUCCESS) {
    00534         return Status;
    00535     }
    00536
    00537     //
    00538     // Get the OsloadFilename environment variable and add a semicolon to the end.
    00539     //
    00540
    00541     OsloadFilename = ArcGetEnvironmentVariable("OsloadFilename");
    00542     if (OsloadFilename == NULL) {
    00543         *TempValue = 0;
    00544     } else {
    00545         strcpy(TempValue, OsloadFilename);
    00546     }
    00547     strcat(TempValue, ";");
    00548     Status = ArcSetEnvironmentVariable("OsloadFilename",TempValue);
    00549
    00550     if (Status != ESUCCESS) {
    00551         return Status;
    00552     }
    00553
    00554     //
    00555     // Get the OsloadOptions environment variable and add a semicolon to the end.
    00556     //
    00557
    00558     OsloadOptions = ArcGetEnvironmentVariable("OsloadOptions");
    00559     if (OsloadOptions == NULL) {
    00560         *TempValue = 0;
    00561     } else {
    00562         strcpy(TempValue, OsloadOptions);
    00563     }
    00564     strcat(TempValue, ";");
    00565     Status = ArcSetEnvironmentVariable("OsloadOptions",TempValue);
    00566 #endif
    00567     return Status;
    00568 }
    00569
    00570
    00571 typedef struct _tagMENUITEM {
    00572     PCHAR Text;
    00573     ULONG AssociatedData;
    00574 } MENUITEM,*PMENUITEM;
    00575
    00576 typedef struct _tagMENUCOOKIE {
    00577     ULONG     ItemCount;
    00578     PMENUITEM Items;
    00579 } MENUCOOKIE,*PMENUCOOKIE;
    00580
    00581
    00582 // indent for menus, status, etc.
    00583
    00584 char MARGIN[] = "          ";
    00585 char MSGMARGIN[] = " ";
    00586
    00587 // special constants used when fetching keystrokes
    00588
    00589 #define KEY_UP 1
    00590 #define KEY_DOWN 2
    00591
    00592
    00593 VOID
    00594 MarkLine(
    00595     ULONG   Line,
    00596     BOOLEAN Selected,
    00597     PCHAR String
    00598     );
    00599
    00600 BOOLEAN
    00601 CommonMenuDisplay(
    00602     PMENUCOOKIE Menu,
    00603     BOOLEAN     StaticMenu,
    00604     PCHAR       Items[],
    00605     ULONG       ItemCount,
    00606     BOOLEAN     PrintOnly,
    00607     ULONG       AssociatedDataOfDefaultChoice,
    00608     ULONG      *AssociatedDataOfChoice,
    00609     PCHAR       MenuName,
    00610     ULONG       Row
    00611     );
    00612
    00613 char
    00614 GetChar(
    00615     VOID
    00616     );
    00617
    00618
    00619 BOOLEAN
    00620 AlInitializeMenuPackage(
    00621     VOID
    00622     )
    00623 {
    00624     return(TRUE);
    00625 }
    00626
    00627
    00628 ULONG
    00629 AlGetMenuNumberItems(
    00630     PVOID MenuID
    00631     )
    00632 {
    00633     return(((PMENUCOOKIE)MenuID)->ItemCount);
    00634 }
    00635
    00636
    00637 ULONG
    00638 AlGetMenuAssociatedData(
    00639     PVOID MenuID,
    00640     ULONG n
    00641     )
    00642 {
    00643     return(((PMENUCOOKIE)MenuID)->Items[n].AssociatedData);
    00644 }
    00645
    00646 BOOLEAN
    00647 AlNewMenu(
    00648     PVOID *MenuID
    00649     )
    00650 {
    00651     PMENUCOOKIE p;
    00652
    00653     if(!(p = AlAllocateHeap(sizeof(MENUCOOKIE)))) {
    00654         return(FALSE);
    00655     }
    00656     p->ItemCount = 0;
    00657     p->Items = NULL;
    00658     *MenuID = p;
    00659     return(TRUE);
    00660 }
    00661
    00662
    00663 VOID
    00664 AlFreeMenu(
    00665     PVOID MenuID
    00666     )
    00667 {
    00668     PMENUCOOKIE p = MenuID;
    00669     ULONG       i;
    00670
    00671     for(i=0; i<p->ItemCount; i++) {
    00672         if(p->Items[i].Text != NULL) {
    00673             AlDeallocateHeap(p->Items[i].Text);
    00674         }
    00675     }
    00676     if(p->Items) {
    00677         AlDeallocateHeap(p->Items);
    00678     }
    00679     AlDeallocateHeap(p);
    00680 }
    00681
    00682
    00683 BOOLEAN
    00684 AlAddMenuItem(
    00685     PVOID MenuID,
    00686     PCHAR Text,
    00687     ULONG AssociatedData,
    00688     ULONG Attributes                // unused
    00689     )
    00690 {
    00691     PMENUCOOKIE Menu = MenuID;
    00692     PMENUITEM   p;
    00693
    00694     DBG_UNREFERENCED_PARAMETER(Attributes);
    00695
    00696     if(!Menu->ItemCount) {
    00697         if((Menu->Items = AlAllocateHeap(sizeof(MENUITEM))) == NULL) {
    00698             return(FALSE);
    00699         }
    00700         Menu->ItemCount = 1;
    00701         p = Menu->Items;
    00702     } else {
    00703         if((p = AlReallocateHeap(Menu->Items,sizeof(MENUITEM)*(Menu->ItemCount+1))) == NULL) {
    00704             return(FALSE);
    00705         }
    00706         Menu->Items = p;
    00707         p = &Menu->Items[Menu->ItemCount++];
    00708     }
    00709
    00710     if((p->Text = AlAllocateHeap(strlen(Text)+1)) == NULL) {
    00711         return(FALSE);
    00712     }
    00713     strcpy(p->Text,Text);
    00714     p->AssociatedData = AssociatedData;
    00715     return(TRUE);
    00716 }
    00717
    00718
    00719 BOOLEAN
    00720 AlAddMenuItems(
    00721     PVOID MenuID,
    00722     PCHAR Text[],
    00723     ULONG ItemCount
    00724     )
    00725 {
    00726     ULONG base,i;
    00727
    00728     base = AlGetMenuNumberItems(MenuID);
    00729
    00730     for(i=0; i<ItemCount; i++) {
    00731     if(!AlAddMenuItem(MenuID,Text[i],i+base,0)) {
    00732             return(FALSE);
    00733         }
    00734     }
    00735     return(TRUE);
    00736 }
    00737
    00738
    00739 BOOLEAN
    00740 AlDisplayMenu(
    00741     PVOID   MenuID,
    00742     BOOLEAN PrintOnly,
    00743     ULONG   AssociatedDataOfDefaultChoice,
    00744     ULONG  *AssociatedDataOfChoice,
    00745     ULONG   Row,
    00746     PCHAR   MenuName
    00747     )
    00748 {
    00749     return(CommonMenuDisplay((PMENUCOOKIE)MenuID,
    00750                              FALSE,
    00751                              NULL,
    00752                              ((PMENUCOOKIE)MenuID)->ItemCount,
    00753                              PrintOnly,
    00754                              AssociatedDataOfDefaultChoice,
    00755                              AssociatedDataOfChoice,
    00756                              MenuName,
    00757                              Row
    00758                             )
    00759           );
    00760 }
    00761
    00762
    00763 BOOLEAN
    00764 AlDisplayStaticMenu(
    00765     PCHAR  Items[],
    00766     ULONG  ItemCount,
    00767     ULONG  DefaultChoice,
    00768     ULONG  Row,
    00769     ULONG *IndexOfChoice
    00770     )
    00771 {
    00772     return(CommonMenuDisplay(NULL,
    00773                              TRUE,
    00774                              Items,
    00775                              ItemCount,
    00776                              FALSE,
    00777                              DefaultChoice,
    00778                              IndexOfChoice,
    00779                              NULL,
    00780                              Row
    00781                             )
    00782           );
    00783 }
    00784
    00785
    00786
    00787 BOOLEAN
    00788 CommonMenuDisplay(
    00789     PMENUCOOKIE Menu,
    00790     BOOLEAN     StaticMenu,
    00791     PCHAR       Items[],
    00792     ULONG       ItemCount,
    00793     BOOLEAN     PrintOnly,
    00794     ULONG       AssociatedDataOfDefaultChoice,
    00795     ULONG      *AssociatedDataOfChoice,
    00796     PCHAR       MenuName,
    00797     ULONG       Row
    00798     )
    00799 {
    00800 //    ULONG x;
    00801     ULONG i,MenuBaseLine,Selection;
    00802     char  c;
    00803     PCHAR String;
    00804
    00805     AlSetPosition(Row,0);
    00806     AlPrint("%cJ",ASCI_CSI);            // clear to end of screen.
    00807     MenuBaseLine = Row;
    00808
    00809     AlSetScreenColor(7,4);              // white on blue
    00810
    00811 //    if(MenuName) {
    00812 //        AlPrint("%s%s\r\n%s",MARGIN,MenuName,MARGIN);
    00813 //        x = strlen(MenuName);
    00814 //        for(i=0; i<x; i++) {
    00815 //            AlPrint("-");
    00816 //        }
    00817 //        AlPrint("\r\n\r\n");
    00818 //        MenuBaseLine += 3;
    00819 //    }
    00820
    00821     for(i=0; i<ItemCount; i++) {
    00822         AlSetScreenAttributes(1,0,0);   // hi intensity
    00823         AlPrint("%s%s\r\n",MARGIN,StaticMenu ? Items[i] : Menu->Items[i].Text);
    00824     }
    00825
    00826     if(PrintOnly) {
    00827
    00828         char dummy;
    00829         AlPrint("\r\nPress any key to continue.");
    00830         AlGetString(&dummy,0);
    00831
    00832     } else {
    00833
    00834 //        AlPrint("\r\n%sMake Selection using arrow keys and return,\r\n%sor escape to cancel",MARGIN,MARGIN);
    00835
    00836         Selection = 0;
    00837         if(StaticMenu) {
    00838             Selection = AssociatedDataOfDefaultChoice;
    00839         } else {
    00840             for(i=0; i<ItemCount; i++) {
    00841                 if(Menu->Items[i].AssociatedData == AssociatedDataOfDefaultChoice) {
    00842                     Selection = i;
    00843                     break;
    00844                 }
    00845             }
    00846         }
    00847
    00848         String = StaticMenu ? Items[Selection] : Menu->Items[Selection].Text;
    00849         MarkLine(MenuBaseLine+Selection,TRUE, String);
    00850
    00851         while(((c = GetChar()) != ASCI_ESC) && (c != ASCI_LF) && (c != ASCI_CR)) {
    00852
    00853             String = StaticMenu ? Items[Selection] : Menu->Items[Selection].Text;
    00854             MarkLine(MenuBaseLine+Selection,FALSE,String);
    00855
    00856             if(c == KEY_UP) {
    00857                 if(!Selection--) {
    00858                     Selection = ItemCount - 1;
    00859                 }
    00860             } else if(c == KEY_DOWN) {
    00861                 if(++Selection == ItemCount) {
    00862                     Selection = 0;
    00863                 }
    00864             }
    00865
    00866             String = StaticMenu ? Items[Selection] : Menu->Items[Selection].Text;
    00867             MarkLine(MenuBaseLine+Selection,TRUE,String);
    00868         }
    00869
    00870         // set cursor to a free place on the screen.
    00871         AlSetPosition(MenuBaseLine + ItemCount + 4,0);
    00872
    00873         if(c == ASCI_ESC) {
    00874             return(FALSE);
    00875         }
    00876
    00877         *AssociatedDataOfChoice = StaticMenu ? Selection : Menu->Items[Selection].AssociatedData;
    00878     }
    00879     return(TRUE);
    00880 }
    00881
    00882
    00883
    00884 VOID
    00885 MarkLine(
    00886     ULONG Line,
    00887     BOOLEAN Selected,
    00888     PCHAR String
    00889     )
    00890 {
    00891     AlSetPosition(Line,sizeof(MARGIN));
    00892     if (Selected) {
    00893         AlSetScreenAttributes(1,0,1);   // hi intensity, Reverse Video
    00894     }
    00895     AlPrint("%s\r\n", String);
    00896     AlSetScreenAttributes(1,0,0);       // hi intensity
    00897 }
    00898
    00899
    00900
    00901 char
    00902 GetChar(
    00903     VOID
    00904     )
    00905 {
    00906     UCHAR c;
    00907     ULONG count;
    00908
    00909     ArcRead(ARC_CONSOLE_INPUT,&c,1,&count);
    00910     switch(c) {
    00911 //  case ASCI_ESC:
    00912 //      ArcRead(ARC_CONSOLE_INPUT,&c,1,&count);
    00913 //      if(c != '[') {
    00914 //          break;
    00915 //      }
    00916     case ASCI_CSI:
    00917         ArcRead(ARC_CONSOLE_INPUT,&c,1,&count);
    00918         switch(c) {
    00919         case 'A':
    00920         case 'D':
    00921             return(KEY_UP);
    00922         case 'B':
    00923         case 'C':
    00924             return(KEY_DOWN);
    00925         }
    00926     default:
    00927         return(c);
    00928     }
    00929 }
    00930
    00931
    00932
    00933 VOID
    00934 AlWaitKey(
    00935     PCHAR Prompt
    00936     )
    00937 {
    00938     char buff[1];
    00939
    00940     AlPrint(MSGMARGIN);
    00941     AlPrint(Prompt ? Prompt : "Press any key to continue...");
    00942     AlGetString(buff,0);
    00943 }
    00944
    00945
    00946 VOID
    00947 vAlStatusMsg(
    00948     IN ULONG   Row,
    00949     IN BOOLEAN Error,
    00950     IN PCHAR   FormatString,
    00951     IN va_list ArgumentList
    00952     )
    00953 {
    00954     char  text[256];
    00955     ULONG Length,Count;
    00956
    00957     AlSetPosition(Row,0);
    00958     AlPrint(MSGMARGIN);
    00959     Length = vsprintf(text,FormatString,ArgumentList);
    00960     if(Error) {
    00961         AlSetScreenColor(1,4);         // red on blue
    00962     } else {
    00963         AlSetScreenColor(3,4);         // yellow on blue
    00964     }
    00965     AlSetScreenAttributes(1,0,0);      // hi intensity
    00966     ArcWrite(ARC_CONSOLE_OUTPUT,text,Length,&Count);
    00967     AlPrint("\r\n");
    00968     AlSetScreenColor(7,4);             // white on blue
    00969     AlSetScreenAttributes(1,0,0);      // hi intensity
    00970 }
    00971
    00972
    00973 VOID
    00974 AlStatusMsg(
    00975     IN ULONG   TopRow,
    00976     IN ULONG   BottomRow,
    00977     IN BOOLEAN Error,
    00978     IN PCHAR   FormatString,
    00979     ...
    00980     )
    00981 {
    00982     va_list ArgList;
    00983
    00984     va_start(ArgList,FormatString);
    00985     vAlStatusMsg(TopRow,Error,FormatString,ArgList);
    00986
    00987     AlWaitKey(NULL);
    00988     AlClearStatusArea(TopRow,BottomRow);
    00989 }
    00990
    00991
    00992 VOID
    00993 AlStatusMsgNoWait(
    00994     IN ULONG   TopRow,
    00995     IN ULONG   BottomRow,
    00996     IN BOOLEAN Error,
    00997     IN PCHAR   FormatString,
    00998     ...
    00999     )
    01000 {
    01001     va_list ArgList;
    01002
    01003     AlClearStatusArea(TopRow,BottomRow);
    01004     va_start(ArgList,FormatString);
    01005     vAlStatusMsg(TopRow,Error,FormatString,ArgList);
    01006 }
    01007
    01008
    01009 VOID
    01010 AlClearStatusArea(
    01011     IN ULONG TopRow,
    01012     IN ULONG BottomRow
    01013     )
    01014 {
    01015     ULONG i;
    01016
    01017     for(i=BottomRow; i>=TopRow; --i) {
    01018         AlSetPosition(i,0);
    01019         AlClearLine();
    01020     }
    01021 }
    01022
    01023
    01024 ARC_STATUS
    01025 AlGetMenuSelection(
    01026
    01027     IN  PCHAR   szTitle,
    01028     IN  PCHAR   *rgszSelections,
    01029     IN  ULONG   crgsz,
    01030     IN  ULONG   crow,
    01031     IN  ULONG   irgszDefault,
    01032     OUT PULONG  pirgsz,
    01033     OUT PCHAR   *pszSelection
    01034     )
    01035 /*++
    01036
    01037 Routine Description:
    01038
    01039     This routine takes an array of strings, turns them into a menu
    01040     and gets a selection. If ESC hit then ESUCCESS is returned with
    01041     the *pszSelection NULL.
    01042
    01043     crgsz is assume to be 1 or greater.
    01044
    01045
    01046 Arguments:
    01047
    01048     szTitle - Pointer to menu title to pass to AlDisplayMenu
    01049     prgszSelection - pointer to an array of strings for menu
    01050     crgsz - count of strings
    01051     irgszDefault - index in rgszSelection to use as default selection
    01052
    01053 Return Value:
    01054
    01055     irgsz - index to selection
    01056     pszSelection - pointer int rgszSelection for selection. Note that
    01057                    this is not a dup and should not be freed seperately
    01058                    then rgszSelections.
    01059
    01060     Note: if ARC_STATUS == ESUCCESS and pszSelection == NULL then the
    01061           menu was successfully displayed but the user hit ESC to select
    01062           nothing from the menu.
    01063
    01064 --*/
    01065
    01066
    01067 {
    01068
    01069     PVOID  hdMenuId;
    01070
    01071     *pszSelection = NULL;
    01072     if (!AlNewMenu(&hdMenuId)) {
    01073
    01074         return( ENOMEM );
    01075
    01076     }
    01077
    01078     //
    01079     // BUGBUG for now 1 selection will also build a menu, in the
    01080     // future once this is working we should just return that selection
    01081     //
    01082
    01083     if (!AlAddMenuItems(hdMenuId, rgszSelections, crgsz)) {
    01084
    01085         AlFreeMenu(hdMenuId);
    01086         return( ENOMEM );
    01087
    01088     }
    01089
    01090     if (!AlDisplayMenu(hdMenuId,
    01091                        FALSE,
    01092                        irgszDefault,
    01093                        pirgsz,
    01094                        crow,
    01095                        szTitle)) {
    01096
    01097         //
    01098         // User did not pick a system partition. return NULL
    01099         // can caller should abort
    01100         //
    01101         AlFreeMenu(hdMenuId);
    01102         return( ESUCCESS );
    01103
    01104     }
    01105
    01106     AlFreeMenu(hdMenuId);
    01107     *pszSelection = rgszSelections[*pirgsz];
    01108     return( ESUCCESS );
    01109
    01110 }
    01111
    01112 PCHAR
    01113 AlStrDup(
    01114
    01115     IN  PCHAR   szString
    01116     )
    01117
    01118 /*++
    01119
    01120 Routine Description:
    01121
    01122     This routine makes a copy of the passed in string. I do not use
    01123     the CRT strdup since it uses malloc.
    01124
    01125 Arguments:
    01126
    01127     szString - pointer of string to dup.
    01128
    01129 Return Value:
    01130
    01131     pointer to dup'd string. NULL if could not allocate
    01132
    01133 --*/
    01134 {
    01135
    01136     PCHAR   szT;
    01137
    01138     if (szT = AlAllocateHeap(strlen(szString) + 1)) {
    01139
    01140         strcpy(szT, szString);
    01141         return(szT);
    01142
    01143     }
    01144     return( NULL );
    01145
    01146 }
    01147
    01148
    01149 PCHAR
    01150 AlCombinePaths (
    01151
    01152     IN  PCHAR   szPath1,
    01153     IN  PCHAR   szPath2
    01154     )
    01155
    01156 /*++
    01157
    01158 Routine Description:
    01159
    01160     This routine combines to strings. It allocate a new string
    01161     to hold both strings.
    01162
    01163 Arguments:
    01164
    01165     pointer to combined path. NULL if failed to allocate.
    01166
    01167 Return Value:
    01168
    01169
    01170 --*/
    01171 {
    01172
    01173     PCHAR   szT;
    01174
    01175     if (szT = AlAllocateHeap(strlen(szPath1) + strlen(szPath2) + 1)) {
    01176
    01177         strcpy(szT, szPath1);
    01178         strcat(szT, szPath2);
    01179         return( szT );
    01180
    01181     } else {
    01182
    01183         return ( NULL );
    01184
    01185     }
    01186
    01187 }
    01188
    01189 VOID
    01190 AlFreeArray (
    01191
    01192     IN  BOOLEAN fFreeArray,
    01193     IN  PCHAR   *rgsz,
    01194     IN  ULONG   csz
    01195     )
    01196 /*++
    01197
    01198 Routine Description:
    01199
    01200     This routine iterates through an array of pointers to strings freeing
    01201     each string and finally the array itself.
    01202
    01203 Arguments:
    01204
    01205     fFreeArray - flag wither to free the array itself.
    01206     rgsz - pointer to array of strings.
    01207     csz - size of array.
    01208
    01209 Return Value:
    01210
    01211
    01212 --*/
    01213
    01214 {
    01215
    01216     ULONG   irgsz;
    01217
    01218     if (!csz) {
    01219
    01220         return;
    01221
    01222     }
    01223
    01224     for( irgsz = 0; irgsz < csz; irgsz++ ) {
    01225
    01226         if (rgsz[irgsz]) {
    01227
    01228             AlDeallocateHeap(rgsz[irgsz]);
    01229
    01230         } else {
    01231
    01232             break;
    01233
    01234         }
    01235
    01236     }
    01237     if (fFreeArray) {
    01238         AlDeallocateHeap( rgsz );
    01239     }
    01240
    01241 }
    01242
    01243 ARC_STATUS
    01244 AlGetBase (
    01245     IN  PCHAR   szPath,
    01246     OUT PCHAR   *pszBase
    01247     )
    01248
    01249 /*++
    01250
    01251 Routine Description:
    01252
    01253
    01254     This routine strips the filename off a path.
    01255
    01256 Arguments:
    01257
    01258     szPath - path to strip.
    01259
    01260 Return Value:
    01261
    01262     pszBaseh - pointer to buffer holding new base. (this is a copy)
    01263
    01264 --*/
    01265
    01266 {
    01267
    01268     PCHAR   szPathT;
    01269
    01270     //
    01271     // Make local copy of szArcInstPath so we can alter it
    01272     //
    01273     *pszBase = AlStrDup(szPath);
    01274     if ( *pszBase == NULL ) {
    01275
    01276         return( ENOMEM );
    01277     }
    01278
    01279     //
    01280     // The start of the path part should be either a \ or a ) where
    01281     // ) is the end of the arc name
    01282     //
    01283     if ((szPathT = strrchr(*pszBase,'\\')) == 0) {
    01284         if ((szPathT = strrchr(*pszBase, ')')) == 0) {
    01285
    01286             AlDeallocateHeap(*pszBase);
    01287             return( EBADSYNTAX );
    01288         }
    01289     }
    01290
    01291
    01292     //
    01293     // Cut filename out
    01294     //
    01295     // szPath points to either ')' or '\' so need to move over that
    01296     // onto actual name
    01297     //
    01298     *(szPathT + 1) = 0;
    01299     return( ESUCCESS );
    01300
    01301
    01302 }
    01303
    01304 //
    01305 // Define static data.
    01306 //
    01307
    01308
    01309 PCHAR AdapterTypes[AdapterMaximum + 1] = {"eisa","scsi", "multi", NULL};
    01310
    01311 PCHAR ControllerTypes[ControllerMaximum + 1] = {"cdrom", "disk", NULL};
    01312
    01313 PCHAR PeripheralTypes[PeripheralMaximum + 1] = {"rdisk", "fdisk", NULL};
    01314
    01315
    01316
    01317 PCHAR
    01318 AlGetNextArcNamToken (
    01319     IN PCHAR TokenString,
    01320     OUT PCHAR OutputToken,
    01321     OUT PULONG UnitNumber
    01322     )
    01323
    01324 /*++
    01325
    01326 Routine Description:
    01327
    01328     This routine scans the specified token string for the next token and
    01329     unit number. The token format is:
    01330
    01331         name[(unit)]
    01332
    01333 Arguments:
    01334
    01335     TokenString - Supplies a pointer to a zero terminated token string.
    01336
    01337     OutputToken - Supplies a pointer to a variable that receives the next
    01338         token.
    01339
    01340     UnitNumber - Supplies a pointer to a variable that receives the unit
    01341         number.
    01342
    01343 Return Value:
    01344
    01345     If another token exists in the token string, then a pointer to the
    01346     start of the next token is returned. Otherwise, a value of NULL is
    01347     returned.
    01348
    01349 --*/
    01350
    01351 {
    01352
    01353     //
    01354     // If there are more characters in the token string, then parse the
    01355     // next token. Otherwise, return a value of NULL.
    01356     //
    01357
    01358     if (*TokenString == '\0') {
    01359         return NULL;
    01360
    01361     } else {
    01362         while ((*TokenString != '\0') && (*TokenString != '(')) {
    01363             *OutputToken++ = *TokenString++;
    01364         }
    01365
    01366         *OutputToken = '\0';
    01367
    01368         //
    01369         // If a unit number is specified, then convert it to binary.
    01370         // Otherwise, default the unit number to zero.
    01371         //
    01372
    01373         *UnitNumber = 0;
    01374         if (*TokenString == '(') {
    01375             TokenString += 1;
    01376             while ((*TokenString != '\0') && (*TokenString != ')')) {
    01377                 *UnitNumber = (*UnitNumber * 10) + (*TokenString++ - '0');
    01378             }
    01379
    01380             if (*TokenString == ')') {
    01381                 TokenString += 1;
    01382             }
    01383         }
    01384     }
    01385
    01386     return TokenString;
    01387 }
    01388
    01389
    01390 ULONG
    01391 AlMatchArcNamToken (
    01392     IN PCHAR TokenValue,
    01393     IN TOKEN_TYPE TokenType
    01394     )
    01395
    01396 /*++
    01397
    01398 Routine Description:
    01399
    01400     This routine attempts to match a token with an array of possible
    01401     values.
    01402
    01403 Arguments:
    01404
    01405     TokenValue - Supplies a pointer to a zero terminated token value.
    01406
    01407     TokenType  - Indicates which type of token we are dealing with
    01408                  (AdapterType/ControllerType/PeripheralType)
    01409
    01410 Return Value:
    01411
    01412     If the token type is invalid, INVALID_TOKEN_TYPE is returned.
    01413
    01414     If a token match is not located, then a value INVALID_TOKEN_VALUE
    01415     is returned.
    01416
    01417     If a token match is located, then the ENUM value of the token is
    01418     returned.
    01419
    01420 --*/
    01421
    01422 {
    01423
    01424     ULONG   Index;
    01425     PCHAR   MatchString;
    01426     PCHAR   TokenString;
    01427     PCHAR   *TokenArray;
    01428     BOOLEAN Found;
    01429
    01430     //
    01431     // Depending on token type choose the appropriate token string array
    01432     //
    01433     switch (TokenType) {
    01434         case AdapterType:
    01435             TokenArray = AdapterTypes;
    01436             break;
    01437
    01438         case ControllerType:
    01439             TokenArray =  ControllerTypes;
    01440             break;
    01441
    01442         case PeripheralType:
    01443             TokenArray = PeripheralTypes;
    01444             break;
    01445
    01446         default:
    01447             return ((ULONG)INVALID_TOKEN_TYPE);
    01448     }
    01449
    01450     //
    01451     // Scan the match array until either a match is found or all of
    01452     // the match strings have been scanned.
    01453     //
    01454     // BUGBUG** The code below can be easily implemented using _strcmpi.
    01455     //
    01456
    01457     Index = 0;
    01458     Found = FALSE;
    01459     while (TokenArray[Index] != NULL) {
    01460         MatchString = TokenArray[Index];
    01461         TokenString = TokenValue;
    01462         while ((*MatchString != '\0') && (*TokenString != '\0')) {
    01463             if (toupper(*MatchString) != toupper(*TokenString)) {
    01464                 break;
    01465             }
    01466
    01467             MatchString += 1;
    01468             TokenString += 1;
    01469         }
    01470
    01471         if ((*MatchString == '\0') && (*TokenString == '\0')) {
    01472             Found = TRUE;
    01473             break;
    01474         }
    01475
    01476         Index += 1;
    01477     }
    01478
    01479     return (Found ? Index : INVALID_TOKEN_VALUE);
    01480 }
    01481
    01482 ULONG
    01483 AlPrint (
    01484     PCHAR Format,
    01485     ...
    01486     )
    01487
    01488 {
    01489
    01490     va_list arglist;
    01491     UCHAR Buffer[256];
    01492     ULONG Count;
    01493     ULONG Length;
    01494
    01495     //
    01496     // Format the output into a buffer and then print it.
    01497     //
    01498
    01499     va_start(arglist, Format);
    01500     Length = vsprintf(Buffer, Format, arglist);
    01501     ArcWrite( ARC_CONSOLE_OUTPUT, Buffer, Length, &Count);
    01502     va_end(arglist);
    01503     return 0;
    01504 }
    01505
    01506
    01507 BOOLEAN
    01508 AlGetString(
    01509     OUT PCHAR String,
    01510     IN  ULONG StringLength
    01511     )
    01512
    01513 /*++
    01514
    01515 Routine Description:
    01516
    01517     This routine reads a string from standardin until a
    01518     carriage return or escape is found or StringLength is reached.
    01519
    01520 Arguments:
    01521
    01522     String - Supplies a pointer to where the string will be stored.
    01523
    01524     StringLength - Supplies the Max Length to read.
    01525
    01526 Return Value:
    01527
    01528     FALSE if user pressed esc, TRUE otherwise.
    01529
    01530 --*/
    01531
    01532 {
    01533     CHAR    c;
    01534     ULONG   Count;
    01535     PCHAR   Buffer;
    01536
    01537     Buffer = String;
    01538     while (ArcRead(ARC_CONSOLE_INPUT,&c,1,&Count)==ESUCCESS) {
    01539         if(c == ASCI_ESC) {
    01540             return(FALSE);
    01541         }
    01542         if ((c=='\r') || (c=='\n') || ((ULONG)(Buffer-String) == StringLength)) {
    01543             *Buffer='\0';
    01544             ArcWrite(ARC_CONSOLE_OUTPUT,"\r\n",2,&Count);
    01545             return(TRUE);
    01546         }
    01547         //
    01548         // Check for backspace;
    01549         //
    01550         if (c=='\b') {
    01551             if (((ULONG)Buffer > (ULONG)String)) {
    01552                 Buffer--;
    01553                 ArcWrite(ARC_CONSOLE_OUTPUT,"\b \b",3,&Count);
    01554             }
    01555         } else {
    01556             //
    01557             // If it's a printable char store it and display it.
    01558             //
    01559             if (isprint(c)) {
    01560                 *Buffer++ = c;
    01561                 ArcWrite(ARC_CONSOLE_OUTPUT,&c,1,&Count);
    01562             }
    01563         }
    01564     }
    01565 }