/**
 * volser.cpp : jni methods in nativevolser.dll
 * Must have previously generated the volser.h file with
 * javah. Get a clean compile, then
 * javah.exe -jni -o volser.h com.mindprod.volser.Volser
 * You must have
 * J:\Program Files\Java\jdk1.6.0_10\include\
 * and
 * J:\Program Files\Java\jdk1.6.0_10\include\win32
 * in the include list e.g.
 * in Tools | options  | Projects and Solutions | VC++ directories | include files
 * or
 * in tools | options | directories | include
 * For project as a whole:
 * In project | settings | general | no MFC
 * In project | settings | link | output filename | should end in DLL
 *
 * For Visual C++ Express 9,
 * Configure project as a DLL library.
 * Include the following in the /I section when you first define the project, not forced includes.
 * E:\Program Files\Java\jdk1.6.0_10\include;E:\Program Files\Java\jdk1.6.0_10\include\win32
 * In project | C++ | code generation | set the runtime library /MT option to statically link (i.e. include system
 * run time code in the DLL rather than link to the runtime.  Alternatively, you must
 * install the C++ runtime on all clients, available from 
 * http://www.microsoft.com/downloads/details.aspx?familyid=9B2DA534-3E03-4391-8A4D-074B9F2BC1BF&displaylang=en\
 *
 * You can edit them with project properties, C++, additional C++ Include directories.
 *
 * copyright (c) 2007-2009 Roedy Green Canadian Mind Products
 */
#define UNICODE
#define _UNICODE

#include <Windows.h>
#include <WinBase.h>
#include <String.h>

// JNI prototypes generated by javah
#include "volser.h"

/*
 * Class:     com_mindprod_volser_Volser
 * Method:    getVolser
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jint JNICALL Java_com_mindprod_volser_Volser_getVolser
   (JNIEnv * env, jclass volserClass, jstring rootPathName)
   {
   // 16-bit char RootPathName without terminating null, e.g. "C:\"
   const wchar_t * lpRootPathName16 = ( wchar_t *)  env->GetStringChars( rootPathName, NULL /* don't need copy notification */ );
   if ( lpRootPathName16 == NULL )
      {
      return 0;
      }
   jsize rootLen = env->GetStringLength( rootPathName );

   // 16-bit char RootPathName with terminating null
   wchar_t * lpRootPathName16_0 =  new wchar_t[ rootLen+1 ];

   // copy to apply trailing null
   errno_t err = wcsncpy_s(
                          lpRootPathName16_0 /* dest */,
                          rootLen+1 /* dest length */,
                          lpRootPathName16 /* src */,
                          rootLen /* chars to copy */
                          );

   // no longer need handle to Java string, since we have a copy.
   env->ReleaseStringChars( rootPathName, (const jchar *) lpRootPathName16 );

   if ( err )
      {
      delete lpRootPathName16_0;
      return 0;
      }

   LPTSTR lpVolumeNameBuffer =  new TCHAR[ MAX_PATH+1 ];

   DWORD volumeSerialNumber;

   BOOL ok = GetVolumeInformation(
                                 (LPCTSTR)lpRootPathName16_0,
                                 lpVolumeNameBuffer,
                                 MAX_PATH+1 /* nVolumeNameSize */,
                                 &volumeSerialNumber,
                                 NULL /*lpMaximumComponentLength */,
                                 NULL /* lpFileSystemFlags */,
                                 NULL /* lpFileSystemNameBuffer */,
                                 0 /* nFileSystemNameSize */
                                 );

   delete lpRootPathName16_0;
   delete lpVolumeNameBuffer;

   return ok ? volumeSerialNumber : 0 ;
   }

// not class, so no final }