NTMSAPI.CPP

/* 
* This is a part of the Microsoft Source Code Samples.
* Copyright 1996 - 1998 Microsoft Corporation.
* All rights reserved.
*
*This sample code shows the usage of some portions
*of the NTMS API.
*
*Return codes are, for the most part, not checked in
*this code. See the Programmer's reference for error
*return information.
*
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
* PARTICULAR PURPOSE.
*
* Copyright 1997 - 1998 Microsoft Corporation. All Rights Reserved. *
*/
#include <stdio.h>
#include <windows.h>
#include <iostream.h>
#include "NtmsApi.h"
#include "NtmsApiLabel.h"

#define NO_CONTAINERNULL
#define SIZE_FOR_FIRST_TRY5
#define NULL_PARTID((LPNTMS_NULLGUID)0)
#define ALLOCATE_WAIT0
#defineMOUNT_WAITINFINITE
#defineREQUESTING_ONE_MOUNT1
#define REQUESTING_ONE_DISMOUNTREQUESTING_ONE_MOUNT
#define LABEL_BUFFER_SIZE1024


void writeOmid(HANDLE, BYTE *, DWORD *);
void persistPoolID(NTMS_GUID);
NTMS_GUID recallPoolID();
void persistMediaID(NTMS_GUID);
NTMS_GUID recallMediaID();





// Find the first online library
bool
findLibrary( HANDLE hSession, NTMS_GUID &gLibID, DWORD &dwRetCode )
{
DWORD dwSize, i;
NTMS_GUID *gLibList = NULL;
NTMS_OBJECTINFORMATION oiLibraryInfo;


// Enumerate the libraries
dwSize = SIZE_FOR_FIRST_TRY;
for(;;)
{
if(gLibList != NULL)
free(gLibList);
gLibList = (LPNTMS_GUID)malloc(dwSize*sizeof(NTMS_GUID));

dwRetCode = EnumerateNtmsObject(hSession,
NO_CONTAINER,
gLibList,
&dwSize,
NTMS_LIBRARY,
0);

if(dwRetCode == ERROR_INSUFFICIENT_BUFFER) continue;
if(dwRetCode == ERROR_SUCCESS) break;
free(gLibList);
return(false);
}


// Find the first on-line library
oiLibraryInfo.dwSize = sizeof(oiLibraryInfo);
oiLibraryInfo.dwType = NTMS_LIBRARY;
for(i=0; i < dwSize; ++i)
{
dwRetCode = GetNtmsObjectInformation( hSession,
&(gLibList[i]),
&oiLibraryInfo);
if(oiLibraryInfo.Info.Library.LibraryType == NTMS_LIBRARYTYPE_ONLINE)
{
gLibID = gLibList[i];
free(gLibList);
return(true);
}
}


dwRetCode = ERROR_NOT_FOUND;
free(gLibList);
return (false);
}


// Find the first rewritable media type supported by this library
bool
findMediaType( HANDLE hSession, NTMS_GUID &gMediaID, DWORD &dwRetCode )
{
DWORD dwSize, i;
bool bRetCode;
NTMS_GUID *gTypeList = NULL;
NTMS_GUID gLib;
NTMS_OBJECTINFORMATION oiMediaTypeInfo;


// Get the GUID for the library
if((bRetCode = findLibrary(hSession, gLib, dwRetCode)) == false)
return(false);


// Get the list of media type GUIDS in the library
dwSize = SIZE_FOR_FIRST_TRY;
for(;;)
{
if(gTypeList != NULL)
free(gTypeList);
gTypeList = (LPNTMS_GUID)malloc(dwSize*sizeof(NTMS_GUID));

dwRetCode = EnumerateNtmsObject(hSession,
&gLib,
gTypeList,
&dwSize,
NTMS_MEDIA_TYPE,
0);

if(dwRetCode == ERROR_INSUFFICIENT_BUFFER) continue;
if(dwRetCode == ERROR_SUCCESS) break;
free(gTypeList);
return (false);
}


// Go through the guid list and find a rewritable media type
oiMediaTypeInfo.dwSize = sizeof(oiMediaTypeInfo);
oiMediaTypeInfo.dwType = NTMS_MEDIA_TYPE;
for (i=0; i < dwSize; ++i)
{
dwRetCode = GetNtmsObjectInformation( hSession,
&(gTypeList[i]),
&oiMediaTypeInfo);
if(oiMediaTypeInfo.Info.MediaType.ReadWriteCharacteristics == NTMS_MEDIARW_REWRITABLE)
{
gMediaID = gTypeList[i];
free(gTypeList);
return (true);
}
}


dwRetCode = ERROR_NOT_FOUND;
free(gTypeList);
return (false);

}


// Find the import media pool
bool
findImportPool( HANDLE hSession, NTMS_GUID &gIpID, DWORD &dwRetCode )
{
DWORD dwSize, i;
NTMS_GUID *gPoolList = NULL, gTlPool, gMediaType;
NTMS_OBJECTINFORMATION oiMediaPoolInfo;
bool bRetCode;


// Get the GUID of the media type we're interested in
if((bRetCode = findMediaType(hSession, gMediaType, dwRetCode)) == false)
return(false);


// Get the list of pool GUIDS in the library
dwSize = SIZE_FOR_FIRST_TRY;
for(;;)
{
if(gPoolList != NULL)
free(gPoolList);
gPoolList = (LPNTMS_GUID)malloc(dwSize*sizeof(NTMS_GUID));

dwRetCode = EnumerateNtmsObject(hSession,
NULL,
gPoolList,
&dwSize,
NTMS_MEDIA_POOL,
0);

if(dwRetCode == ERROR_INSUFFICIENT_BUFFER) continue;
if(dwRetCode == ERROR_SUCCESS) break;
free(gPoolList);
return (false);
}


// Go through the guid list and find the top level import pool
oiMediaPoolInfo.dwSize = sizeof(oiMediaPoolInfo);
oiMediaPoolInfo.dwType = NTMS_MEDIA_POOL;
for (i=0; i < dwSize; ++i)
{
dwRetCode = GetNtmsObjectInformation( hSession,
&(gPoolList[i]),
&oiMediaPoolInfo);
if(oiMediaPoolInfo.Info.MediaPool.PoolType == NTMS_POOLTYPE_IMPORT)
{
gTlPool = gPoolList[i];
break;
}
}
if(i == dwSize)
{
dwRetCode = ERROR_NOT_FOUND;
free(gPoolList);
return(false);
}


// Now we need to find the media-specific pool beneath the top level pool,
// so get the list of pool GUIDS in the top level import pool
for(;;)
{
dwRetCode = EnumerateNtmsObject(hSession,
&gTlPool,
gPoolList,
&dwSize,
NTMS_MEDIA_POOL,
0);

if(dwRetCode == ERROR_INSUFFICIENT_BUFFER)
{
free(gPoolList);
gPoolList = (LPNTMS_GUID)malloc(dwSize*sizeof(NTMS_GUID));
continue;
}
if(dwRetCode == ERROR_SUCCESS) break;
free(gPoolList);
return (false);
}


// Go through the guid list and find the proper subpool
oiMediaPoolInfo.dwSize = sizeof(oiMediaPoolInfo);
oiMediaPoolInfo.dwType = NTMS_MEDIA_POOL;
for (i=0; i < dwSize; ++i)
{
dwRetCode = GetNtmsObjectInformation( hSession,
&(gPoolList[i]),
&oiMediaPoolInfo);
if(oiMediaPoolInfo.Info.MediaPool.MediaType == gMediaType)
{
gIpID = gPoolList[i];
free(gPoolList);
return (true);
}
}


dwRetCode = ERROR_NOT_FOUND;
free(gPoolList);
return (false);

}


void
UseCase1()
{
HANDLE hSession;
DWORD dwRetCode;
bool bRetCode;
NTMS_GUID gMediaType;
NTMS_GUID gMediaPool;
NTMS_OBJECTINFORMATION oiInfoBuffer;


// Start an NTMS session
hSession = OpenNtmsSession ("", "ApiSampleApp", 0);
if(hSession == INVALID_HANDLE_VALUE)
dwRetCode = GetLastError();


// Get a GUID for a read/write media type
if((bRetCode = findMediaType(hSession, gMediaType, dwRetCode)) == false)
return;


// Create a pool for this app, returns a GUID
dwRetCode = CreateNtmsMediaPool( hSession,
"API_Sample_Pool",
&gMediaType,
NTMS_OPEN_ALWAYS,
NULL,
&gMediaPool);


// Set this new pool to automatically draw media from the scratch pool
// when allocating by first reading the info associated with the
// pool GUID, changing the "allocate from scratch" bit and then setting
// the pool info
oiInfoBuffer.dwSize = sizeof(oiInfoBuffer);
oiInfoBuffer.dwType = NTMS_MEDIA_POOL;
dwRetCode = GetNtmsObjectInformation( hSession,
&gMediaPool,
&oiInfoBuffer);

oiInfoBuffer.Info.MediaPool.AllocationPolicy =
NTMS_ALLOCATE_FROMSCRATCH;

dwRetCode = SetNtmsObjectInformation (hSession,
&gMediaPool,
&oiInfoBuffer);


// Remember the pool GUID for future use
persistPoolID(gMediaPool);


// That's all for this scenario
CloseNtmsSession(hSession);
}


void
UseCase2()
{
HANDLE hSession, hDrive;
DWORD dwRetCode, labelBytesWritten = LABEL_BUFFER_SIZE;
NTMS_GUID gPoolID, gMediaID, gDriveID;
NTMS_OBJECTINFORMATION oiDriveInfo;
BYTE labelBuffer[LABEL_BUFFER_SIZE];


// Start an NTMS session
hSession = OpenNtmsSession ("", "DemoApp", 0) ;
if(hSession == INVALID_HANDLE_VALUE)
dwRetCode = GetLastError();


// We need to write some data, but don't have a piece of
// media to write it to.
//
// Get a piece of media to use and remember the guid
gPoolID = recallPoolID();
dwRetCode = AllocateNtmsMedia(hSession,
&gPoolID,
NULL,
&gMediaID,
NTMS_ALLOCATE_NEW,
ALLOCATE_WAIT);
persistMediaID(gMediaID);


// Mount the piece of media in a drive, returns a drive GUID
dwRetCode = MountNtmsMedia(hSession,
&gMediaID,
&gDriveID,
REQUESTING_ONE_MOUNT,
NTMS_MOUNT_ERROR_NOT_AVAILABLE,
NTMS_PRIORITY_NORMAL,
MOUNT_WAIT);


// Open the drive the media is in
oiDriveInfo.dwSize = sizeof(oiDriveInfo);
oiDriveInfo.dwType = NTMS_DRIVE;
dwRetCode = GetNtmsObjectInformation(hSession,
&gDriveID,
&oiDriveInfo);

hDrive = CreateFile(oiDriveInfo.Info.Drive.szDeviceName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);


// Write the OMID and tell NTMS
writeOmid(hDrive, labelBuffer, &labelBytesWritten);
dwRetCode = UpdateNtmsOmidInfo(hSession,
&gMediaID,
NTMS_OMID_TYPE_RAW_LABEL,
labelBytesWritten,
(void *)labelBuffer);


// Write data via Win32 API calls, close device when done.

// write, write, write, ...
CloseHandle(hDrive);


// Dismount the media
dwRetCode = DismountNtmsMedia( hSession,
&gMediaID,
REQUESTING_ONE_DISMOUNT,
0);


// That's all for this scenario
CloseNtmsSession(hSession);
}



void
UseCase3()
{
HANDLE hSession, hDrive;
DWORD dwRetCode, labelBytesWritten = LABEL_BUFFER_SIZE;
NTMS_GUID gMediaID, gDriveID;
NTMS_OBJECTINFORMATION oiDriveInfo;

// Start an NTMS session
hSession = OpenNtmsSession ("", "DemoApp", 0);
if(hSession == INVALID_HANDLE_VALUE)
dwRetCode = GetLastError();


// Mount the piece of media in a drive
gMediaID = recallMediaID();
dwRetCode = MountNtmsMedia(hSession,
&gMediaID,
&gDriveID,
REQUESTING_ONE_MOUNT,
NTMS_MOUNT_ERROR_NOT_AVAILABLE,
NTMS_PRIORITY_NORMAL,
MOUNT_WAIT);


// Open the drive the media is in
oiDriveInfo.dwSize = sizeof(oiDriveInfo);
oiDriveInfo.dwType = NTMS_DRIVE;
dwRetCode = GetNtmsObjectInformation(hSession,
&gDriveID,
&oiDriveInfo);

hDrive = CreateFile(oiDriveInfo.Info.Drive.szDeviceName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);



// Read (and/or write) data via Win32 API calls, Close device when done.

// read, read, read, ...
CloseHandle(hDrive);


// Dismount the media
dwRetCode = DismountNtmsMedia( hSession,
&gMediaID,
REQUESTING_ONE_DISMOUNT,
0);


// We've determined that we no longer need this piece of media
// so deallocate it.
dwRetCode = DeallocateNtmsMedia( hSession,
&gMediaID,
0);


// That's all for this scenario
CloseNtmsSession(hSession);
}



void
UseCase4()
{
HANDLE hSession;
DWORD dwRetCode, i;
NTMS_GUID gIpID, *gPartitionList = NULL, gPoolID;
bool bRetCode;
DWORD dwSize;
NTMS_OBJECTINFORMATION oiPartitionInfo;


// Start an NTMS session
hSession = OpenNtmsSession ("", "DemoApp", 0);
if(hSession == INVALID_HANDLE_VALUE)
dwRetCode = GetLastError();


// The method used here to find media in the import pool is actually the
// harder of two ways to do it. The easier way is to enumerate all the
// partitions in NTMS (instead of the media-specific import pool and check
// for ones with the partstate set to PARTSTATE_IMPORT. This way is more
// efficient and gives you a flavor for traversing nested media pools (which
// is done in findImportPool).


// Get the GUID of the media-specific import pool
if( (bRetCode = findImportPool(hSession, gIpID, dwRetCode)) == false)
return;


// Enumerate all the partitions in the media-specific import pool
dwSize = SIZE_FOR_FIRST_TRY;
for(;;)
{
if(gPartitionList != NULL)
free(gPartitionList);
gPartitionList = (LPNTMS_GUID)malloc(dwSize*sizeof(NTMS_GUID));

dwRetCode = EnumerateNtmsObject(hSession,
&gIpID,
gPartitionList,
&dwSize,
NTMS_PARTITION,
0);

if(dwRetCode == ERROR_INSUFFICIENT_BUFFER) continue;
if(dwRetCode == ERROR_SUCCESS) break;
return;
}


gPoolID = recallPoolID();

// Look at the label on each piece of media & move it
// to this app's pool if it was written by this
// app.
oiPartitionInfo.dwSize = sizeof(oiPartitionInfo);
oiPartitionInfo.dwType = NTMS_PARTITION;
for (i=0; i < dwSize; ++i)
{
dwRetCode = GetNtmsObjectInformation( hSession,
&(gPartitionList[i]),
&oiPartitionInfo);
if((dwRetCode = strncmp(oiPartitionInfo.Info.Partition.szOmidLabelType,
"Microsoft NTMS API Demo", 23)) == 0)
{
MoveToNtmsMediaPool(hSession,
&(oiPartitionInfo.Info.Partition.PhysicalMedia), &gPoolID);
}
}


// That's all for this scenario
CloseNtmsSession(hSession);
}

void
main()
{


UseCase1();// Stuff done during app initialization


UseCase2(); // Typical stuff done during app operations
//including media allocation


UseCase3(); // More typical stuff done during app operations
//including media deallocation


UseCase4();// Find each piece of media in the import pool that
//belong to this app and move it to this
//app's media pool



}