diff --git a/CHANGELOG b/CHANGELOG
index 6768c46f54d0e41b91acb1dc482633a35fd8fd77..7139adb3a566690e2d81cc00f1b3a8bcfc52bfed 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,30 @@
+0.6.3 (2/3/2010):
+------------------
+
+- Fixed serious data corruption bug on big-endian (PowerPC and similar)
+  systems.
+
+- Changed several GPT fdisk Solaris type codes to correct a duplicate
+
+- Corrected error in GPT fdisk type codes for NetBSD LFS and NetBSD RAID;
+  they were identical, but I've now changed NetBSD RAID to A906, which
+  is unique.
+
+- Added GUID for IBM General Parallel File System (GPFS) partition type
+  code. Somewhat arbitrarily set it to use the 7501 number (MBR code 0x75
+  is used by IBM PC/IX, so it's at least the right company, by my loose
+  numbering rules....).
+
+- Improved GUID generation. Prior versions generated completely random
+  numbers for GUIDs. This works, but is technically a violation of the
+  spec. Unix versions now employ libuuid to generate GUIDs in a more
+  correct way. The Windows version still generates random numbers, though.
+
+- Turned PartTypes class into a derived class of GUIDData, and renamed
+  it to PartType.
+
+- Created new GUIDData class, to replace the original GUIDData struct.
+
 0.6.2 (1/29/2010):
 ------------------
 
diff --git a/Makefile b/Makefile
index 83381ed1aa804c60fc15cb93713b04011f0557e1..8e14b075825c9bee033e9fc29360971a0fe4dfa0 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ CC=gcc
 CXX=g++
 CFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -g
 CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -I /usr/local/include -I/opt/local/include -g
-LIB_NAMES=crc32 support gptpart mbr gpt bsd parttypes attributes diskio diskio-unix
+LIB_NAMES=crc32 support guid gptpart mbr gpt bsd parttypes attributes diskio diskio-unix
 LIB_SRCS=$(NAMES:=.cc)
 LIB_OBJS=$(LIB_NAMES:=.o)
 LIB_HEADERS=$(LIB_NAMES:=.h)
@@ -11,10 +11,13 @@ DEPEND= makedepend $(CFLAGS)
 all:	gdisk sgdisk
 
 gdisk:	$(LIB_OBJS) gdisk.o
-	$(CXX) $(LIB_OBJS) gdisk.o -o gdisk
+	$(CXX) $(LIB_OBJS) gdisk.o -L/opt/local/lib -L/usr/local/lib -luuid -o gdisk
 
 sgdisk: $(LIB_OBJS) sgdisk.o
-	$(CXX) $(LIB_OBJS) sgdisk.o -L/opt/local/lib -L/usr/local/lib -lpopt -o sgdisk
+	$(CXX) $(LIB_OBJS) sgdisk.o -L/opt/local/lib -L/usr/local/lib -luuid -lpopt -o sgdisk
+
+testguid:	$(LIB_OBJS) testguid.o
+	$(CXX) $(LIB_OBJS) testguid.o -o testguid
 
 lint:	#no pre-reqs
 	lint $(SRCS)
diff --git a/Makefile.mingw b/Makefile.mingw
index 1a59f2d599c1757151f9e144588c2822a28c8780..96ef8a0d14b5627c90f92a1742d0963902ec4900 100644
--- a/Makefile.mingw
+++ b/Makefile.mingw
@@ -2,8 +2,9 @@ CC=/usr/bin/i586-mingw32msvc-gcc
 CXX=/usr/bin/i586-mingw32msvc-g++
 STRIP=/usr/bin/i586-mingw32msvc-strip
 CFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -g
-CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -I /usr/local/include -I/opt/local/include -g
-LIB_NAMES=gptpart bsd parttypes attributes crc32 mbr gpt support diskio diskio-windows
+CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -g
+#CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -I /usr/local/include -I/opt/local/include -g
+LIB_NAMES=guid gptpart bsd parttypes attributes crc32 mbr gpt support diskio diskio-windows
 LIB_SRCS=$(NAMES:=.cc)
 LIB_OBJS=$(LIB_NAMES:=.o)
 LIB_HEADERS=$(LIB_NAMES:=.h)
@@ -12,10 +13,10 @@ DEPEND= makedepend $(CFLAGS)
 all:	gdisk
 
 gdisk:	$(LIB_OBJS) gdisk.o
-	$(CXX) $(LIB_OBJS) gdisk.o -o gdisk.exe
+	$(CXX) $(LIB_OBJS) gdisk.o -luuid -o gdisk.exe
 
 sgdisk: $(LIB_OBJS) sgdisk.o
-	$(CXX) $(LIB_OBJS) sgdisk.o -L/opt/local/lib -L/usr/local/lib -lpopt -o sgdisk.exe
+	$(CXX) $(LIB_OBJS) sgdisk.o -lpopt -o sgdisk.exe
 
 lint:	#no pre-reqs
 	lint $(SRCS)
diff --git a/README b/README
index cfca4fad61ffa481e21dd687c2b3b440378eabc6..9bf133c2faebe43aefcbe390ca941ebdf26b0483 100644
--- a/README
+++ b/README
@@ -50,22 +50,31 @@ Installing
 
 To compile GPT fdisk, you must have appropriate development tools
 installed, most notably the GNU Compiler Collection (GCC) and its g++
-compiler for C++. The sgdisk program also requires the popt library and its
-development files (headers). Most Linux distributions install popt by
-default, but you may need to install a package called popt-dev, popt-devel,
-or something similar to obtain the header files. Mac OS users can find a
-version of popt for Mac OS from http://popt.darwinports.com; however,
-you'll first need to install DarwinPorts (instructions exist on the
-preceding page). Alternatively, you can compile gdisk alone, without
-sgdisk; gdisk doesn't require popt.
+compiler for C++. In addition, note these requirements:
+
+* On Linux, FreeBSD, and OS X, libuuid must be installed. This is the
+  standard for Linux and OS X, although you may need to install a package
+  called uuid-dev or something similar to get the headers. On FreeBSD, the
+  e2fsprogs-libuuid port must be installed.
+
+* The sgdisk program also requires the popt library and its development
+  files (headers). Most Linux distributions install popt by default, but
+  you may need to install a package called popt-dev, popt-devel, or
+  something similar to obtain the header files. Mac OS users can find a
+  version of popt for Mac OS from http://popt.darwinports.com; however,
+  you'll first need to install DarwinPorts (instructions exist on the
+  preceding page). Alternatively, you can compile gdisk alone, without
+  sgdisk; gdisk doesn't require popt.
 
 When all the necessary development tools and libraries are installed, you
 can uncompress the package and type "make" at the command prompt in the
-resulting directory. The result should be program files called gdisk and
-sgdisk. Typing "make gdisk" or "make sgdisk" will compile only the requested
-programs. You can use these programs in place or copy the files to a
-suitable directory, such as /usr/local/sbin. You can copy the man pages
-(gdisk.8 and sgdisk.8) to /usr/local/man/man8 to make them available.
+resulting directory. (You may need to type "make -f Makefile.mac" on Mac OS
+X or "make -f Makefile.mingw" to compile using MinGW for Windows.) The
+result should be program files called gdisk and sgdisk. Typing "make gdisk"
+or "make sgdisk" will compile only the requested programs. You can use
+these programs in place or copy the files to a suitable directory, such as
+/usr/local/sbin. You can copy the man pages (gdisk.8 and sgdisk.8) to
+/usr/local/man/man8 to make them available.
 
 Caveats
 -------
diff --git a/README.Windows b/README.Windows
index a88d29d9610b7fae9656032ed1e9db2d940eef95..91074c46296b8c65813f94a6427e9608c02d445f 100644
--- a/README.Windows
+++ b/README.Windows
@@ -70,6 +70,15 @@ support of GPT, see Microsoft's Web page on the topic:
 
 http://www.microsoft.com/whdc/device/storage/GPT_FAQ.mspx
 
+The GUIDs generated by the program to uniquely identify disks and
+partitions aren't "proper" GUIDs; they're purely random numbers. In
+practice, this has caused me no problems; however, it's conceivable that
+some disk utility will complain. The Unix versions of GPT fdisk generate
+proper GUIDs, as of version 0.6.3. Note that this limitation applies ONLY
+to the unique GUIDs for disks and partitions, not to the GUIDs used to
+identify partition type codes; those are standardized and are handled
+correctly by all versions of GPT fdisk.
+
 Source Code and Compilation Issues
 ----------------------------------
 
diff --git a/attributes.cc b/attributes.cc
index 9bdd42869a8c3e64711d5403472483c617592cb0..b0800fa3c27adc624ab1b263236982eed5474da6 100644
--- a/attributes.cc
+++ b/attributes.cc
@@ -30,7 +30,7 @@ Attributes::Attributes(void) {
    } // for
 
    // Now reset those names that are defined....
-   atNames[0] = "system partition";
+   atNames[0] = "system partition"; // required for computer to operate
    atNames[60] = "read-only";
    atNames[62] = "hidden";
    atNames[63] = "do not automount";
diff --git a/bsd.cc b/bsd.cc
index 75dca603e81ad8cacac25f49db83ad60c2262430..f1d1ade532a9f3b2454e0388d4dbb89e580648c9 100644
--- a/bsd.cc
+++ b/bsd.cc
@@ -291,7 +291,7 @@ GPTPart BSDData::AsGPT(int i) {
       guid.SetFirstLBA(sectorOne);
       guid.SetLastLBA(sectorEnd);
       // Now set a random unique GUID for the partition....
-      guid.SetUniqueGUID(1);
+      guid.RandomizeUniqueGUID();
       // ... zero out the attributes and name fields....
       guid.SetAttributes(UINT64_C(0));
       // Most BSD disklabel type codes seem to be archaic or rare.
@@ -321,7 +321,7 @@ GPTPart BSDData::AsGPT(int i) {
             guid.SetType(0x0700); break;
       } // switch
       // Set the partition name to the name of the type code....
-      guid.SetName(guid.GetNameType());
+      guid.SetName(guid.GetTypeName());
    } // if
    return guid;
 } // BSDData::AsGPT()
diff --git a/gdisk.8 b/gdisk.8
index dad92659732e0736f5b5a611be06e3db7ab2eb57..3a683c72386b6354e95db3764befe114f6b61bbb 100644
--- a/gdisk.8
+++ b/gdisk.8
@@ -1,6 +1,6 @@
 .\" Copyright 2009 Roderick W. Smith (rodsmith@rodsbooks.com)
 .\" May be distributed under the GNU General Public License
-.TH "GDISK" "8" "0.5.3" "Roderick W. Smith" "GPT fdisk Manual"
+.TH "GDISK" "8" "0.6.3" "Roderick W. Smith" "GPT fdisk Manual"
 .SH "NAME"
 gdisk \- Interactive GUID partition table (GPT) manipulator
 .SH "SYNOPSIS"
diff --git a/gdisk.cc b/gdisk.cc
index 3dddc9e57abfa7ae19730031d79e3abfc3b37a13..5a2c9050c7376e7fc358f41b2eb04b112443686e 100644
--- a/gdisk.cc
+++ b/gdisk.cc
@@ -29,6 +29,7 @@ int main(int argc, char* argv[]) {
    GPTData theGPT;
    int doMore = 1;
    char* device = NULL;
+   PartType typeHelper; // unused, but necessary to initialize partition type linked list
 
    cout << "GPT fdisk (gdisk) version " << GPTFDISK_VERSION << "\n\n";
 
@@ -76,7 +77,7 @@ void MainMenu(string filename, struct GPTData* theGPT) {
    char command, line[255], buFile[255];
    char* junk;
    int goOn = 1;
-   PartTypes typeHelper;
+   PartType typeHelper;
    uint32_t temp1, temp2;
 
    do {
@@ -105,7 +106,7 @@ void MainMenu(string filename, struct GPTData* theGPT) {
             theGPT->ShowDetails();
             break;
          case 'l': case 'L':
-            typeHelper.ShowTypes();
+            typeHelper.ShowAllTypes();
             break;
          case 'n': case 'N':
             theGPT->CreatePartition();
@@ -177,7 +178,6 @@ void ShowCommands(void) {
 void RecoveryMenu(string filename, struct GPTData* theGPT) {
    char command, line[255], buFile[255];
    char* junk;
-   PartTypes typeHelper;
    uint32_t temp1;
    int goOn = 1;
 
@@ -303,10 +303,10 @@ void ShowRecoveryCommands(void) {
 void ExpertsMenu(string filename, struct GPTData* theGPT) {
    char command, line[255];
    char* junk;
-   PartTypes typeHelper;
    uint32_t pn;
    uint32_t temp1, temp2;
    int goOn = 1;
+   GUIDData aGUID;
 
    do {
       cout << "\nExpert command (? for help): ";
@@ -325,7 +325,7 @@ void ExpertsMenu(string filename, struct GPTData* theGPT) {
             if (theGPT->GetPartRange(&temp1, &temp2) > 0) {
                pn = theGPT->GetPartNum();
                cout << "Enter the partition's new unique GUID:\n";
-               theGPT->SetPartitionGUID(pn, GetGUID());
+               theGPT->SetPartitionGUID(pn, aGUID.GetGUIDFromUser());
             } else cout << "No partitions\n";
             break;
          case 'd': case 'D':
@@ -338,7 +338,7 @@ void ExpertsMenu(string filename, struct GPTData* theGPT) {
             break;
          case 'g': case 'G':
             cout << "Enter the disk's unique GUID:\n";
-            theGPT->SetDiskGUID(GetGUID());
+            theGPT->SetDiskGUID(aGUID.GetGUIDFromUser());
             break;
          case 'i': case 'I':
             theGPT->ShowDetails();
diff --git a/gpt.cc b/gpt.cc
index 9bb67632c1ed8a62befd344673b670e8bd11759c..562a085b5397175dd0655f4a124635ce10943683 100644
--- a/gpt.cc
+++ b/gpt.cc
@@ -173,12 +173,11 @@ int GPTData::Verify(void) {
            << secondHeader.lastUsableLBA << ")\n"
            << "The 'e' option on the experts' menu can probably fix this problem.\n";
    } // if
-   if ((mainHeader.diskGUID.data1 != secondHeader.diskGUID.data1) ||
-        (mainHeader.diskGUID.data2 != secondHeader.diskGUID.data2)) {
+   if ((mainHeader.diskGUID != secondHeader.diskGUID)) {
       problems++;
-      cout << "\nProblem: main header's disk GUID (" << GUIDToStr(mainHeader.diskGUID)
+      cout << "\nProblem: main header's disk GUID (" << mainHeader.diskGUID.AsString()
            << ") doesn't\nmatch the backup GPT header's disk GUID ("
-           << GUIDToStr(secondHeader.diskGUID) << ")\n"
+           << secondHeader.diskGUID.AsString() << ")\n"
            << "You should use the 'b' or 'd' option on the recovery & transformation menu to\n"
            << "select one or the other header.\n";
    } // if
@@ -368,8 +367,9 @@ int GPTData::CheckHeaderCRC(struct GPTHeader* header) {
    return (oldCRC == newCRC);
 } // GPTData::CheckHeaderCRC()
 
-// Recompute all the CRCs. Must be called before saving (but after reversing
-// byte order on big-endian systems) if any changes have been made.
+// Recompute all the CRCs. Must be called before saving if any changes have
+// been made. Must be called on platform-ordered data (this function reverses
+// byte order and then undoes that reversal.)
 void GPTData::RecomputeCRCs(void) {
    uint32_t crc, hSize, trueNumParts;
    int littleEndian = 1;
@@ -377,13 +377,21 @@ void GPTData::RecomputeCRCs(void) {
    // Initialize CRC functions...
    chksum_crc32gentab();
 
+   // Save some key data from header before reversing byte order....
+   trueNumParts = mainHeader.numParts;
    hSize = mainHeader.headerSize;
-   littleEndian = IsLittleEndian();
+
+   if ((littleEndian = IsLittleEndian()) == 0) {
+      ReversePartitionBytes();
+      ReverseHeaderBytes(&mainHeader);
+      ReverseHeaderBytes(&secondHeader);
+   } // if
+/*   if ((littleEndian = IsLittleEndian()) == 0) {
+      ReverseBytes(&trueNumParts, 4);
+      ReverseBytes(&hSize, 4);
+   } // if */
 
    // Compute CRC of partition tables & store in main and secondary headers
-   trueNumParts = mainHeader.numParts;
-   if (littleEndian == 0)
-      ReverseBytes(&trueNumParts, 4); // unreverse this key piece of data....
    crc = chksum_crc32((unsigned char*) partitions, trueNumParts * GPT_SIZE);
    mainHeader.partitionEntriesCRC = crc;
    secondHeader.partitionEntriesCRC = crc;
@@ -405,6 +413,12 @@ void GPTData::RecomputeCRCs(void) {
    if (littleEndian == 0)
       ReverseBytes(&crc, 4);
    secondHeader.headerCRC = crc;
+
+   if ((littleEndian = IsLittleEndian()) == 0) {
+      ReverseHeaderBytes(&mainHeader);
+      ReverseHeaderBytes(&secondHeader);
+      ReversePartitionBytes();
+   } // if
 } // GPTData::RecomputeCRCs()
 
 // Rebuild the main GPT header, using the secondary header as a model.
@@ -421,8 +435,7 @@ void GPTData::RebuildMainHeader(void) {
    mainHeader.backupLBA = secondHeader.currentLBA;
    mainHeader.firstUsableLBA = secondHeader.firstUsableLBA;
    mainHeader.lastUsableLBA = secondHeader.lastUsableLBA;
-   mainHeader.diskGUID.data1 = secondHeader.diskGUID.data1;
-   mainHeader.diskGUID.data2 = secondHeader.diskGUID.data2;
+   mainHeader.diskGUID = secondHeader.diskGUID;
    mainHeader.partitionEntriesLBA = UINT64_C(2);
    mainHeader.numParts = secondHeader.numParts;
    mainHeader.sizeOfPartitionEntries = secondHeader.sizeOfPartitionEntries;
@@ -445,8 +458,7 @@ void GPTData::RebuildSecondHeader(void) {
    secondHeader.backupLBA = mainHeader.currentLBA;
    secondHeader.firstUsableLBA = mainHeader.firstUsableLBA;
    secondHeader.lastUsableLBA = mainHeader.lastUsableLBA;
-   secondHeader.diskGUID.data1 = mainHeader.diskGUID.data1;
-   secondHeader.diskGUID.data2 = mainHeader.diskGUID.data2;
+   secondHeader.diskGUID = mainHeader.diskGUID;
    secondHeader.partitionEntriesLBA = secondHeader.lastUsableLBA + UINT64_C(1);
    secondHeader.numParts = mainHeader.numParts;
    secondHeader.sizeOfPartitionEntries = mainHeader.sizeOfPartitionEntries;
@@ -836,12 +848,14 @@ int GPTData::LoadSecondTableAsMain(void) {
 // Writes GPT (and protective MBR) to disk. Returns 1 on successful
 // write, 0 if there was a problem.
 int GPTData::SaveGPTData(int quiet) {
-   int allOK = 1;
+   int allOK = 1, littleEndian;
    char answer;
    uint64_t secondTable;
    uint32_t numParts;
    uint64_t offset;
 
+   littleEndian = IsLittleEndian();
+
    if (device == "") {
       cerr << "Device not defined.\n";
    } // if
@@ -894,14 +908,17 @@ int GPTData::SaveGPTData(int quiet) {
    // big-endian systems....
    numParts = mainHeader.numParts;
    secondTable = secondHeader.partitionEntriesLBA;
-   if (IsLittleEndian() == 0) {
+/*   if (IsLittleEndian() == 0) {
       // Reverse partition bytes first, since that function requires non-reversed
       // data from the main header....
       ReversePartitionBytes();
       ReverseHeaderBytes(&mainHeader);
       ReverseHeaderBytes(&secondHeader);
-   } // if
+   } // if */
    RecomputeCRCs();
+/*   ReverseHeaderBytes(&mainHeader);
+   ReverseHeaderBytes(&secondHeader);
+   ReversePartitionBytes(); */
 
    if ((allOK) && (!quiet)) {
       cout << "\nFinal checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING\n"
@@ -922,16 +939,24 @@ int GPTData::SaveGPTData(int quiet) {
       if (allOK && myDisk.OpenForWrite(device)) {
          // Now write the main GPT header...
          if (myDisk.Seek(1) == 1) {
+            if (!littleEndian)
+               ReverseHeaderBytes(&mainHeader);
             if (myDisk.Write(&mainHeader, 512) != 512)
                allOK = 0;
+            if (!littleEndian)
+               ReverseHeaderBytes(&mainHeader);
          } else allOK = 0; // if (myDisk.Seek()...)
 
          // Now write the main partition tables...
          if (allOK) {
 	    offset = mainHeader.partitionEntriesLBA;
 	    if (myDisk.Seek(offset)) {
+               if (!littleEndian)
+                  ReversePartitionBytes();
                if (myDisk.Write(partitions, GPT_SIZE * numParts) == -1)
                   allOK = 0;
+               if (!littleEndian)
+                  ReversePartitionBytes();
             } else allOK = 0; // if (myDisk.Seek()...)
          } // if (allOK)
 
@@ -947,18 +972,26 @@ int GPTData::SaveGPTData(int quiet) {
 
          // Now write the secondary partition tables....
          if (allOK) {
+            if (!littleEndian)
+               ReversePartitionBytes();
             if (myDisk.Write(partitions, GPT_SIZE * numParts) == -1)
                allOK = 0;
-	 } // if (allOK)
+            if (!littleEndian)
+               ReversePartitionBytes();
+         } // if (allOK)
 
          // Now write the secondary GPT header...
          if (allOK) {
 	    offset = mainHeader.backupLBA;
-	    if (myDisk.Seek(offset)) {
+            if (!littleEndian)
+               ReverseHeaderBytes(&secondHeader);
+            if (myDisk.Seek(offset)) {
                if (myDisk.Write(&secondHeader, 512) == -1)
                   allOK = 0;
 	    } else allOK = 0; // if (myDisk.Seek()...)
-	 } // if (allOK)
+            if (!littleEndian)
+               ReverseHeaderBytes(&secondHeader);
+         } // if (allOK)
 
          // re-read the partition table
          if (allOK) {
@@ -982,13 +1015,13 @@ int GPTData::SaveGPTData(int quiet) {
       cout << "Aborting write of new partition table.\n";
    } // if
 
-   if (IsLittleEndian() == 0) {
+/*   if (IsLittleEndian() == 0) {
       // Reverse (normalize) header bytes first, since ReversePartitionBytes()
       // requires non-reversed data in mainHeader...
       ReverseHeaderBytes(&mainHeader);
       ReverseHeaderBytes(&secondHeader);
       ReversePartitionBytes();
-   } // if
+   } // if */
 
    return (allOK);
 } // GPTData::SaveGPTData()
@@ -1005,6 +1038,12 @@ int GPTData::SaveGPTBackup(const string & filename) {
    DiskIO backupFile;
 
    if (backupFile.OpenForWrite(filename)) {
+      // Recomputing the CRCs is likely to alter them, which could be bad
+      // if the intent is to save a potentially bad GPT for later analysis;
+      // but if we don't do this, we get bogus errors when we load the
+      // backup. I'm favoring misses over false alarms....
+      RecomputeCRCs();
+
       // Reverse the byte order, if necessary....
       numParts = mainHeader.numParts;
       if (IsLittleEndian() == 0) {
@@ -1013,12 +1052,6 @@ int GPTData::SaveGPTBackup(const string & filename) {
          ReverseHeaderBytes(&secondHeader);
       } // if
 
-      // Recomputing the CRCs is likely to alter them, which could be bad
-      // if the intent is to save a potentially bad GPT for later analysis;
-      // but if we don't do this, we get bogus errors when we load the
-      // backup. I'm favoring misses over false alarms....
-      RecomputeCRCs();
-
       // Now write the protective MBR...
       protectiveMBR.WriteMBRData(&backupFile);
 
@@ -1191,7 +1224,7 @@ void GPTData::DisplayGPTData(void) {
    cout << "Disk " << device << ": " << diskSize << " sectors, "
         << BytesToSI(diskSize * blockSize) << "\n";
    cout << "Logical sector size: " << blockSize << " bytes\n";
-   cout << "Disk identifier (GUID): " << GUIDToStr(mainHeader.diskGUID) << "\n";
+   cout << "Disk identifier (GUID): " << mainHeader.diskGUID.AsString() << "\n";
    cout << "Partition table holds up to " << mainHeader.numParts << " entries\n";
    cout << "First usable sector is " << mainHeader.firstUsableLBA
         << ", last usable sector is " << mainHeader.lastUsableLBA << "\n";
@@ -1320,7 +1353,7 @@ void GPTData::CreatePartition(void) {
 
       firstFreePart = CreatePartition(partNum, firstBlock, lastBlock);
       partitions[partNum].ChangeType();
-      partitions[partNum].SetName(partitions[partNum].GetNameType());
+      partitions[partNum].SetDefaultDescription();
    } else {
       cout << "No free sectors available\n";
    } // if/else
@@ -1551,7 +1584,6 @@ WhichToUse GPTData::UseWhichPartitions(void) {
 int GPTData::XFormPartitions(void) {
    int i, numToConvert;
    uint8_t origType;
-   struct newGUID;
 
    // Clear out old data & prepare basics....
    ClearGPTData();
@@ -1567,7 +1599,7 @@ int GPTData::XFormPartitions(void) {
       // don't waste CPU time trying to convert extended, hybrid protective, or
       // null (non-existent) partitions
       if ((origType != 0x05) && (origType != 0x0f) && (origType != 0x85) &&
-           (origType != 0x00) && (origType != 0xEE))
+          (origType != 0x00) && (origType != 0xEE))
          partitions[i] = protectiveMBR.AsGPT(i);
    } // for
 
@@ -1583,6 +1615,7 @@ int GPTData::XFormPartitions(void) {
 
 // Transforms BSD disklabel on the specified partition (numbered from 0).
 // If an invalid partition number is given, the program prompts for one.
+// (Default for i is -1; called without an option, it therefore prompts.)
 // Returns the number of new partitions created.
 int GPTData::XFormDisklabel(int i) {
    uint32_t low, high, partNum, startPart;
@@ -1635,7 +1668,7 @@ int GPTData::XFormDisklabel(BSDData* disklabel, uint32_t startPart) {
    int i, numDone = 0;
 
    if ((disklabel->IsDisklabel()) && (startPart >= 0) &&
-        (startPart < mainHeader.numParts)) {
+       (startPart < mainHeader.numParts)) {
       for (i = 0; i < disklabel->GetNumParts(); i++) {
          partitions[i + startPart] = disklabel->AsGPT(i);
          if (partitions[i + startPart].GetFirstLBA() != UINT64_C(0))
@@ -1682,7 +1715,7 @@ int GPTData::OnePartToMBR(uint32_t gptPart, int mbrPart) {
       do {
          cout << "Enter an MBR hex code (default " << hex;
          cout.width(2);
-         cout << typeHelper.GUIDToID(partitions[gptPart].GetType()) / 256 << "): ";
+         cout << partitions[gptPart].GetHexType() / 0x0100 << "): ";
          junk = fgets(line, 255, stdin);
          if (line[0] == '\n')
             typeCode = partitions[gptPart].GetHexType() / 256;
@@ -1948,7 +1981,7 @@ uint32_t GPTData::CreatePartition(uint32_t partNum, uint64_t startSector, uint64
             partitions[partNum].SetFirstLBA(startSector);
             partitions[partNum].SetLastLBA(endSector);
             partitions[partNum].SetType(0x0700);
-            partitions[partNum].SetUniqueGUID(1);
+            partitions[partNum].RandomizeUniqueGUID();
          } else retval = 0; // if free space until endSector
       } else retval = 0; // if startSector is free
    } else retval = 0; // if legal partition number
@@ -2021,9 +2054,7 @@ int GPTData::ClearGPTData(void) {
    mainHeader.lastUsableLBA = diskSize - mainHeader.firstUsableLBA;
 
    // Set a unique GUID for the disk, based on random numbers
-   // rand() is only 32 bits, so multiply together to fill a 64-bit value
-   mainHeader.diskGUID.data1 = (uint64_t) rand() * (uint64_t) rand();
-   mainHeader.diskGUID.data2 = (uint64_t) rand() * (uint64_t) rand();
+   mainHeader.diskGUID.Randomize();
 
    // Copy main header to backup header
    RebuildSecondHeader();
@@ -2392,8 +2423,7 @@ void GPTData::ReverseHeaderBytes(struct GPTHeader* header) {
    ReverseBytes(&header->sizeOfPartitionEntries, 4);
    ReverseBytes(&header->partitionEntriesCRC, 4);
    ReverseBytes(&header->reserved2, GPT_RESERVED);
-   ReverseBytes(&header->diskGUID.data1, 8);
-   ReverseBytes(&header->diskGUID.data2, 8);
+//   header->diskGUID.ReverseGUIDBytes();
 } // GPTData::ReverseHeaderBytes()
 
 // IMPORTANT NOTE: This function requires non-reversed mainHeader
@@ -2458,6 +2488,14 @@ int SizesOK(void) {
       cerr << "GPTPart is " << sizeof(GPTPart) << " bytes, should be 128 bytes; aborting!\n";
       allOK = 0;
    } // if
+   if (sizeof(GUIDData) != 16) {
+      cerr << "GUIDData is " << sizeof(GUIDData) << " bytes, should be 16 bytes; aborting!\n";
+      allOK = 0;
+   } // if
+   if (sizeof(PartType) != 16) {
+      cerr << "PartType is " << sizeof(GUIDData) << " bytes, should be 16 bytes; aborting!\n";
+      allOK = 0;
+   } // if
    // Determine endianness; warn user if running on big-endian (PowerPC, etc.) hardware
    if (IsLittleEndian() == 0) {
       cerr << "\aRunning on big-endian hardware. Big-endian support is new and poorly"
diff --git a/gpt.h b/gpt.h
index ca04ec4092fa7831354bd82be4dc212d02849e0e..f1225707245ae7bce3fca2a2d25e5a65ab012057 100644
--- a/gpt.h
+++ b/gpt.h
@@ -16,7 +16,7 @@
 #ifndef __GPTSTRUCTS
 #define __GPTSTRUCTS
 
-#define GPTFDISK_VERSION "0.6.2"
+#define GPTFDISK_VERSION "0.6.3"
 
 using namespace std;
 
@@ -44,7 +44,7 @@ struct GPTHeader {
    uint64_t backupLBA;
    uint64_t firstUsableLBA;
    uint64_t lastUsableLBA;
-   struct GUIDData diskGUID;
+   GUIDData diskGUID;
    uint64_t partitionEntriesLBA;
    uint32_t numParts;
    uint32_t sizeOfPartitionEntries;
@@ -72,7 +72,6 @@ protected:
    int apmFound; // set to 1 if APM detected
    int bsdFound; // set to 1 if BSD disklabel detected in MBR
    int sectorAlignment; // Start & end partitions at multiples of sectorAlignment
-   PartTypes typeHelper;
    int beQuiet;
    WhichToUse whichWasUsed;
 public:
diff --git a/gptpart.cc b/gptpart.cc
index 40c426c4a95ecbe8655c81ba468653e8d9422ae3..1cba0a0f56800360f3de458b144f843d043b24d9 100644
--- a/gptpart.cc
+++ b/gptpart.cc
@@ -23,8 +23,6 @@
 
 using namespace std;
 
-PartTypes GPTPart::typeHelper;
-
 GPTPart::GPTPart(void) {
    int i;
 
@@ -37,13 +35,13 @@ GPTPart::~GPTPart(void) {
 
 // Return the gdisk-specific two-byte hex code for the partition
 uint16_t GPTPart::GetHexType(void) {
-   return typeHelper.GUIDToID(partitionType);
+   return partitionType.GetHexType();
 } // GPTPart::GetHexType()
 
 // Return a plain-text description of the partition type (e.g., "Linux/Windows
 // data" or "Linux swap").
-string GPTPart::GetNameType(void) {
-   return typeHelper.GUIDToName(partitionType);
+string GPTPart::GetTypeName(void) {
+   return partitionType.TypeName();
 } // GPTPart::GetNameType()
 
 // Compute and return the partition's length (or 0 if the end is incorrectly
@@ -56,7 +54,7 @@ uint64_t GPTPart::GetLengthLBA(void) {
 } // GPTPart::GetLengthLBA()
 
 // Return partition's name field, converted to a C++ ASCII string
-string GPTPart::GetName(void) {
+string GPTPart::GetDescription(void) {
    string theName;
    int i;
 
@@ -66,32 +64,18 @@ string GPTPart::GetName(void) {
          theName += name[i];
    } // for
    return theName;
-} // GPTPart::GetName()
+} // GPTPart::GetDescription()
 
 // Set the type code to the specified one. Also changes the partition
 // name *IF* the current name is the generic one for the current partition
 // type.
-void GPTPart::SetType(struct GUIDData t) {
-   if (GetName() == typeHelper.GUIDToName(partitionType)) {
-      SetName(typeHelper.GUIDToName(t));
+void GPTPart::SetType(PartType t) {
+   if (GetDescription() == partitionType.TypeName()) {
+      SetName(t.TypeName());
    } // if
    partitionType = t;
 } // GPTPart::SetType()
 
-// Sets the unique GUID to a value of 0 or a random value,
-// depending on the parameter: 0 = 0, anything else = random
-void GPTPart::SetUniqueGUID(int zeroOrRandom) {
-   if (zeroOrRandom == 0) {
-      uniqueGUID.data1 = 0;
-      uniqueGUID.data2 = 0;
-   } else {
-      // rand() is only 32 bits on 32-bit systems, so multiply together to
-      // fill a 64-bit value.
-      uniqueGUID.data1 = (uint64_t) rand() * (uint64_t) rand();
-      uniqueGUID.data2 = (uint64_t) rand() * (uint64_t) rand();
-   }
-} // GPTPart::SetUniqueGUID()
-
 // Set the name for a partition to theName, or prompt for a name if
 // theName is empty. Note that theName is a standard C++-style ASCII
 // string, although the GUID partition definition requires a UTF-16LE
@@ -111,8 +95,9 @@ void GPTPart::SetName(const string & theName) {
 
       // Input is likely to include a newline, so remove it....
       i = strlen(newName);
-      if (newName[i - 1] == '\n')
-         newName[i - 1] = '\0';
+      if ((i > 0) && (i <= NAME_SIZE))
+         if (newName[i - 1] == '\n')
+            newName[i - 1] = '\0';
    } else {
       strcpy(newName, theName.substr(0, NAME_SIZE / 2).c_str());
    } // if
@@ -128,6 +113,12 @@ void GPTPart::SetName(const string & theName) {
    } // for
 } // GPTPart::SetName()
 
+// Set the name for the partition based on the current GUID partition type
+// code's associated name
+void GPTPart::SetDefaultDescription(void) {
+   SetName(partitionType.TypeName());
+} // GPTPart::SetDefaultDescription()
+
 GPTPart & GPTPart::operator=(const GPTPart & orig) {
    int i;
 
@@ -159,10 +150,9 @@ void GPTPart::ShowSummary(int partNum, uint32_t blockSize) {
       cout.fill('0');
       cout.width(4);
       cout.setf(ios::uppercase);
-      cout << hex << typeHelper.GUIDToID(partitionType) << "  " << dec;
+      cout << hex << partitionType.GetHexType() << "  " << dec;
       cout.fill(' ');
-//      cout.setf(ios::right);
-      cout << GetName().substr(0, 23) << "\n";
+      cout << GetDescription().substr(0, 23) << "\n";
       cout.fill(' ');
    } // if
 } // GPTPart::ShowSummary()
@@ -173,9 +163,9 @@ void GPTPart::ShowDetails(uint32_t blockSize) {
    uint64_t size;
 
    if (firstLBA != 0) {
-      cout << "Partition GUID code: " << GUIDToStr(partitionType);
-      cout << " (" << typeHelper.GUIDToName(partitionType) << ")\n";
-      cout << "Partition unique GUID: " << GUIDToStr(uniqueGUID) << "\n";
+      cout << "Partition GUID code: " << partitionType.AsString();
+      cout << " (" << partitionType.TypeName() << ")\n";
+      cout << "Partition unique GUID: " << uniqueGUID.AsString() << "\n";
 
       cout << "First sector: " << firstLBA << " (at "
             << BytesToSI(firstLBA * blockSize) << ")\n";
@@ -190,7 +180,7 @@ void GPTPart::ShowDetails(uint32_t blockSize) {
       cout << hex;
       cout << attributes << "\n";
       cout << dec;
-      cout << "Partition name: " << GetName() << "\n";
+      cout << "Partition name: " << GetDescription() << "\n";
       cout.fill(' ');
    }  // if
 } // GPTPart::ShowDetails()
@@ -198,12 +188,9 @@ void GPTPart::ShowDetails(uint32_t blockSize) {
 // Blank (delete) a single partition
 void GPTPart::BlankPartition(void) {
    int j;
-   GUIDData zeroGUID;
 
-   zeroGUID.data1 = 0;
-   zeroGUID.data2 = 0;
-   uniqueGUID = zeroGUID;
-   partitionType = zeroGUID;
+   uniqueGUID.Zero();
+   partitionType.Zero();
    firstLBA = 0;
    lastLBA = 0;
    attributes = 0;
@@ -228,10 +215,8 @@ int GPTPart::DoTheyOverlap(const GPTPart & other) {
 
 // Reverse the bytes of integral data types; used on big-endian systems.
 void GPTPart::ReversePartBytes(void) {
-   ReverseBytes(&partitionType.data1, 8);
-   ReverseBytes(&partitionType.data2, 8);
-   ReverseBytes(&uniqueGUID.data1, 8);
-   ReverseBytes(&uniqueGUID.data2, 8);
+//   partitionType.ReverseGUIDBytes();
+//   uniqueGUID.ReverseGUIDBytes();
    ReverseBytes(&firstLBA, 8);
    ReverseBytes(&lastLBA, 8);
    ReverseBytes(&attributes, 8);
@@ -241,30 +226,34 @@ void GPTPart::ReversePartBytes(void) {
  * Functions requiring user interaction *
  ****************************************/
 
-// Change the type code on the partition.
+// Change the type code on the partition. Also changes the name if the original
+// name is the generic one for the partition type.
 void GPTPart::ChangeType(void) {
    char line[255];
    char* junk;
-   int typeNum = 0xFFFF;
-   GUIDData newType;
+   unsigned int typeNum = 0xFFFF, changeName = 0;
 
-   cout << "Current type is '" << GetNameType() << "'\n";
-   while ((!typeHelper.Valid(typeNum)) && (typeNum != 0)) {
+   if (GetDescription() == GetTypeName())
+      changeName = 1;
+   cout << "Current type is '" << GetTypeName() << "'\n";
+   while ((!partitionType.Valid(typeNum)) && (typeNum != 0)) {
       cout << "Hex code (L to show codes, 0 to enter raw code, Enter = 0700): ";
       junk = fgets(line, 255, stdin);
       sscanf(line, "%X", &typeNum);
       if ((line[0] == 'L') || (line[0] == 'l'))
-         typeHelper.ShowTypes();
+         partitionType.ShowAllTypes();
       if (line[0] == '\n') {
          typeNum = 0x0700;
       } // if
    } // while
    if (typeNum != 0) // user entered a code, so convert it
-      newType = typeHelper.IDToGUID((uint16_t) typeNum);
+      partitionType = typeNum;
    else // user wants to enter the GUID directly, so do that
-      newType = GetGUID();
-   SetType(newType);
-   cout << "Changed type of partition to '" << typeHelper.GUIDToName(partitionType) << "'\n";
+      partitionType.GetGUIDFromUser();
+   cout << "Changed type of partition to '" << partitionType.TypeName() << "'\n";
+   if (changeName) {
+      SetDefaultDescription();
+   } // if
 } // GPTPart::ChangeType()
 
 /***********************************
diff --git a/gptpart.h b/gptpart.h
index d24ed87fba1745377cb3af5d9bdaab1e9fbf8729..e6467c1579addf35eefc9000bd03bc807d460e0c 100644
--- a/gptpart.h
+++ b/gptpart.h
@@ -20,6 +20,7 @@
 #include <sys/types.h>
 #include "support.h"
 #include "parttypes.h"
+#include "guid.h"
 
 using namespace std;
 
@@ -38,38 +39,37 @@ class GPTPart {
       // adjusting the data-load operation in GPTData::LoadMainTable() and
       // GPTData::LoadSecondTableAsMain() and then removing the GPTPart
       // size check in SizesOK() (in gpt.cc file).
-      struct GUIDData partitionType;
-      struct GUIDData uniqueGUID;
+      PartType partitionType;
+      GUIDData uniqueGUID;
       uint64_t firstLBA;
       uint64_t lastLBA;
       uint64_t attributes;
       unsigned char name[NAME_SIZE];
-
-      static PartTypes typeHelper;
    public:
       GPTPart(void);
       ~GPTPart(void);
 
       // Simple data retrieval:
-      struct GUIDData GetType(void) {return partitionType;}
+      PartType & GetType(void) {return partitionType;}
       uint16_t GetHexType(void);
-      string GetNameType(void);
-      struct GUIDData GetUniqueGUID(void) {return uniqueGUID;}
+      string GetTypeName(void);
+      GUIDData GetUniqueGUID(void) {return uniqueGUID;}
       uint64_t GetFirstLBA(void) {return firstLBA;}
       uint64_t GetLastLBA(void) {return lastLBA;}
       uint64_t GetLengthLBA(void);
       uint64_t GetAttributes(void) {return attributes;}
-      string GetName(void);
+      string GetDescription(void);
 
       // Simple data assignment:
-      void SetType(struct GUIDData t);
-      void SetType(uint16_t hex) {SetType(typeHelper.IDToGUID(hex));}
-      void SetUniqueGUID(struct GUIDData u) {uniqueGUID = u;}
-      void SetUniqueGUID(int zeroOrRandom);
+      void SetType(PartType t);
+      void SetType(uint16_t hex) {partitionType = hex;}
+      void SetUniqueGUID(GUIDData u) {uniqueGUID = u;}
+      void RandomizeUniqueGUID(void) {uniqueGUID.Randomize();}
       void SetFirstLBA(uint64_t f) {firstLBA = f;}
       void SetLastLBA(uint64_t l) {lastLBA = l;}
       void SetAttributes(uint64_t a) {attributes = a;}
       void SetName(const string & n);
+      void SetDefaultDescription(void);
 
       // Additional functions
       GPTPart & operator=(const GPTPart & orig);
diff --git a/mbr.cc b/mbr.cc
index 214fcb0e1f8a5a4dad8dcc07dd61b7e3aed8851d..2417d7745dba924ec110918c2cdcbb0432ed14e9 100644
--- a/mbr.cc
+++ b/mbr.cc
@@ -39,6 +39,7 @@ MBRData::MBRData(void) {
    numHeads = MAX_HEADS;
    numSecspTrack = MAX_SECSPERTRACK;
    myDisk = NULL;
+   canDeleteMyDisk = 0;
    EmptyMBR();
 } // MBRData default constructor
 
@@ -50,6 +51,7 @@ MBRData::MBRData(string filename) {
    numHeads = MAX_HEADS;
    numSecspTrack = MAX_SECSPERTRACK;
    myDisk = NULL;
+   canDeleteMyDisk = 0;
 
    srand((unsigned int) time(NULL));
    // Try to read the specified partition table, but if it fails....
@@ -59,8 +61,12 @@ MBRData::MBRData(string filename) {
    } // if
 } // MBRData(string filename) constructor
 
+// Free space used by myDisk only if that's OK -- sometimes it will be
+// copied from an outside source, in which case that source should handle
+// it!
 MBRData::~MBRData(void) {
-//   delete myDisk;
+   if (canDeleteMyDisk)
+      delete myDisk;
 } // MBRData destructor
 
 /**********************
@@ -74,8 +80,10 @@ MBRData::~MBRData(void) {
 int MBRData::ReadMBRData(const string & deviceFilename) {
    int allOK = 1;
 
-   if (myDisk == NULL)
+   if (myDisk == NULL) {
       myDisk = new DiskIO;
+      canDeleteMyDisk = 1;
+   } // if
    if (myDisk->OpenForRead(deviceFilename)) {
       ReadMBRData(myDisk);
    } else {
@@ -98,8 +106,10 @@ void MBRData::ReadMBRData(DiskIO * theDisk, int checkBlockSize) {
    int err = 1;
    TempMBR tempMBR;
 
-   if (myDisk != NULL)
+   if ((myDisk != NULL) && (canDeleteMyDisk)) {
       delete myDisk;
+      canDeleteMyDisk = 0;
+   } // if
 
    myDisk = theDisk;
 
@@ -831,9 +841,9 @@ GPTPart MBRData::AsGPT(int i) {
          if (lastSector > 0) lastSector--;
          newPart.SetLastLBA(lastSector);
          newPart.SetType(((uint16_t) origType) * 0x0100);
-         newPart.SetUniqueGUID(1);
+         newPart.RandomizeUniqueGUID();
          newPart.SetAttributes(0);
-         newPart.SetName(newPart.GetNameType());
+         newPart.SetName(newPart.GetTypeName());
       } // if not extended, protective, or non-existent
    } // if (origPart != NULL)
    return newPart;
diff --git a/mbr.h b/mbr.h
index e83de7e88a5497690ec604bfbb967d041b5245b9..35cd1076a3fbabf5ab68c6bfa3aa32e46177f7ee 100644
--- a/mbr.h
+++ b/mbr.h
@@ -71,6 +71,7 @@ protected:
    uint64_t numHeads; // number of heads, in CHS scheme
    uint64_t numSecspTrack; // number of sectors per track, in CHS scheme
    DiskIO* myDisk;
+   int canDeleteMyDisk;
    string device;
    MBRValidity state;
    struct MBRRecord* GetPartition(int i); // Return primary or logical partition
diff --git a/parttypes.cc b/parttypes.cc
index 85ce6b0c778b2cb3f006bb6bbb612317dca2d7b4..850b1e3ad8d5919e2e2991d25f43ce1a5f933e7d 100644
--- a/parttypes.cc
+++ b/parttypes.cc
@@ -16,9 +16,9 @@
 
 using namespace std;
 
-int PartTypes::numInstances = 0;
-AType* PartTypes::allTypes = NULL;
-AType* PartTypes::lastType = NULL;
+int PartType::numInstances = 0;
+AType* PartType::allTypes = NULL;
+AType* PartType::lastType = NULL;
 
 // Constructor. Its main task is to initialize the data list, but only
 // if this is the first instance, since it's a static linked list.
@@ -31,166 +31,28 @@ AType* PartTypes::lastType = NULL;
 // by typing "L" at the main gdisk menu.
 // See http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
 // for a list of MBR partition type codes.
-PartTypes::PartTypes(void) {
-
+PartType::PartType(void) : GUIDData() {
    numInstances++;
    if (numInstances == 1) {
-
-      // Start with the "unused entry," which should normally appear only
-      // on empty partition table entries....
-      AddType(0x0000, UINT64_C(0x0000000000000000), UINT64_C(0x0000000000000000),
-              "Unused entry", 0);
-
-      // DOS/Windows partition types, which confusingly Linux also uses in GPT
-      AddType(0x0100, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
-              "Linux/Windows data", 0); // FAT-12
-      AddType(0x0400, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
-              "Linux/Windows data", 0); // FAT-16 < 32M
-      AddType(0x0600, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
-              "Linux/Windows data", 0); // FAT-16
-      AddType(0x0700, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
-              "Linux/Windows data", 1); // NTFS (or could be HPFS)
-      AddType(0x0b00, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
-              "Linux/Windows data", 0); // FAT-32
-      AddType(0x0c00, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
-              "Linux/Windows data", 0); // FAT-32 LBA
-      AddType(0x0c01, UINT64_C(0x4DB80B5CE3C9E316), UINT64_C(0xAE1502F02DF97D81),
-              "Microsoft Reserved"); // Microsoft reserved
-      AddType(0x0e00, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
-              "Linux/Windows data", 0); // FAT-16 LBA
-      AddType(0x1100, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
-              "Linux/Windows data", 0); // Hidden FAT-12
-      AddType(0x1400, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
-              "Linux/Windows data", 0); // Hidden FAT-16 < 32M
-      AddType(0x1600, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
-              "Linux/Windows data", 0); // Hidden FAT-16
-      AddType(0x1700, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
-              "Linux/Windows data", 0); // Hidden NTFS (or could be HPFS)
-      AddType(0x1b00, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
-              "Linux/Windows data", 0); // Hidden FAT-32
-      AddType(0x1c00, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
-              "Linux/Windows data", 0); // Hidden FAT-32 LBA
-      AddType(0x1e00, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
-              "Linux/Windows data", 0); // Hidden FAT-16 LBA
-      AddType(0x2700, UINT64_C(0x4D4006D1DE94BBA4), UINT64_C(0xACD67901D5BF6AA1),
-              "Windows RE"); // Windows RE
-      AddType(0x4200, UINT64_C(0x4F621431Af9B60A0), UINT64_C(0xAD694A71113368BC),
-              "Windows LDM data"); // Logical disk manager
-      AddType(0x4201, UINT64_C(0x42E07E8F5808C8AA), UINT64_C(0xB3CF3404E9E1D285),
-              "Windows LDM metadata"); // Logical disk manager
-
-      // Linux-specific partition types....
-      AddType(0x8200, UINT64_C(0x43C4A4AB0657FD6D), UINT64_C(0x4F4F4BC83309E584),
-              "Linux swap"); // Linux swap (or could be Solaris)
-      AddType(0x8300, UINT64_C(0x4433B9E5EBD0A0A2), UINT64_C(0xC79926B7B668C087),
-              "Linux/Windows data", 0); // Linux native
-      AddType(0x8301, UINT64_C(0x60C000078DA63339), UINT64_C(0x080923C83A0836C4),
-              "Linux Reserved"); // Linux reserved
-      AddType(0x8e00, UINT64_C(0x44C2F507E6D6D379), UINT64_C(0x28F93D2A8F233CA2),
-              "Linux LVM"); // Linux LVM
-
-      // FreeBSD partition types....
-      // Note: Rather than extract FreeBSD disklabel data, convert FreeBSD
-      // partitions in-place, and let FreeBSD sort out the details....
-      AddType(0xa500, UINT64_C(0x11D66ECF516E7CB4), UINT64_C(0x2B71092D0200F88F),
-              "FreeBSD disklabel"); // FreeBSD disklabel
-      AddType(0xa501, UINT64_C(0x11DC7F4183BD6B9D), UINT64_C(0x0F4FB86015000BBE),
-              "FreeBSD boot"); // FreeBSD boot
-      AddType(0xa502, UINT64_C(0x11D66ECF516E7CB5), UINT64_C(0x2B71092D0200F88F),
-              "FreeBSD swap"); // FreeBSD swap
-      AddType(0xa503, UINT64_C(0x11D66ECF516E7CB6), UINT64_C(0x2B71092D0200F88F),
-              "FreeBSD UFS"); // FreeBSD UFS
-      AddType(0xa504, UINT64_C(0x11D66ECF516E7CBA), UINT64_C(0x2B71092D0200F88F),
-              "FreeBSD ZFS"); // FreeBSD ZFS
-      AddType(0xa505, UINT64_C(0x11D66ECF516E7CB8), UINT64_C(0x2B71092D0200F88F),
-              "FreeBSD Vinum/RAID"); // FreeBSD Vinum
-
-      // A MacOS partition type, separated from others by NetBSD partition types...
-      AddType(0xa800, UINT64_C(0x11AA000055465300), UINT64_C(0xACEC4365300011AA),
-              "Apple UFS"); // MacOS X
-
-      // NetBSD partition types. Note that the main entry sets it up as a
-      // FreeBSD disklabel. I'm not 100% certain this is the correct behavior.
-      AddType(0xa900, UINT64_C(0x11D66ECF516E7CB4), UINT64_C(0x2B71092D0200F88F),
-              "FreeBSD disklabel", 0); // NetBSD disklabel
-      AddType(0xa901, UINT64_C(0x11DCB10E49F48D32), UINT64_C(0x489687D119009BB9),
-              "NetBSD swap");
-      AddType(0xa902, UINT64_C(0x11DCB10E49F48D5A), UINT64_C(0x489687D119009BB9),
-              "NetBSD FFS");
-      AddType(0xa903, UINT64_C(0x11DCB10E49F48D82), UINT64_C(0x489687D119009BB9),
-              "NetBSD LFS");
-      AddType(0xa903, UINT64_C(0x11DCB10E49F48DAA), UINT64_C(0x489687D119009BB9),
-              "NetBSD RAID");
-      AddType(0xa904, UINT64_C(0x11DCB10F2DB519C4), UINT64_C(0x489687D119009BB9),
-              "NetBSD concatenated");
-      AddType(0xa905, UINT64_C(0x11DCB10F2DB519EC), UINT64_C(0x489687D119009BB9),
-              "NetBSD encrypted");
-
-      // MacOS partition types (See also 0xa800, above)....
-      AddType(0xab00, UINT64_C(0x11AA0000426F6F74), UINT64_C(0xACEC4365300011AA),
-              "Apple boot"); // MacOS X
-      AddType(0xaf00, UINT64_C(0x11AA000048465300), UINT64_C(0xACEC4365300011AA),
-              "Apple HFS/HFS+"); // MacOS X
-      AddType(0xaf01, UINT64_C(0x11AA000052414944), UINT64_C(0xACEC4365300011AA),
-              "Apple RAID"); // MacOS X
-      AddType(0xaf02, UINT64_C(0x11AA5F4F52414944), UINT64_C(0xACEC4365300011AA),
-              "Apple RAID offline"); // MacOS X
-      AddType(0xaf03, UINT64_C(0x11AA6C004C616265), UINT64_C(0xACEC4365300011AA),
-              "Apple label"); // MacOS X
-      AddType(0xaf04, UINT64_C(0x11AA76655265636F), UINT64_C(0xACEC4365300011AA),
-              "AppleTV recovery"); // MacOS X
-
-      // Solaris partition types (one of which is shared with MacOS)
-      AddType(0xbe00, UINT64_C(0x11B21DD26A82CB45), UINT64_C(0x316673200008A699),
-              "Solaris boot"); // Solaris boot
-      AddType(0xbf00, UINT64_C(0x11B21DD26a85CF4D), UINT64_C(0x316673200008A699),
-              "Solaris root"); // Solaris root
-      AddType(0xbf01, UINT64_C(0x11B21DD26A898CC3), UINT64_C(0x316673200008A699),
-              "Solaris /usr & Mac ZFS"); // MacOS X & Solaris
-      AddType(0xbf02, UINT64_C(0x11B21DD26A87C46F), UINT64_C(0x316673200008A699),
-              "Solaris swap");
-      AddType(0xbf03, UINT64_C(0x11B21DD26A8B642B), UINT64_C(0x316673200008A699),
-              "Solaris backup");
-      AddType(0xbf04, UINT64_C(0x11B21DD26A8EF2E9), UINT64_C(0x316673200008A699),
-              "Solaris /var");
-      AddType(0xbf05, UINT64_C(0x11B21DD26A90BA39), UINT64_C(0x316673200008A699),
-              "Solaris /home");
-      AddType(0xbf05, UINT64_C(0x11B21DD26A9283A5), UINT64_C(0x316673200008A699),
-              "Solaris EFI_ALTSCTR");
-      AddType(0xbf06, UINT64_C(0x11B21DD26A945A3B), UINT64_C(0x316673200008A699),
-              "Solaris Reserved 1");
-      AddType(0xbf07, UINT64_C(0x11B21DD26A9630D1), UINT64_C(0x316673200008A699),
-              "Solaris Reserved 2");
-      AddType(0xbf08, UINT64_C(0x11B21DD26A980767), UINT64_C(0x316673200008A699),
-              "Solaris Reserved 3");
-      AddType(0xbf09, UINT64_C(0x11B21DD26A96237F), UINT64_C(0x316673200008A699),
-              "Solaris Reserved 4");
-      AddType(0xbf0a, UINT64_C(0x11B21DD26A8D2AC7), UINT64_C(0x316673200008A699),
-              "Solaris Reserved 5");
-
-      // I can find no MBR equivalents for these, but they're on the
-      // Wikipedia page for GPT, so here we go....
-      AddType(0xc001, UINT64_C(0x11D33AEB75894C1E), UINT64_C(0x000000A0037BC1B7),
-              "HP-UX data");
-      AddType(0xc002, UINT64_C(0x11D632E3E2A1E728), UINT64_C(0x000000A0037B82A6),
-              "HP-UX service");
-
-      // EFI system and related partitions
-      AddType(0xEF00, UINT64_C(0x11d2f81fc12a7328), UINT64_C(0x3bc93ec9a0004bba),
-              "EFI System"); // EFI System (parted marks Linux boot
-                             // partitions like this)
-      AddType(0xEF01, UINT64_C(0x11d333e7024dee41), UINT64_C(0x9FF381C70800699d),
-              "MBR partition scheme"); // Used to nest an MBR table on a GPT disk
-      AddType(0xEF02, UINT64_C(0x6E6F644921686148), UINT64_C(0x4946456465654E74),
-              "BIOS boot partition"); //
-
-      // A straggler Linux partition type....
-      AddType(0xfd00, UINT64_C(0x4D3B05FCA19D880F), UINT64_C(0x1E91840F3F7406A0),
-              "Linux RAID"); // Linux RAID
+      AddAllTypes();
    } // if
 } // default constructor
 
-PartTypes::~PartTypes(void) {
+PartType::PartType(const PartType & orig) : GUIDData(orig) {
+   numInstances++;
+   if (numInstances == 1) { // should never happen; just being paranoid
+      AddAllTypes();
+   } // if
+} // PartType copy constructor
+
+PartType::PartType(const GUIDData & orig) : GUIDData(orig) {
+   numInstances++;
+   if (numInstances == 1) {
+      AddAllTypes();
+   } // if
+} // PartType copy constructor
+
+PartType::~PartType(void) {
    AType* tempType;
 
    numInstances--;
@@ -203,19 +65,117 @@ PartTypes::~PartTypes(void) {
    } // if
 } // destructor
 
+// Add all partition type codes to the internal linked-list structure.
+// Used by constructors.
+void PartType::AddAllTypes(void) {
+   // Start with the "unused entry," which should normally appear only
+   // on empty partition table entries....
+   AddType(0x0000, "00000000-0000-0000-0000-000000000000", "Unused entry", 0);
+
+   // DOS/Windows partition types, which confusingly Linux also uses in GPT
+   AddType(0x0100, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // FAT-12
+   AddType(0x0400, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // FAT-16 < 32M
+   AddType(0x0600, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // FAT-16
+   AddType(0x0700, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 1); // NTFS (or HPFS)
+   AddType(0x0b00, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // FAT-32
+   AddType(0x0c00, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // FAT-32 LBA
+   AddType(0x0c01, "E3C9E316-0B5C-4DB8-817D-F92DF00215AE", "Microsoft reserved");
+   AddType(0x0e00, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // FAT-16 LBA
+   AddType(0x1100, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // Hidden FAT-12
+   AddType(0x1400, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // Hidden FAT-16 < 32M
+   AddType(0x1600, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // Hidden FAT-16
+   AddType(0x1700, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // Hidden NTFS (or HPFS)
+   AddType(0x1b00, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // Hidden FAT-32
+   AddType(0x1c00, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // Hidden FAT-32 LBA
+   AddType(0x1e00, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // Hidden FAT-16 LBA
+   AddType(0x2700, "DE94BBA4-06D1-4D40-A16A-BFD50179D6AC", "Windows RE");
+   AddType(0x4200, "AF9B60A0-1431-4F62-BC68-3311714A69AD", "Windows LDM data"); // Logical disk manager
+   AddType(0x4201, "5808C8AA-7E8F-42E0-85D2-E1E90434CFB3", "Windows LDM metadata"); // Logical disk manager
+
+   // An oddball IBM filesystem....
+   AddType(0x7501, "37AFFC90-EF7D-4E96-91C3-2D7AE055B174", "IBM GPFS"); // General Parallel File System (GPFS)
+
+   // Linux-specific partition types....
+   AddType(0x8200, "0657FD6D-A4AB-43C4-84E5-0933C84B4F4F", "Linux swap"); // Linux swap (or Solaris)
+   AddType(0x8300, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", "Linux/Windows data", 0); // Linux native
+   AddType(0x8301, "8DA63339-0007-60C0-C436-083AC8230908", "Linux reserved");
+   AddType(0x8e00, "E6D6D379-F507-44C2-A23C-238F2A3DF928", "Linux LVM");
+
+   // FreeBSD partition types....
+   // Note: Rather than extract FreeBSD disklabel data, convert FreeBSD
+   // partitions in-place, and let FreeBSD sort out the details....
+   AddType(0xa500, "516E7CB4-6ECF-11D6-8FF8-00022D09712B", "FreeBSD Disklabel");
+   AddType(0xa501, "83BD6B9D-7F41-11DC-BE0B-001560B84F0F", "FreeBSD boot");
+   AddType(0xa502, "516E7CB5-6ECF-11D6-8FF8-00022D09712B", "FreeBSD swap");
+   AddType(0xa503, "516E7CB6-6ECF-11D6-8FF8-00022D09712B", "FreeBSD UFS");
+   AddType(0xa504, "516E7CBA-6ECF-11D6-8FF8-00022D09712B", "FreeBSD ZFS");
+   AddType(0xa505, "516E7CB8-6ECF-11D6-8FF8-00022D09712B", "FreeBSD Vinum/RAID");
+
+   // A MacOS partition type, separated from others by NetBSD partition types...
+   AddType(0xa800, "55465300-0000-11AA-AA11-00306543ECAC", "Apple UFS"); // Mac OS X
+
+   // NetBSD partition types. Note that the main entry sets it up as a
+   // FreeBSD disklabel. I'm not 100% certain this is the correct behavior.
+   AddType(0xa900, "516E7CB4-6ECF-11D6-8FF8-00022D09712B", "FreeBSD disklabel", 0); // NetBSD disklabel
+   AddType(0xa901, "49F48D32-B10E-11DC-B99B-0019D1879648", "NetBSD swap");
+   AddType(0xa902, "49F48D5A-B10E-11DC-B99B-0019D1879648", "NetBSD FFS");
+   AddType(0xa903, "49F48D82-B10E-11DC-B99B-0019D1879648", "NetBSD LFS");
+   AddType(0xa904, "2DB519C4-B10F-11DC-B99B-0019D1879648", "NetBSD concatenated");
+   AddType(0xa905, "2DB519EC-B10F-11DC-B99B-0019D1879648", "NetBSD encrypted");
+   AddType(0xa906, "49F48DAA-B10E-11DC-B99B-0019D1879648", "NetBSD RAID");
+
+   // Mac OS partition types (See also 0xa800, above)....
+   AddType(0xab00, "426F6F74-0000-11AA-AA11-00306543ECAC", "Apple boot");
+   AddType(0xaf00, "48465300-0000-11AA-AA11-00306543ECAC", "Apple HFS/HFS+");
+   AddType(0xaf01, "52414944-0000-11AA-AA11-00306543ECAC", "Apple RAID");
+   AddType(0xaf02, "52414944-5F4F-11AA-AA11-00306543ECAC", "Apple RAID offline");
+   AddType(0xaf03, "4C616265-6C00-11AA-AA11-00306543ECAC", "Apple label");
+   AddType(0xaf04, "5265636F-7665-11AA-AA11-00306543ECAC", "AppleTV recovery");
+
+   // Solaris partition types (one of which is shared with MacOS)
+   AddType(0xbe00, "6A82CB45-1DD2-11B2-99A6-080020736631", "Solaris boot");
+   AddType(0xbf00, "6A85CF4D-1DD2-11B2-99A6-080020736631", "Solaris root");
+   AddType(0xbf01, "6A898CC3-1DD2-11B2-99A6-080020736631", "Solaris /usr & Mac ZFS"); // Solaris/MacOS
+   AddType(0xbf02, "6A87C46F-1DD2-11B2-99A6-080020736631", "Solaris swap");
+   AddType(0xbf03, "6A8B642B-1DD2-11B2-99A6-080020736631", "Solaris backup");
+   AddType(0xbf04, "6A8EF2E9-1DD2-11B2-99A6-080020736631", "Solaris /var");
+   AddType(0xbf05, "6A90BA39-1DD2-11B2-99A6-080020736631", "Solaris /home");
+   AddType(0xbf06, "6A9283A5-1DD2-11B2-99A6-080020736631", "Solaris alternate sector");
+   AddType(0xbf07, "6A945A3B-1DD2-11B2-99A6-080020736631", "Solaris Reserved 1");
+   AddType(0xbf08, "6A9630D1-1DD2-11B2-99A6-080020736631", "Solaris Reserved 2");
+   AddType(0xbf09, "6A980767-1DD2-11B2-99A6-080020736631", "Solaris Reserved 3");
+   AddType(0xbf0a, "6A96237F-1DD2-11B2-99A6-080020736631", "Solaris Reserved 4");
+   AddType(0xbf0b, "6A8D2AC7-1DD2-11B2-99A6-080020736631", "Solaris Reserved 5");
+
+   // I can find no MBR equivalents for these, but they're on the
+   // Wikipedia page for GPT, so here we go....
+   AddType(0xc001, "75894C1E-3AEB-11D3-B7C1-7B03A0000000", "HP-UX data");
+   AddType(0xc002, "E2A1E728-32E3-11D6-A682-7B03A0000000", "HP-UX service");
+
+   // EFI system and related partitions
+   AddType(0xef00, "C12A7328-F81F-11D2-BA4B-00A0C93EC93B", "EFI System"); // Parted marks Linux boot partitions as this
+   AddType(0xef01, "024DEE41-33E7-11D3-9D69-0008C781F39F", "MBR partition scheme"); // Used to nest MBR in GPT
+   AddType(0xef02, "21686148-6449-6E6F-744E-656564454649", "BIOS boot partition"); // Boot loader
+
+   // A straggler Linux partition type....
+   AddType(0xfd00, "A19D880F-05FC-4D3B-A006-743F0F84911E", "Linux RAID");
+
+   // Note: DO NOT use the 0xffff code; that's reserved to indicate an
+   // unknown type code.
+} // PartType::AddAllTypes()
+
 // Add a single type to the linked list of types. Returns 1 if operation
 // succeeds, 0 otherwise.
-int PartTypes::AddType(uint16_t mbrType, uint64_t guidData1, uint64_t guidData2,
-                       const char * n, int toDisplay) {
+int PartType::AddType(uint16_t mbrType, const char * guidData, const char * name,
+                      int toDisplay) {
    AType* tempType;
    int allOK = 1;
 
    tempType = new AType;
    if (tempType != NULL) {
       tempType->MBRType = mbrType;
-      tempType->GUIDType.data1 = guidData1;
-      tempType->GUIDType.data2 = guidData2;
-      tempType->name = n;
+      tempType->GUIDType = guidData;
+      tempType->name = name;
       tempType->display = toDisplay;
       tempType->next = NULL;
       if (allTypes == NULL) { // first entry
@@ -228,122 +188,70 @@ int PartTypes::AddType(uint16_t mbrType, uint64_t guidData1, uint64_t guidData2,
       allOK = 0;
    } // if/else
    return allOK;
-} // PartTypes::AddType()
-
-// Displays the available types and my extended MBR codes for same....
-// Note: This function assumes an 80-column display. On wider displays,
-// it stops at under 80 columns; on narrower displays, lines will wrap
-// in an ugly way.
-void PartTypes::ShowTypes(void) {
-   int colCount = 1; // column count
-   size_t i;
-   AType* thisType = allTypes;
+} // GUID::AddType(const char* variant)
 
-   cout.unsetf(ios::uppercase);
-   while (thisType != NULL) {
-      if (thisType->display == 1) { // show it
-         cout.fill('0');
-         cout.width(4);
-         cout << hex << thisType->MBRType << " ";
-         cout << thisType->name.substr(0, 20);
-         for (i = 0; i < (20 - (thisType->name.substr(0, 20).length())); i++) cout << " ";
-         if ((colCount % 3) == 0)
-            cout << "\n";
-         else
-            cout << "  ";
-         colCount++;
-      } // if
-      thisType = thisType->next;
-   } // while
-   cout.fill(' ');
-   cout << "\n" << dec;
-} // PartTypes::ShowTypes()
-
-// Returns 1 if code is a valid extended MBR code, 0 if it's not
-int PartTypes::Valid(uint16_t code) {
-   AType* thisType = allTypes;
-   int found = 0;
-
-   while ((thisType != NULL) && (!found)) {
-      if (thisType->MBRType == code) {
-         found = 1;
-      } // if
-      thisType = thisType->next;
-   } // while
-   return found;
-} // PartTypes::Valid()
-
-// Convert a GUID code to a name.
-string PartTypes::GUIDToName(struct GUIDData typeCode) {
+// Assign a GUID based on my custom 2-byte (16-bit) MBR hex ID variant
+GUIDData & PartType::operator=(uint16_t ID) {
    AType* theItem = allTypes;
    int found = 0;
-   string typeName;
 
+   // Assign a default value....
+   GUIDData::operator=("EBD0A0A2-B9E5-4433-87C0-68B6B72699C7"); // 0700, Linux/Windows data
+
+   // Now search the type list for a match to the ID....
    while ((theItem != NULL) && (!found)) {
-      if ((theItem->GUIDType.data1 == typeCode.data1) &&
-          (theItem->GUIDType.data2 == typeCode.data2)) { // found it!
-         typeName = theItem->name;
-	 found = 1;
+      if (theItem->MBRType == ID)  { // found it!
+         GUIDData::operator=(theItem->GUIDType);
+         found = 1;
       } else {
          theItem = theItem->next;
       } // if/else
    } // while
    if (!found) {
-      typeName = "Unknown";
+      cout.setf(ios::uppercase);
+      cout.fill('0');
+      cout << "Exact type match not found for type code ";
+      cout.width(4);
+      cout << hex << ID << "; assigning type code for\n'Linux/Windows data'\n" << dec;
+      cout.fill(' ');
    } // if (!found)
-   return typeName;
-} // PartTypes::GUIDToName()
+   return *this;
+} // PartType::operator=(uint16_t ID)
 
-// This function takes a variant of the MBR partition type code and
-// converts it to a GUID type code
-struct GUIDData PartTypes::IDToGUID(uint16_t ID) {
+// Return the English description of the partition type (e.g., "Linux/Windows data")
+string PartType::TypeName(void) {
    AType* theItem = allTypes;
    int found = 0;
-   struct GUIDData theGUID;
-
-   // Start by assigning a default GUID for the return value. Done
-   // "raw" to avoid the necessity for a recursive call and the
-   // remote possibility of an infinite recursive loop that this
-   // approach would present....
-   theGUID.data1 = UINT64_C(0x4433B9E5EBD0A0A2);
-   theGUID.data2 = UINT64_C(0xC79926B7B668C087);
+   string typeName;
 
-   // Now search the type list for a match to the ID....
    while ((theItem != NULL) && (!found)) {
-      if (theItem->MBRType == ID)  { // found it!
-         theGUID = theItem->GUIDType;
-	 found = 1;
+      if (theItem->GUIDType == *this) { // found it!
+         typeName = theItem->name;
+         found = 1;
       } else {
          theItem = theItem->next;
       } // if/else
    } // while
    if (!found) {
-      cout.setf(ios::uppercase);
-      cout.fill('0');
-      cout << "Exact type match not found for type code ";
-      cout.width(4);
-      cout << hex << ID << "; assigning type code for\n'Linux/Windows data'\n" << dec;
-      cout.fill(' ');
+      typeName = "Unknown";
    } // if (!found)
-   return theGUID;
-} // PartTypes::IDToGUID()
+   return typeName;
+} // PartType::TypeName()
 
-// Convert a GUID to a 16-bit variant of the MBR ID number.
+// Return the custom GPT fdisk 2-byte (16-bit) hex code for this GUID partition type
 // Note that this function ignores entries for which the display variable
 // is set to 0. This enables control of which values get returned when
 // there are multiple possibilities, but opens the algorithm up to the
 // potential for problems should the data in the list be bad.
-uint16_t PartTypes::GUIDToID(struct GUIDData typeCode) {
+uint16_t PartType::GetHexType() {
    AType* theItem = allTypes;
    int found = 0;
    uint16_t theID = 0xFFFF;
 
    while ((theItem != NULL) && (!found)) {
-      if ((theItem->GUIDType.data1 == typeCode.data1) &&
-          (theItem->GUIDType.data2 == typeCode.data2) &&
-          (theItem->display == 1)) { // found it!
+      if ((theItem->GUIDType == *this) && (theItem->display == 1)) { // found it!
          theID = theItem->MBRType;
-	 found = 1;
+         found = 1;
       } else {
          theItem = theItem->next;
       } // if/else
@@ -352,4 +260,47 @@ uint16_t PartTypes::GUIDToID(struct GUIDData typeCode) {
       theID = 0xFFFF;
    } // if (!found)
    return theID;
-} // PartTypes::GUIDToID()
+} // PartType::GetHex()
+
+// Displays the available types and my extended MBR codes for same....
+// Note: This function assumes an 80-column display. On wider displays,
+// it stops at under 80 columns; on narrower displays, lines will wrap
+// in an ugly way.
+void PartType::ShowAllTypes(void) {
+   int colCount = 1; // column count
+   size_t i;
+   AType* thisType = allTypes;
+
+   cout.unsetf(ios::uppercase);
+   while (thisType != NULL) {
+      if (thisType->display == 1) { // show it
+         cout.fill('0');
+         cout.width(4);
+         cout << hex << thisType->MBRType << " ";
+         cout << thisType->name.substr(0, 20);
+         for (i = 0; i < (20 - (thisType->name.substr(0, 20).length())); i++) cout << " ";
+         if ((colCount % 3) == 0)
+            cout << "\n";
+         else
+            cout << "  ";
+         colCount++;
+      } // if
+      thisType = thisType->next;
+   } // while
+   cout.fill(' ');
+   cout << "\n" << dec;
+} // PartType::ShowTypes()
+
+// Returns 1 if code is a valid extended MBR code, 0 if it's not
+int PartType::Valid(uint16_t code) {
+   AType* thisType = allTypes;
+   int found = 0;
+
+   while ((thisType != NULL) && (!found)) {
+      if (thisType->MBRType == code) {
+         found = 1;
+      } // if
+      thisType = thisType->next;
+   } // while
+   return found;
+} // PartType::Valid()
diff --git a/parttypes.h b/parttypes.h
index 1534a52c38a02eeaf963908ffb00011f7c4f9194..1f82d1d71b0d5585b68a35d21cdecc37f7c08839 100644
--- a/parttypes.h
+++ b/parttypes.h
@@ -6,6 +6,7 @@
 #include <stdlib.h>
 #include <string>
 #include "support.h"
+#include "guid.h"
 
 #ifndef __PARTITION_TYPES
 #define __PARTITION_TYPES
@@ -18,27 +19,42 @@ struct AType {
    // type codes, so as to permit disambiguation and use of new
    // codes required by GPT
    uint16_t MBRType;
-   struct GUIDData GUIDType;
+   GUIDData GUIDType;
    string name;
    int display; // 1 to show to users as available type, 0 not to
    AType* next;
 }; // struct AType
 
-class PartTypes {
+class PartType : public GUIDData {
 protected:
    static int numInstances;
    static AType* allTypes; // Linked list holding all the data
    static AType* lastType; // Pointer to last entry in the list
+   void AddAllTypes(void);
 public:
-   PartTypes(void);
-   ~PartTypes(void);
-   int AddType(uint16_t mbrType, uint64_t guidData1, uint64_t guidData2,
-               const char * name, int toDisplay = 1);
-   void ShowTypes(void);
+   PartType(void);
+   PartType(const PartType & orig);
+   PartType(const GUIDData & orig);
+   ~PartType(void);
+
+   // Set up type information
+   int AddType(uint16_t mbrType, const char * guidData, const char * name, int toDisplay = 1);
+
+   // Assignment operators based on base class....
+   GUIDData & operator=(const GUIDData & orig) {return GUIDData::operator=(orig);}
+   GUIDData & operator=(const string & orig) {return GUIDData::operator=(orig);}
+   GUIDData & operator=(const char * orig) {return GUIDData::operator=(orig);}
+
+   // New data assignment
+   GUIDData & operator=(uint16_t ID); // Use MBR type code time 0x0100 to assign GUID
+
+   // Retrieve transformed GUID data based on type code matches
+   string TypeName(void);
+   uint16_t GetHexType();
+
+   // Information relating to all type data
+   void ShowAllTypes(void);
    int Valid(uint16_t);
-   string GUIDToName(struct GUIDData typeCode);
-   struct GUIDData IDToGUID(uint16_t ID);
-   uint16_t GUIDToID(struct GUIDData);
 };
 
 #endif
diff --git a/sgdisk.8 b/sgdisk.8
index 1a26a61c0631505fe7c545434c2a0ec27e48fe87..5a554cd7077cb988eca097f6086456ed8c8b1be7 100644
--- a/sgdisk.8
+++ b/sgdisk.8
@@ -1,6 +1,6 @@
 .\" Copyright 2009 Roderick W. Smith (rodsmith@rodsbooks.com)
 .\" May be distributed under the GNU General Public License
-.TH "SGDISK" "8" "0.6.0" "Roderick W. Smith" "GPT fdisk Manual"
+.TH "SGDISK" "8" "0.6.3" "Roderick W. Smith" "GPT fdisk Manual"
 .SH "NAME"
 sgdisk \- Command\-line GUID partition table (GPT) manipulator for Linux and Unix
 .SH "SYNOPSIS"
diff --git a/sgdisk.cc b/sgdisk.cc
index bdb2eb2f823f631ed9e3cc3fede7df24016f98e3..e97e57d34143c31266a4d519b950a238fff31b06 100644
--- a/sgdisk.cc
+++ b/sgdisk.cc
@@ -37,7 +37,7 @@ int main(int argc, char *argv[]) {
    char *device = NULL;
    char *newPartInfo = NULL, *typeCode = NULL, *partName;
    char *backupFile = NULL;
-   PartTypes typeHelper;
+   PartType typeHelper;
 
    poptContext poptCon;
    struct poptOption theOptions[] =
@@ -82,7 +82,7 @@ int main(int argc, char *argv[]) {
    while ((opt = poptGetNextOpt(poptCon)) > 0) {
       switch (opt) {
          case 'L':
-            typeHelper.ShowTypes();
+            typeHelper.ShowAllTypes();
             break;
          case 'P':
             pretend = 1;
diff --git a/support.cc b/support.cc
index 313763592f13c490c45d49965f80903444da036b..56a2dd3b745f03157bb7aa3fc1a13c64298b485f 100644
--- a/support.cc
+++ b/support.cc
@@ -200,112 +200,19 @@ string BytesToSI(uint64_t size) {
    return theValue;
 } // BlocksToSI()
 
-// Return a plain-text name for a partition type.
-// Convert a GUID to a string representation, suitable for display
-// to humans....
-string GUIDToStr(struct GUIDData theGUID) {
-   unsigned long long blocks[11];
-   char theString[40];
-
-   theString[0] = '\0';;
-   blocks[0] = (theGUID.data1 & UINT64_C(0x00000000FFFFFFFF));
-   blocks[1] = (theGUID.data1 & UINT64_C(0x0000FFFF00000000)) >> 32;
-   blocks[2] = (theGUID.data1 & UINT64_C(0xFFFF000000000000)) >> 48;
-   blocks[3] = (theGUID.data2 & UINT64_C(0x00000000000000FF));
-   blocks[4] = (theGUID.data2 & UINT64_C(0x000000000000FF00)) >> 8;
-   blocks[5] = (theGUID.data2 & UINT64_C(0x0000000000FF0000)) >> 16;
-   blocks[6] = (theGUID.data2 & UINT64_C(0x00000000FF000000)) >> 24;
-   blocks[7] = (theGUID.data2 & UINT64_C(0x000000FF00000000)) >> 32;
-   blocks[8] = (theGUID.data2 & UINT64_C(0x0000FF0000000000)) >> 40;
-   blocks[9] = (theGUID.data2 & UINT64_C(0x00FF000000000000)) >> 48;
-   blocks[10] = (theGUID.data2 & UINT64_C(0xFF00000000000000)) >> 56;
-   sprintf(theString,
-            "%08llX-%04llX-%04llX-%02llX%02llX-%02llX%02llX%02llX%02llX%02llX%02llX",
-            blocks[0], blocks[1], blocks[2], blocks[3], blocks[4], blocks[5],
-            blocks[6], blocks[7], blocks[8], blocks[9], blocks[10]);
-   return theString;
-} // GUIDToStr()
-
-// Get a GUID from the user
-GUIDData GetGUID(void) {
-   unsigned long long part1, part2, part3, part4, part5;
-   int entered = 0;
-   char temp[255], temp2[255];
-   char* junk;
-   GUIDData theGUID;
-
-   cout << "\nA GUID is entered in five segments of from two to six bytes, with\n"
-        << "dashes between segments.\n";
-   cout << "Enter the entire GUID, a four-byte hexadecimal number for the first segment, or\n"
-        << "'R' to generate the entire GUID randomly: ";
-   junk = fgets(temp, 255, stdin);
-
-   // If user entered 'r' or 'R', generate GUID randomly....
-   if ((temp[0] == 'r') || (temp[0] == 'R')) {
-      theGUID.data1 = (uint64_t) rand() * (uint64_t) rand();
-      theGUID.data2 = (uint64_t) rand() * (uint64_t) rand();
-      entered = 1;
-   } // if user entered 'R' or 'r'
-
-   // If string length is right for whole entry, try to parse it....
-   if ((strlen(temp) == 37) && (entered == 0)) {
-      strncpy(temp2, &temp[0], 8);
-      temp2[8] = '\0';
-      sscanf(temp2, "%llx", &part1);
-      strncpy(temp2, &temp[9], 4);
-      temp2[4] = '\0';
-      sscanf(temp2, "%llx", &part2);
-      strncpy(temp2, &temp[14], 4);
-      temp2[4] = '\0';
-      sscanf(temp2, "%llx", &part3);
-      theGUID.data1 = (part3 << 48) + (part2 << 32) + part1;
-      strncpy(temp2, &temp[19], 4);
-      temp2[4] = '\0';
-      sscanf(temp2, "%llx", &part4);
-      strncpy(temp2, &temp[24], 12);
-      temp2[12] = '\0';
-      sscanf(temp2, "%llx", &part5);
-      theGUID.data2 = ((part4 & UINT64_C(0x000000000000FF00)) >> 8) +
-                      ((part4 & UINT64_C(0x00000000000000FF)) << 8) +
-                      ((part5 & UINT64_C(0x0000FF0000000000)) >> 24) +
-                      ((part5 & UINT64_C(0x000000FF00000000)) >> 8) +
-                      ((part5 & UINT64_C(0x00000000FF000000)) << 8) +
-                      ((part5 & UINT64_C(0x0000000000FF0000)) << 24) +
-                      ((part5 & UINT64_C(0x000000000000FF00)) << 40) +
-                      ((part5 & UINT64_C(0x00000000000000FF)) << 56);
-      entered = 1;
+// Converts two consecutive characters in the input string into a
+// number, interpreting the string as a hexadecimal number, starting
+// at the specified position.
+unsigned char StrToHex(const string & input, unsigned int position) {
+   unsigned char retval = 0x00;
+   unsigned int temp;
+
+   if (input.length() >= (position + 2)) {
+      sscanf(input.substr(position, 2).c_str(), "%x", &temp);
+      retval = (unsigned char) temp;
    } // if
-
-   // If neither of the above methods of entry was used, use prompted
-   // entry....
-   if (entered == 0) {
-      sscanf(temp, "%llx", &part1);
-      cout << "Enter a two-byte hexadecimal number for the second segment: ";
-      junk = fgets(temp, 255, stdin);
-      sscanf(temp, "%llx", &part2);
-      cout << "Enter a two-byte hexadecimal number for the third segment: ";
-      junk = fgets(temp, 255, stdin);
-      sscanf(temp, "%llx", &part3);
-      theGUID.data1 = (part3 << 48) + (part2 << 32) + part1;
-      cout << "Enter a two-byte hexadecimal number for the fourth segment: ";
-      junk = fgets(temp, 255, stdin);
-      sscanf(temp, "%llx", &part4);
-      cout << "Enter a six-byte hexadecimal number for the fifth segment: ";
-      junk = fgets(temp, 255, stdin);
-      sscanf(temp, "%llx", &part5);
-      theGUID.data2 = ((part4 & UINT64_C(0x000000000000FF00)) >> 8) +
-                      ((part4 & UINT64_C(0x00000000000000FF)) << 8) +
-                      ((part5 & UINT64_C(0x0000FF0000000000)) >> 24) +
-                      ((part5 & UINT64_C(0x000000FF00000000)) >> 8) +
-                      ((part5 & UINT64_C(0x00000000FF000000)) << 8) +
-                      ((part5 & UINT64_C(0x0000000000FF0000)) << 24) +
-                      ((part5 & UINT64_C(0x000000000000FF00)) << 40) +
-                      ((part5 & UINT64_C(0x00000000000000FF)) << 56);
-      entered = 1;
-   } // if/else
-   cout << "New GUID: " << GUIDToStr(theGUID) << "\n";
-   return theGUID;
-} // GetGUID()
+   return retval;
+} // StrToHex()
 
 // Return 1 if the CPU architecture is little endian, 0 if it's big endian....
 int IsLittleEndian(void) {
diff --git a/support.h b/support.h
index 0123ee04919eda1c4f27913fd5d8326cb2a560cc..f17b14cf7e984d310fda478df694bbd98bce6ca9 100644
--- a/support.h
+++ b/support.h
@@ -23,11 +23,6 @@
 #include <linux/fs.h>
 #endif
 
-/* #ifdef __FreeBSD__
-#define fstat64 fstat
-#define stat64 stat
-#endif */
-
 // Set this as a default
 #define SECTOR_SIZE UINT32_C(512)
 
@@ -53,20 +48,11 @@
 
 using namespace std;
 
-// a GUID
-struct GUIDData {
-   uint64_t data1;
-   uint64_t data2;
-}; // struct GUIDData
-
-// static char theFile[255];
-
 int GetNumber(int low, int high, int def, const string & prompt);
 char GetYN(void);
 uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, const string & prompt);
 string BytesToSI(uint64_t size);
-string GUIDToStr(struct GUIDData theGUID);
-GUIDData GetGUID(void);
+unsigned char StrToHex(const string & input, unsigned int position);
 int IsLittleEndian(void); // Returns 1 if CPU is little-endian, 0 if it's big-endian
 void ReverseBytes(void* theValue, int numBytes); // Reverses byte-order of theValue
 uint64_t PowerOf2(int value);