MSSQLWIKI

Karthick P.K on SQL Server

Archive for the ‘Programming’ Category

Multi Threaded OVELAPPED and Nonbuffered I/O Example

Posted by Karthick P.K on March 4, 2012

How to Read file using Multiple threads OVERLAPPED and Nonbuffered I/O

Multithreaded Overlapped I/O and Nonbuffered I/O example

Nonbuffered I/O :Allows application to bypass the Windows cache manager or disable system caching of data being read from or written to the file .So there is no intermediate buffer or cache and gives direct control over data I/O buffering to application.

Things to remember:

1. When we use non buffered I/O (FILE_FLAG_NO_BUFFERING in createfile) reads and writes has to be in multiple of bytes per sector.

2. GetDiskFreeSpace-Retrieves information about the specified disk, including Bytes per sector (dwBytesPerSector) of disk.

3. When using non buffered I/O (FILE_FLAG_NO_BUFFERING) file offset in the OVERLAPPED structure in Readfile/Writefile if specified, must be number of bytes that is an integer multiple of the Bytes per sector

4. Buffers used for read and write operations should be physical sector-aligned, which means aligned on addresses in memory that are integer multiples of Bytes per sector.

5. GetFileSizeEx-Retrieves the size of the specified file. When multiple threads are used to read or write file. Each thread needs to have its own overlapped structure and Event has to be created for hEvent member of each overlapped structure.

If the hEvent member of the OVERLAPPED structure is NULL, the system uses the state of the hFile handle to signal when the operation has been completed. This will cause confusion when multiple threads are using same file handle to read or write file.

It is safer to use an event object because of the confusion that can occur when multiple simultaneous overlapped operations are performed on the same file, named pipe, or communications device.In this situation, there is no way to know which operation caused the object’s state to be signaled.

#include "windows.h"
#include "stdlib.h"
#include <windows.h>
#include <string>
#include <winbase.h>
#include <iostream>
using namespace std;
#include <psapi.h>
#pragma comment(lib,"psapi.lib")
#include <time.h>

#define ThreadPerProc 1 //If you want more than 1 thread per processor increase this value.

int Dootherwork();

struct SUreadfile
{
int x;
DWORDLONG  dwOffset;
DWORDLONG  dwTotalBytespostedNOffset;

};
  SUreadfile *PSUreadfile;
  int Ureadfile(SUreadfile *PSUreadfile1);

  int  x=0;
  int  i=0;
  SYSTEM_INFO si;
  DWORD dwSectorsPerCluster;
  DWORD dwBytesPerSector;
  DWORD dwNumberOfFreeClusters;
  DWORD dwTotalNumberOfClusters;

  //
  LONGLONG BuffSize=0;
  OVERLAPPED *iAIO=NULL;
  DWORDLONG  dwTotalBytesposted=0;
  DWORDLONG  dwTotalBytespostedwithinoffset=0;
  HANDLE hIFile;
  HANDLE hOFile;
  HANDLE *hEvent;
 char dateStr [9];
 char timeStr [9];

int main(int argc, char* argv[])
{

  _strdate( dateStr);
  _strtime( timeStr );
  printf("\n Date:%s\t", dateStr);
  printf("Time is%s\t", timeStr);
  if (argc<3)
  {
		printf("Usage is: To stimulate asynch I/O. Accept two parameters Source file and Destination file");
		return 1;
  }

 //Open source file
 hIFile=CreateFile((LPCSTR)argv[1],GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL
                           | FILE_FLAG_OVERLAPPED
                           | FILE_FLAG_NO_BUFFERING
                           ,NULL); //FILE_FLAG_OVERLAPPED  - to process input or output asynchronously
								   //FILE_FLAG_NO_BUFFERING-The file or device is being opened with no system caching for data reads and writes.
 if (INVALID_HANDLE_VALUE==hIFile)
		  {
			printf("Unable to open file %s.  Error=%d\n",argv[1], GetLastError());
			return 1;
		  }
//Create destination file
 hOFile=CreateFile((LPCSTR)argv[2],GENERIC_WRITE,FILE_SHARE_READ,NULL,CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL);
	 if (INVALID_HANDLE_VALUE==hOFile)
		  {
			printf("Unable to create file %s.  Error=%d\n",argv[1], GetLastError());
			return 1;
		  }

//GetSystemInfo- Retrieves information about the current system. Output is pointer to SYSTEM_INFO structure
 GetSystemInfo(&si);
 /*GetDiskFreeSpace-Retrieves information about the specified disk, including dwBytesPerSector . When using FILE_FLAG_NO_BUFFERING
 file offset in the OVERLAPPED structure and nNumberOfBytesToRead in Readfile
 if specified, must be   number of bytes that is an integer multiple of the dwBytesPerSector*/
 GetDiskFreeSpace(NULL,&dwSectorsPerCluster,&dwBytesPerSector,&dwNumberOfFreeClusters,&dwTotalNumberOfClusters);
 LARGE_INTEGER *fsize;
 fsize =new LARGE_INTEGER;

 dwBytesPerSector=dwBytesPerSector*4; //for larger files if you want to read data greater then dwBytesPerSector in one shot increase the size of dwBytesPerSector.

//GetFileSizeEx-Retrieves the size of the specified file.

 GetFileSizeEx (hIFile,fsize);
 if (fsize->QuadPart==0)
      {
      printf("\nUnable to get the size of file. Error:%d ",GetLastError());
      return 1;
      }
    else
      {
          printf("\nFile size is: %lld Bytes",fsize->QuadPart);

		  if (fsize->QuadPart > dwBytesPerSector)
          {
			  /*Later in this program we create 1 thread per processor and read the files parellely.
			  Below logic is used to calculate the bytes each thread will read
			  remember when we use non buffered I/O (FILE_FLAG_NO_BUFFERING) reads has to be in multiple of bytes per sector. So no of bytes each thread
			  will read has to be rouded to   bytes per sector
			  */

			  BuffSize=  fsize->QuadPart +  ( (si.dwNumberOfProcessors*dwBytesPerSector)  -  (fsize->QuadPart % (si.dwNumberOfProcessors*dwBytesPerSector))  );
			  BuffSize=BuffSize/si.dwNumberOfProcessors;
          }
          else
          {
              BuffSize=fsize->QuadPart; //If the file size is less then dwBytesPerSector there is no nead to create multiple threads
          }
      }

	iAIO =new OVERLAPPED[si.dwNumberOfProcessors*ThreadPerProc];// Create overlapped structure for each thread
	HANDLE *h;
    h = new HANDLE[(si.dwNumberOfProcessors*ThreadPerProc)]; // Pointer  array to hold thread handles
	PSUreadfile= new SUreadfile[256];
	int OffsetHigh=0;
	hEvent=new HANDLE[(si.dwNumberOfProcessors*ThreadPerProc)];
	/*Create event for hEvent member of each overlapped structure If the hEvent member of the OVERLAPPED structure is NULL, the system
	uses the state of the hFile handle to signal when the operation has been completed.
	This is will cause confusion when multiple threads are using same file handle to read or write file.
	It is safer to use an event object because of the
	confusion that can occur when multiple simultaneous overlapped operations are performed on the same file, named pipe, or communications device.
	In this situation, there is no way to know which operation caused the object's state to be signaled.*/

	//Create threads and and assign the starting file offset to each thread for read operation
	for ( i=0;i<(si.dwNumberOfProcessors*ThreadPerProc);i++)
			{
			ZeroMemory(&PSUreadfile[i],sizeof(PSUreadfile[i]));
 			PSUreadfile[i].x=i;
			ZeroMemory (&iAIO[i],sizeof(iAIO[i]));
			iAIO[i].Internal=0;
			iAIO[i].InternalHigh=0;
			iAIO[i].Offset=0;
			iAIO[i].OffsetHigh=0;
			iAIO[i].Pointer=0;
			iAIO[i].Offset= 0;
			PSUreadfile[i].dwOffset=dwTotalBytesposted;
			hEvent[i] = CreateEvent(NULL, TRUE, FALSE, NULL);
			if(hEvent)
			{
			 iAIO[i].hEvent = hEvent[i];
			}
			 else
			{
			 printf("\nCreate event failed with error:%d",GetLastError());
			}

			h[i]=CreateThread(0,0,(LPTHREAD_START_ROUTINE  )Ureadfile,(LPVOID)&PSUreadfile[i],  0,  NULL);

			if (!h[i])
			{
			printf("Thread creation failure :", GetLastError());
			}

			dwTotalBytesposted=dwTotalBytesposted+BuffSize;

		}

	WaitForMultipleObjects((si.dwNumberOfProcessors), h,TRUE,INFINITE);  // Wait for all the threads to complete
  _strdate( dateStr);
  _strtime( timeStr );
  printf("\n Date:%s\t", dateStr);
  printf("Time is%s\t", timeStr);

}

int Ureadfile(SUreadfile *PSUreadfile1)
{

	int z=PSUreadfile1->x;
	SIZE_T dwSize=dwBytesPerSector;
	if (PSUreadfile[z].dwOffset>MAXDWORD)
	{
		iAIO[z].Offset=(PSUreadfile[z].dwOffset%MAXDWORD)-(PSUreadfile[z].dwOffset/MAXDWORD); //Offset start from zero
		iAIO[z].OffsetHigh=PSUreadfile[z].dwOffset/MAXDWORD;

	/*iAIO[z].Offset (Offset of overlapped structure) is the low-order portion of the file position at which to start the I/O request.
	Data type of Offset is DWORD so the 	maximum size is 2^32 (4294967296-1). If you want to read the file from offset
	which is greater than 4294967296 bytes increase the OffsetHigh */
	}
	else
	{
	iAIO[z].Offset=PSUreadfile[z].dwOffset;
	}

	DWORD dwBytesRead=0;
	LONGLONG dwTotalBytesRead=0;
	BOOL	RF;
	BOOL	WF;
	wchar_t *IBuffer = (wchar_t *) VirtualAlloc(NULL,  dwSize, MEM_RESERVE| MEM_COMMIT,PAGE_READWRITE);

	 while (BuffSize>dwTotalBytesRead)
	{

		RF=0;

		RF=ReadFile(hIFile,IBuffer,dwSize, &dwBytesRead,&iAIO[z]); // pass  a pointer to an OVERLAPPED structure (iAIO)

		if ((RF==0) && GetLastError()==997)      //ERROR_IO_PENDING                 997L
        {

			/*bWait parameter of GetOverlappedResult can be set to TRUE or FALSE.
			If this parameter is TRUE, and the Internal member of the lpOverlapped structure is STATUS_PENDING, the function
			does not return until the operation has been completed. If this parameter is FALSE and the operation is still pending, the function
			returns FALSE and the GetLastError function returns ERROR_IO_INCOMPLETE	*/
            while( !GetOverlappedResult( hIFile,&iAIO[z],&dwBytesRead,TRUE))
                {

                    if (GetLastError()==996)//ERROR_IO_INCOMPLETE  (Not signaled)            996L
                    {
                    printf("\nI/O pending: %d .",GetLastError());
                    //Dootherwork();
					/*If the bWait parameter of GetOverlappedResult is set to false thread can do other work while the I/O is progressing.
					Change the bWait parameter to FALSE in GetOverlappedResult and un-comment Dootherwork function above to stimulate clean overlapped I/O.
					*/
                    }
                    else if  (GetLastError()==38) //ERROR_HANDLE_EOF                 38L
                    {
                    printf("\nEnd of file reached.");
                    break;
                    }
                    else
                    {
                    printf("GetOverlappedResult failed with error:%d,Offset:%d",GetLastError(),iAIO[z].Offset);
                    break;
                    }

                }

        }
        else if ((RF==0)  && GetLastError()!=997 &&   GetLastError()!=38 )
        {
            printf ("\nError reading file :%d offset-%d",GetLastError(),iAIO[z].Offset);
            return 0;
        }

		else if ((RF==0)  && GetLastError()==38 )
        {
            printf ("\nEnd of file reached file :%d offset:%d",GetLastError(),iAIO[z].Offset);
            return 0;
        }

		WF= WriteFile(hOFile,IBuffer,iAIO[z].InternalHigh,NULL,&iAIO[z]);  //Write the buffers which we read to new file.

		if (!WF)
		 {
			printf("\nWrite file operation failed. Error:%d",GetLastError());
		 }

	    dwTotalBytesRead=dwTotalBytesRead + iAIO[z].InternalHigh;

		//Increase the offset if we hit the max DWORD limitation
		if (iAIO[z].Offset+iAIO[z].InternalHigh > (MAXDWORD* (iAIO[z].OffsetHigh+1)))
		{
printf("\nThread Id-%d completed ReadFile operation from %lld till  %lld of %lld bytes",z,(iAIO[z].Offset-dwTotalBytesRead-iAIO[z].InternalHigh),iAIO[z].Offset+iAIO[z].InternalHigh,dwTotalBytesRead);
					iAIO[z].OffsetHigh++;
			        iAIO[z].Offset= (iAIO[z].Offset + iAIO[z].InternalHigh-MAXDWORD-iAIO[z].OffsetHigh); //Offset starts from zero
		}
		else
		{
		iAIO[z].Offset=iAIO[z].Offset+iAIO[z].InternalHigh;
		}

		if (dwSize >iAIO[z].InternalHigh)
		{
		  printf("\nEnd of file reached %ld-%ld",iAIO[z].InternalHigh,dwSize);
		 break;
		}

	}

	printf("\nThread Id:%d completed ReadFile operation  of %lld bytes",z,dwTotalBytesRead);
  return 1;
}

int Dootherwork()
{

	x=x+1;
	printf("\nWe are doing other work when overlapped I/O read is in progress-%d -Sleeping for 1 Milli second",x);
	Sleep(1);
	return 0;
}

Posted in Programming, SQL Server I/O | Tagged: , , , , | 6 Comments »

Asynchronous I/O example

Posted by Karthick P.K on February 15, 2012

How to Read file using asynchronous read operations – Overlapped I/O example

Asynchronous I/O facility in windows allows an application to initiate an I/O operation and continue other operation’s while I/O completes. This will improve the performance of an application because it allows the application to do multiple operations at once.

1. FILE_FLAG_OVERLAPPED switch is used in CreateFile to do Asynchronous I/O operation.

2. OVERLAPPED structure – when we call ReadFile/ReadFileEx or WriteFile/WriteFileEx we pass Pointer to an OVERLAPPED structure that specifies the starting position of I/O operation.

3. GetOverlappedResult – Status of a pending asynchronous operation can be checked using HasOverlappedIoCompleted or GetOverlappedResult Win32 API functions. bWait parameter in GetOverlappedResult can be set to true to wait infinitely till the Asynchronous I/O operation completes.

4. Createevent – Used to create an event object to assign for hEvent member of the OVERLAPPED structure passed into ReadFile/WriteFile and GetOverlappedResult. When multiple Asynchronous I/O happens   in parallel then each Asynch I/O must have its own OVERLAPPED structure

#include "windows.h"
#include "stdlib.h"
#include <windows.h>
#include <string>
#include <winbase.h>
#include <iostream>
using namespace std;
#include <psapi.h>
#pragma comment(lib,"psapi.lib")
#define BUF_SIZE 8192*100*100 // BuffSize for read file
int  x=0; 
int Dootherwork();

int main(int argc, char* argv[])
{
  if (argc<2)
  {
        printf("Usage is: To stimulate asynch I/O");
        return 1;
  }

HANDLE hIFile=CreateFile((LPCSTR)argv[1],GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL); //FILE_FLAG_OVERLAPPED-To process input or output asynchronously
    
 if (INVALID_HANDLE_VALUE==hIFile) 
          {
            printf("Unable to open file %s.  Error=%d\n",argv[1], GetLastError());
            return 1;
          }

     OVERLAPPED iAIO;  
     ZeroMemory (&iAIO,sizeof(iAIO));

      DWORD dwBytesRead=0;
      DWORD dwTotalBytesRead=0;
      BOOL RF;
      BOOL OLR=0;
      DWORD *lpFileSizeHigh;
      DWORD rfs; 
      
      lpFileSizeHigh = new DWORD;
      LARGE_INTEGER *fsize;
      fsize =new LARGE_INTEGER;
      rfs=GetFileSizeEx (hIFile,fsize);
      LONGLONG BuffSize=0;
      HANDLE hEvent;
      hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
      if(hEvent)
      {
      iAIO.hEvent = hEvent; 
      }
      else
      {
      printf("\nCreate event failed with error:%d",GetLastError());
      }
  
    if (fsize->QuadPart==0)
      {
      printf("\nUnable to get the size of file. Error:%d ",GetLastError());
      return 1;
      }
    else 
      { 
          printf("\nFile size is: %lld Bytes",fsize->QuadPart);
          if (fsize->QuadPart > BUF_SIZE)
          {
          BuffSize=BUF_SIZE;
          }
          else
          {
          BuffSize=fsize->QuadPart;
          }
      }
    wchar_t *IBuffer = (wchar_t *)HeapAlloc(GetProcessHeap(),  HEAP_ZERO_MEMORY,  BuffSize);
  

  while (fsize->QuadPart>dwTotalBytesRead)
  {

      SetLastError(0);
      
      RF=ReadFile(hIFile,IBuffer,BuffSize, NULL,&iAIO); // pass  a pointer to an OVERLAPPED structure (iAIO)
        
      if ((RF==0) && GetLastError()==997)      //ERROR_IO_PENDING                 997L   
        {
            printf ("\nAsynch readfile started. I can do other operations now");
             
            while( !GetOverlappedResult( hIFile,&iAIO,&dwBytesRead,FALSE))
                {
                    if (GetLastError()==996)//ERROR_IO_INCOMPLETE  (Not signaled)            996L 
                    {
                    printf("\nI/O pending: %d .",GetLastError());
                    Dootherwork();
                    }
                    else if  (GetLastError()==38) //ERROR_HANDLE_EOF                 38L
                    { 
                    printf("\nEnd of file reached.");
                    break;
                    } 
                    else
                    {
                    printf("GetOverlappedResult failed with error:%d",GetLastError());
                    break;
                    }

                } 
    



        }
        else if ((RF==0)  && GetLastError()!=997 )
        {
            printf ("Error reading file :%d",GetLastError());
            return 0;
        }
      
         

        dwTotalBytesRead=dwTotalBytesRead + iAIO.InternalHigh;
        iAIO.Offset=dwTotalBytesRead;
        printf("\nReadFile operation completed for %lld bytes",dwTotalBytesRead);
    
  }
  printf("\nReadFile  completed.  %d bytes read",dwTotalBytesRead);

 ResetEvent(iAIO.hEvent);
 HeapFree(GetProcessHeap(),0,IBuffer);
 CloseHandle(hEvent);

 CloseHandle(hIFile);
 return 0;
}


int Dootherwork()
{

    x=x+1;
    printf("\nWe are doing other work when overlapped I/O read is in progress-%d -Sleeping for 1000 Milli second",x);
    Sleep(1000);
    return 0;
}

 

 

Thanks

Karthick P.K

Posted in Programming, SQL Server Engine, SQL Server I/O | Tagged: , , , , , | 2 Comments »

How to Create process in c++….. CreateProcess function

Posted by Karthick P.K on December 31, 2011

 
#include <windows.h> 
#include <string> 
#include <winbase.h> 
#include <iostream> 
using namespace std;

void main()
{
    int N;    
    cout<<"Enter count for process:";
    cin>>N;

    PROCESS_INFORMATION *x;
    STARTUPINFO *startup_info;

    startup_info = new STARTUPINFO[N];
    x =new  PROCESS_INFORMATION[N]; 
    HANDLE *h;
    h = new HANDLE[N];
    for (int i=0;i<N;i++)
        {
            memset((char *)&startup_info[i], 0, sizeof(STARTUPINFO));
            startup_info[i].cb = sizeof(STARTUPINFO);
            startup_info[i].dwFlags = STARTF_USESTDHANDLES;
            startup_info[i].hStdInput = GetStdHandle(STD_INPUT_HANDLE);
            printf("\nProcess creation starting:%d",i);
            CreateProcess("c:\\windows\\notepad.exe",NULL,NULL,NULL,FALSE,0x00010000,NULL,NULL,startup_info,&x[i]);
            h[i]= x[i].hProcess;
        
        }
        
    WaitForMultipleObjects(N, h,TRUE,INFINITE);
    
    for (int i=0;i<N;i++)
        {
        CloseHandle(x[i].hProcess);
        CloseHandle(x[i].hThread);
        }

}
 
 
 
Thanks
Karthick P.K

Posted in Programming | Tagged: , | 2 Comments »

how to Open CreateFile (Createfile example)

Posted by Karthick P.K on March 10, 2011

#include <windows.h> 
#include <string> 
#include <winbase.h> 
#include <iostream> 
using namespace std;

void main()
{
    HANDLE  h;
    CHAR *filename;
 
    filename =new CHAR[2500];
    wcout<<"enter the file name:";
    cin.getline (filename,2500);
    h= CreateFile( filename,FILE_SHARE_READ,0x00000001,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
    cout<<filename;
    if (h!=INVALID_HANDLE_VALUE)
    {
    printf("File is opened");
    }
    else
    {
    printf("Unable to open or create file");
    }
    system ("pause");

}

Posted in Programming | Tagged: | 2 Comments »

How to get the current state of cluster resource?

Posted by Karthick P.K on December 9, 2010

#include <windows.h> 
#include <ClusApi.h>
#include <winbase.h> 
#include <iostream> 
using namespace std;
#pragma comment(lib,"ClusApi.lib")
#include <stdlib.h>

void main()
{
    HCLUSTER Clusterhandle=NULL; 
    HRESOURCE  ClusterRhandle=NULL; 
    LPCWSTR lpszClusterName =NULL;
    WCHAR *lpszResourceName;
    CLUSTER_RESOURCE_STATE A = ClusterResourceStateUnknown;
    lpszResourceName =new WCHAR;
    wcout<<"enter the name of cluster resource:";
    wcin.getline (lpszResourceName,256);
    Clusterhandle= OpenCluster(lpszClusterName);
    if (Clusterhandle!=NULL)
    {
    
        ClusterRhandle=OpenClusterResource(Clusterhandle,lpszResourceName);
        if (ClusterRhandle!=NULL)
        {
         printf("Got Cluster resource handle\n");
            
         A= GetClusterResourceState(ClusterRhandle,NULL,NULL,NULL,NULL);

         if (A!=ClusterResourceStateUnknown)
             {
             printf("ClusterResourceState is:%d",A);
         
              }
              else
              {
              printf("ClusterResourceState is unknowm",GetLastError());
              
              }
              
        }
        else
        {
        printf("Unable to get ClusterRhandle:%d",GetLastError());
        }
    }
    else 
    {
    printf ("unable to get handle to cluster",GetLastError());
    }
 
}

Posted in Programming, SQL Server Cluster | Tagged: , , | 1 Comment »

QueryMemoryResourceNotification & CreateMemoryResourceNotification (How SQL Server identifies low system memory on the system and respond to low system memory?)

Posted by Karthick P.K on December 2, 2010

#include <windows.h> 
#include <string> 
#include <winbase.h> 
#include <iostream> 
using namespace std;
#include <psapi.h>
#pragma comment(lib,"psapi.lib")
#include <time.h>

DWORD dwLength;
DWORD dwMemoryLoad;
ULONG_PTR dwTotalPhys;
ULONG_PTR dwAvailPhys;
ULONG_PTR dwTotalPageFile;
ULONG_PTR dwAvailPageFile;
ULONG_PTR dwTotalVirtual;
ULONG_PTR dwAvailVirtual;
int *m_pBuf; 
MEMORY_RESOURCE_NOTIFICATION_TYPE Low;
MEMORY_RESOURCE_NOTIFICATION_TYPE High;
HANDLE LMHandle;
HANDLE HMHandle;
HANDLE THandle;
int ResourceState;
int x=0;
BOOL state=1;
char dateStr [9];
char timeStr [9];


BOOL SetPrivilege(
    HANDLE hToken,          // access token handle
    LPCTSTR lpszPrivilege,  // name of privilege to enable/disable
    BOOL bEnablePrivilege   // to enable or disable privilege
    ) 
{
    TOKEN_PRIVILEGES tp;
    LUID luid;

    if ( !LookupPrivilegeValue( 
        NULL,            // lookup privilege on local system
        lpszPrivilege,   // privilege to lookup 
        &luid ) )        // receives LUID of privilege
    {
        printf("LookupPrivilegeValue error: %u\n", GetLastError() ); 
        return FALSE; 
    }

    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = luid;
    if (bEnablePrivilege)
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    else
        tp.Privileges[0].Attributes = 0;

    // Enable the privilege or disable all privileges.

    if ( !AdjustTokenPrivileges(
        hToken, 
        FALSE, 
        &tp, 
        sizeof(TOKEN_PRIVILEGES), 
        (PTOKEN_PRIVILEGES) NULL, 
        (PDWORD) NULL) )
    { 
        printf("AdjustTokenPrivileges error: %u\n", GetLastError() ); 
        return FALSE; 
    } 

    if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)

    {
        printf("The token does not have the specified privilege. \n");
        return FALSE;
    } 

    return TRUE;
}



void processmemory()

{

    FILE * pFile;
    pFile = fopen ("MemoryStatus.txt","a");
    DWORD     PID[1024];
    DWORD pBytesReturned=NULL;
    BOOL S;
    //PID= new DWORD(SIZEOF(pBytesReturned));

    S= EnumProcesses(PID,sizeof(PID), &pBytesReturned);
    BOOL x;
    HANDLE TokenHandle;
    TokenHandle=NULL;
    fprintf(pFile,"Low Memory Notification received on  %s  %s  ", dateStr,timeStr);
    x= OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&TokenHandle);

    if (x==0)
    {

        fprintf (pFile,"Unable To OpenProcessToken For current Process Error:%d",GetLastError());

    }


    if(SetPrivilege(TokenHandle, SE_DEBUG_NAME, TRUE))
    {
        fprintf (pFile,"Success");
    }
    else
    {
        fprintf (pFile,"FAILURE");
    }            



    for(int i=0;i<=pBytesReturned/sizeof(DWORD);i++)
    {
        HANDLE H;    
        fprintf (pFile,"\nProcess:%d",PID[i]);

        H= OpenProcess(PROCESS_QUERY_INFORMATION |PROCESS_VM_READ |PROCESS_ALL_ACCESS,TRUE,PID[i]);


        if (H==0)
        {
            fprintf (pFile,"Unable To Get Process Name ");
            fprintf (pFile,"Error:%d",GetLastError());
        }
        else

        {
            char   Basename[MAX_PATH];

            BOOL A=0;

            A=GetModuleBaseName(H,NULL,(LPSTR) Basename,sizeof(Basename)/sizeof(TCHAR));
            if (A==0)
            {
                fprintf (pFile,"Error:%d",GetLastError());
                fprintf (pFile,"Unable To Get ModuleBaseName ");
            }
            else
            {
                fprintf (pFile,",Process Name:%s",Basename);
            }

            PROCESS_MEMORY_COUNTERS PMC;

            GetProcessMemoryInfo(H, &PMC,sizeof(PMC));


            fprintf (pFile,",PageFaultCount:%d",PMC.PageFaultCount);
            fprintf (pFile,",PeakWorkingSetSize:%d",PMC.PeakWorkingSetSize);
            fprintf (pFile,",WorkingSetSize:%d",PMC.WorkingSetSize);
            fprintf (pFile,",QuotaPeakPagedPoolUsage:%d",PMC.QuotaPeakPagedPoolUsage);
            fprintf (pFile,",QuotaPagedPoolUsage:%d",PMC.QuotaPagedPoolUsage);
            fprintf (pFile,",QuotaPeakNonPagedPoolUsage:%d",PMC.QuotaPeakNonPagedPoolUsage);
            fprintf (pFile,",QuotaNonPagedPoolUsage:%d",PMC.QuotaNonPagedPoolUsage);
            fprintf (pFile,",PagefileUsage:%d",PMC.PagefileUsage);
            fprintf (pFile,",PeakPagefileUsage:%d",PMC.PeakPagefileUsage);

        }





    }


    PERFORMANCE_INFORMATION Perfinfo;
    GetPerformanceInfo(&Perfinfo,sizeof(Perfinfo));
    SIZE_T CommitTotal=Perfinfo.CommitTotal;

    fprintf (pFile,"\n\n\nSYSTEM PERFORMANCE INFORMATION");
    fprintf (pFile,"\nCommitTotal=%d",Perfinfo.CommitTotal);
    fprintf (pFile,"\nCommitLimit=%d",Perfinfo.CommitLimit);
    fprintf (pFile,"\nCommitPeak=%d",Perfinfo.CommitPeak);
    fprintf (pFile,"\nPhysicalTotal=%d",Perfinfo.PhysicalTotal);
    fprintf (pFile,"\nPhysicalAvailable=%d",Perfinfo.PhysicalAvailable);
    fprintf (pFile,"\nSystemCache=%d",Perfinfo.SystemCache);
    fprintf (pFile,"\nKernelTotal=%d",Perfinfo.KernelTotal);
    fprintf (pFile,"\nKernelPaged=%d",Perfinfo.KernelPaged);
    fprintf (pFile,"\nKernelNonpaged=%d",Perfinfo.KernelNonpaged);
    fprintf (pFile,"\nPageSize=%d",Perfinfo.PageSize);
    fprintf (pFile,"\nHandleCount=%d",Perfinfo.HandleCount);
    fprintf (pFile,"\nProcessCount=%d",Perfinfo.ProcessCount);
    fprintf (pFile,"\nThreadCount=%d",Perfinfo.ThreadCount);




    OSVERSIONINFOEX   OSINFO;

    OSINFO.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
    GetVersionEx((LPOSVERSIONINFOA) &OSINFO);
    fprintf (pFile,"\n\n\nWINDOWS VERSION INFO");
    fprintf (pFile,"\ndwMajorVersion:%d",OSINFO.dwMajorVersion);
    fprintf (pFile,"\ndwMinorVersion:%d",OSINFO.dwMinorVersion);
    fprintf (pFile,"\ndwBuildNumber:%d",OSINFO.dwBuildNumber);
    fprintf (pFile,"\ndwPlatformId:%d",OSINFO.dwPlatformId);
    // fprintf (pFile,"\nszCSDVersion[128]:%s",OSINFO.szCSDVersion[128]);
    fprintf (pFile,"\nwServicePackMajor:%d",OSINFO.wServicePackMajor);
    fprintf (pFile,"\nwServicePackMinor:%d",OSINFO.wServicePackMinor);
    fprintf (pFile,"\nwSuiteMask:%d",OSINFO.wSuiteMask);
    fprintf (pFile,"\nwProductType:%d",OSINFO.wProductType);
    fprintf (pFile,"\nwReserved:%d",OSINFO.wReserved);

    fclose (pFile);

}


DWORD Lowmemorynotification()    
{
    LMHandle = CreateMemoryResourceNotification(Low);
    HMHandle = CreateMemoryResourceNotification(High);
    state=QueryMemoryResourceNotification(LMHandle, &ResourceState);
    if (state==1)
    {
        printf("QueryMemoryResourceNotification Created for Low Memory pressure");
        printf("\nYou will be signaled when there is low MemoryResourceNotification");
    }
loop:

    x=x+1;
    WaitForSingleObject( LMHandle,INFINITE);
    _strdate( dateStr);
    _strtime( timeStr );
    printf("%d",x);
    printf("Low Memory Notification received on  %s  %s  ", dateStr,timeStr);
    processmemory();
    printf("  Memory status is printed to Memorystatus.txt \n");
    Sleep(3000); 
    goto loop; 

    return 1;
};


void main()

{
    THandle=CreateThread( NULL, 8388608,(LPTHREAD_START_ROUTINE)Lowmemorynotification,NULL,0,NULL);

    //8388608=>Stack size in bytes which is 1 mb
    //    Lowmemorynotification();


    if (THandle==NULL)
    {
        printf("Create thread failed",GetLastError());
    }

    else
    {
        printf("\nSuccess");
        WaitForSingleObject(THandle,INFINITE);
    }

}

Thanks

Karthick P.K

Posted in Memory, Programming, SQL Server Engine | Tagged: , , , , , | 3 Comments »

AWE allocator API’s (How SQL Server AWE works)

Posted by Karthick P.K on November 11, 2010

#include <windows.h> 
#include <string> 
#include <winbase.h> 
#include <iostream> 
using namespace std;
#include <psapi.h>
#pragma comment(lib,"psapi.lib")


BOOL LoggedSetLockPagesPrivilege ( HANDLE hProcess,BOOL bEnable)
{
  struct {
    DWORD Count;
    LUID_AND_ATTRIBUTES Privilege [1];
  } Info;

  HANDLE Token;
  BOOL Result;

  // Open the token.

  Result = OpenProcessToken ( hProcess,
                              TOKEN_ADJUST_PRIVILEGES,
                              & Token);

  if( Result != TRUE ) 
  {
    printf( "Cannot open process token.\n" );
    return FALSE;
  }

  // Enable or disable?

  Info.Count = 1;
  if( bEnable ) 
  {
    Info.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
  } 
  else 
  {
    Info.Privilege[0].Attributes = 0;
  }

  // Get the LUID.

  Result = LookupPrivilegeValue ( NULL,
                                  SE_LOCK_MEMORY_NAME,
                                  &(Info.Privilege[0].Luid));

  if( Result != TRUE ) 
  {
    printf( "Cannot get privilege for %s.\n", SE_LOCK_MEMORY_NAME );
    return FALSE;
  }

  // Adjust the privilege.

  Result = AdjustTokenPrivileges ( Token, FALSE,
                                   (PTOKEN_PRIVILEGES) &Info,
                                   0, NULL, NULL);

  // Check the result.

  if( Result != TRUE ) 
  {
    printf ("Cannot adjust token privileges (%u)\n", GetLastError() );
    return FALSE;
  } 
  else 
  {
    if( GetLastError() != ERROR_SUCCESS ) 
    {
      printf ("Cannot enable the SE_LOCK_MEMORY_NAME privilege; ");
      printf ("please check the local policy.\n");
      return FALSE;
    }
  }

  CloseHandle( Token );

  return TRUE;
};






void main()
    {

    long int s=0;
    
    printf("\nEnter the size in MB  for address range that can be used to map Address Windowing Extensions (AWE) pages:");
    scanf("%d",&s);
    LPVOID lpaddress=NULL; 
    SIZE_T size=s*1024*1024;  //size in bytes
    printf ("\n%d",size);
    LPVOID ADD;
    int i;
    char *ADDw;
    BOOL bResult= FALSE;
    BOOL bResult2= FALSE;
    BOOL bResult3= FALSE;
    BOOL bResult4= FALSE;
    BOOL bResult5= FALSE;
    
    ULONG_PTR sizemap= (size)/4096;
    ULONG_PTR sizemap2= (size)/4096;
    ULONG_PTR sizemap3= (size)/4096;
    ULONG_PTR sizemap4= (size)/4096;
    ULONG_PTR sizemap5= (size)/4096;
    
                if( ! LoggedSetLockPagesPrivilege( GetCurrentProcess(), TRUE ) )  
                /*. The SeLockMemoryPrivilege privilege must be enabled in the caller's token or 
                the function will fail with ERROR_PRIVILEGE_NOT_HELD*/
                  {
                    printf("\n No Previledge");
                    printf("\n %u", GetLastError() );
                      return;
                  }


    ULONG_PTR * aRAMPages = new ULONG_PTR[sizemap];
    ULONG_PTR * aRAMPages2 = new ULONG_PTR[sizemap2];
    ULONG_PTR * aRAMPages3 = new ULONG_PTR[sizemap3];
    ULONG_PTR * aRAMPages4 = new ULONG_PTR[sizemap4];
    ULONG_PTR * aRAMPages5 = new ULONG_PTR[sizemap5];


    ADD=VirtualAlloc(lpaddress,size,MEM_RESERVE | MEM_PHYSICAL,PAGE_READWRITE);

    
    if (ADD==0)

    {
    printf ("allocation failled");
    printf("\n %u", GetLastError() );
        return;
    }



    bResult=AllocateUserPhysicalPages(GetCurrentProcess(),&sizemap,aRAMPages);

            if( bResult != TRUE ) 
            {
            printf("\n %uError in AllocateUserPhysicalPages", GetLastError() );
            return;
            }

    bResult2=AllocateUserPhysicalPages(GetCurrentProcess(),&sizemap2,aRAMPages2);

            if( bResult != TRUE ) 
            {
            printf("\n %uError in AllocateUserPhysicalPages2", GetLastError() );
            return;
            }
    bResult3=AllocateUserPhysicalPages(GetCurrentProcess(),&sizemap3,aRAMPages3);

            if( bResult != TRUE ) 
            {
            printf("\n %uError in AllocateUserPhysicalPages2", GetLastError() );
            return;
            }

    bResult4=AllocateUserPhysicalPages(GetCurrentProcess(),&sizemap4,aRAMPages4);

            if( bResult != TRUE ) 
            {
            printf("\n %uError in AllocateUserPhysicalPages2", GetLastError() );
            return;
            }

    bResult5=AllocateUserPhysicalPages(GetCurrentProcess(),&sizemap5,aRAMPages5);

            if( bResult != TRUE ) 
            {
            printf("\n %uError in AllocateUserPhysicalPages2", GetLastError() );
            return;
            }


printf("\n We have allocated 5 different ranges of physical memory pages that could be used to map and unmapp within Address Windowing Extensions (AWE) region of a specified process");


printf("\n Mapping the first range and filling with : MAP1");

   bResult=MapUserPhysicalPages(ADD,sizemap,aRAMPages);

            if( bResult != TRUE ) 
            {
            printf("\n %uError in MapUserPhysicalPages", GetLastError() );
            return;
            }
            

        ADDw =(LPSTR) ADD;
        for(i=1;i<=(size-5);i=i+5)

        {
            ADDw[i] = 'M';
            ADDw[i+1] = 'A';
            ADDw[i+2] = 'P';
            ADDw[i+3] = '1';
            ADDw[i+4] = ':';

        }
 
    printf("\n Mapping the second range and filling with : MAP2");
    bResult2=MapUserPhysicalPages(ADD,sizemap2,aRAMPages2);
                if( bResult != TRUE ) 
                {
                printf("\n %uError in MapUserPhysicalPages", GetLastError() );
                return;
                }

            for(i=1;i<=(size-5);i=i+5)
            {
            ADDw[i] = 'M';
            ADDw[i+1] = 'A';
            ADDw[i+2] = 'P';
            ADDw[i+3] = '2';
            ADDw[i+4] = ':';
            }
       
    printf("\n Mapping the third range and filling with : MAP3");            
       bResult3=MapUserPhysicalPages(ADD,sizemap3,aRAMPages3);

                if( bResult != TRUE ) 
                {
                printf("\n %uError in MapUserPhysicalPages", GetLastError() );
                return;
                }

            for(i=1;i<=(size-5);i=i+5)
            {
            ADDw[i] = 'M';
            ADDw[i+1] = 'A';
            ADDw[i+2] = 'P';
            ADDw[i+3] = '3';
            ADDw[i+4] = ':';
            }
    
       printf("\n Mapped the fourth range and filling with : MAP4");    
            
        bResult4=MapUserPhysicalPages(ADD,sizemap4,aRAMPages4);
        
                if( bResult != TRUE ) 
                {
                printf("\n %uError in MapUserPhysicalPages", GetLastError() );
                return;
                }

            for(i=1;i<=(size-5);i=i+5)
            {
            ADDw[i] = 'M';
            ADDw[i+1] = 'A';
            ADDw[i+2] = 'P';
            ADDw[i+3] = '4';
            ADDw[i+4] = ':';
            }
    
        printf("\n Mapped the fifth range and filled with : MAP5");

        bResult5=MapUserPhysicalPages(ADD,sizemap5,aRAMPages5);

                if( bResult != TRUE ) 
                {
                printf("\n %uError in MapUserPhysicalPages", GetLastError() );
                return;
                }

            for(i=1;i<=(size-5);i=i+5)
            {
            ADDw[i] = 'M';
            ADDw[i+1] = 'A';
            ADDw[i+2] = 'P';
            ADDw[i+3] = '5';
            ADDw[i+4] = ':';
            }

         


    printf("\n Mapping the first range and printing First 128 charecters");

    bResult=MapUserPhysicalPages(ADD,sizemap,aRAMPages);
            
            if( bResult != TRUE ) 
            {
            printf("\n %uError in MapUserPhysicalPages", GetLastError() );
            return;
            }


            

                for(int i=1;i<=128;i++)
                {
                printf("%c",ADDw[i]);
                }

printf("\n Mapping the second range and printing First 128 charecters");            
     bResult2=MapUserPhysicalPages(ADD,sizemap2,aRAMPages2);

                if( bResult != TRUE ) 
                {
                printf("\n %uError in MapUserPhysicalPages", GetLastError() );
                return;
                }
                for(int i=1;i<=128;i++)
                {
                printf("%c",ADDw[i]);
                }

printf("\n Mapping the third range and printing First 128 charecters");
bResult3=MapUserPhysicalPages(ADD,sizemap3,aRAMPages3);

                if( bResult != TRUE ) 
                {
                printf("\n %uError in MapUserPhysicalPages", GetLastError() );
                return;
                }
                for(int i=1;i<=128;i++)
                {
                printf("%c",ADDw[i]);
                }

printf("\n Mapping the fourth range and printing First 128 charecters");
bResult4=MapUserPhysicalPages(ADD,sizemap4,aRAMPages4);

                if( bResult != TRUE ) 
                {
                printf("\n %uError in MapUserPhysicalPages", GetLastError() );
                return;
                }
                for(int i=1;i<=128;i++)
                {
                printf("%c",ADDw[i]);
                }

printf("\n Mapping the five range and printing First 128 charecters");
bResult5=MapUserPhysicalPages(ADD,sizemap5,aRAMPages5);

                if( bResult != TRUE ) 
                {
                printf("\n %uError in MapUserPhysicalPages", GetLastError() );
                return;
                }
                for(int i=1;i<=128;i++)
                {
                printf("%c",ADDw[i]);
                }

system("pause");

}

 
 
 
Thanks
Karthick P.K

Posted in Programming | Tagged: , , , , , | 6 Comments »

How to check if local system is connected to a network and identify the type of network connection

Posted by Karthick P.K on July 26, 2010

#include <windows.h> 
#include <iostream> 
using namespace std;
#pragma comment(lib, "Sensapi.lib")
#include <Sensapi.h>

void main()
{
    
bool a; 
LPDWORD lpdwFlags;
lpdwFlags = new DWORD;
a=IsNetworkAlive( lpdwFlags);

        if(GetLastError()!=0)
        {
            cout<<"IsNetworkAlive failed:%d"<<GetLastError();
        }
        else if(GetLastError()==0 & (!a) )
        {
            cout<<"Network is not connected";
        }
        else if(GetLastError()==0 & (a))
        {
            cout<<"Network is connected.Type: "<< *lpdwFlags;  //1=Lan and 2=WAN
        }

}

Regards

Karthick P.K

Posted in Programming, SQL General | 2 Comments »

How to check if my account has LPM privilege

Posted by Karthick P.K on July 18, 2010

#include <windows.h> 
#include <string> 
#include <winbase.h> 
#include <iostream> 
using namespace std;
#include <psapi.h>
#pragma comment(lib,"psapi.lib")

void main()
    {

    long int s=0;
    printf("\nThis program will allocate memory using AWE allocator API's");
    printf("\nEnter the size of memory to be allocated using AWE API's:");
    scanf("%d",&s);
    LPVOID lpaddress=NULL; 
    SIZE_T size=s;   
    LPVOID ADD;
    BOOL bResult= FALSE;
    BOOL bResult2= FALSE;
    ULONG_PTR sizemap= (size)*1024*1024/4096;
    
                if( ! LoggedSetLockPagesPrivilege( GetCurrentProcess(), TRUE ) )  //. The SeLockMemoryPrivilege privilege must be enabled in the caller's token or the function will fail with ERROR_PRIVILEGE_NOT_HELD
                  {
                    printf("\n No Previledge");
                    printf("\n Error: %u", GetLastError() );
                      return;
                  }


    ULONG_PTR * aRAMPages = new ULONG_PTR[sizemap];


    ADD=VirtualAlloc(lpaddress,(size*1024*1024),MEM_RESERVE | MEM_PHYSICAL,PAGE_READWRITE);

    
    if (ADD==0)

    {
    printf ("allocation failled");
    printf("\n %u", GetLastError() );
        return;
    }



    bResult=AllocateUserPhysicalPages(GetCurrentProcess(),&sizemap,aRAMPages);

            if( bResult != TRUE ) 
            {
            printf("\n %uError in AllocateUserPhysicalPages", GetLastError() );
            return;
            }

     bResult2=MapUserPhysicalPages(ADD,sizemap,aRAMPages);

            if( bResult != TRUE ) 
            {
            printf("\n %uError in MapUserPhysicalPages", GetLastError() );
            return;
            }
printf("\nAllocated %d MB using AWE allocator API's which SQLServer uses when LPM is enabled.",s  );
system("pause");
}





 
BOOL LoggedSetLockPagesPrivilege ( HANDLE hProcess,BOOL bEnable)
{
  struct {
    DWORD Count;
    LUID_AND_ATTRIBUTES Privilege [1];
  } Info;

  HANDLE Token;
  BOOL Result;

  // Open the token.

  Result = OpenProcessToken ( hProcess,
                              TOKEN_ADJUST_PRIVILEGES,
                              & Token);

  if( Result != TRUE ) 
  {
    printf( "Cannot open process token.\n" );
    return FALSE;
  }

  // Enable or disable?

  Info.Count = 1;
  if( bEnable ) 
  {
    Info.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
  } 
  else 
  {
    Info.Privilege[0].Attributes = 0;
  }

  // Get the LUID.

  Result = LookupPrivilegeValue ( NULL,
                                  SE_LOCK_MEMORY_NAME,
                                  &(Info.Privilege[0].Luid));

  if( Result != TRUE ) 
  {
    printf( "Cannot get privilege for %s.\n", SE_LOCK_MEMORY_NAME );
    return FALSE;
  }

  // Adjust the privilege.

  Result = AdjustTokenPrivileges ( Token, FALSE,
                                   (PTOKEN_PRIVILEGES) &Info,
                                   0, NULL, NULL);

  // Check the result.

  if( Result != TRUE ) 
  {
    printf ("Cannot adjust token privileges (%u) Error:", GetLastError() );
    return FALSE;
  } 
  else 
  {
    if( GetLastError() != ERROR_SUCCESS ) 
    {
      
    printf ("\nCannot enable the SE_LOCK_MEMORY_NAME privilege; ");
     printf ("\nPlease check the local policy.\n");
      return FALSE;
    }
  }

  CloseHandle( Token );

  return TRUE;
};




Regards
Karthick P.K

Posted in Programming | Tagged: , , , | 1 Comment »

How to retrieve information about the file system and volume associated with the specified root directory (GetVolumeInformation function)

Posted by Karthick P.K on May 30, 2010

#include <windows.h> 
#include <winbase.h> 
#include <iostream> 
using namespace std;

void main()
{

  bool x=0;    
  char lpVolumeNameBuffer[1000];
  DWORD nVolumeNameSize;
  DWORD lpVolumeSerialNumber;
  DWORD lpMaximumComponentLength;
  DWORD lpFileSystemFlags;
  char lpFileSystemNameBuffer[1000];
  DWORD nFileSystemNameSize;
  char a[100];
  cout<<"A trailing backslash is required when you enter diskname. For example, you specify \\\\MyServer\\\MyShare as \\\\MyServer\\MyShare\\ or\n the C drive as C:\\";

   cout<<"\n"<<"Enter the Disk:";
   cin>>a;
   nVolumeNameSize= sizeof( (TCHAR) (lpVolumeNameBuffer))+1;
   nFileSystemNameSize=sizeof( (TCHAR) (lpFileSystemNameBuffer))+1;
 
  x= GetVolumeInformation((LPCSTR)&a, (LPSTR) lpVolumeNameBuffer,256,&lpVolumeSerialNumber,&lpMaximumComponentLength,&lpFileSystemFlags,(LPSTR) lpFileSystemNameBuffer,256);

            if (x==0)

            {
                int e=GetLastError();
                printf ( "Error getting volume information, Error ID:");
                printf ("%d",e);
            }
            else
            {
            cout<<"Disk:"<<a;    
            cout<<"\nVolumeNameBuffer:"<<lpVolumeNameBuffer;
            cout<<"\nVolumeSerialNumber:"<<lpVolumeSerialNumber;
            cout<<"\nMaximumComponentLength:"<<lpMaximumComponentLength;
            cout<<"\nFileSystemFlags:"<<lpFileSystemFlags;
            cout<<"\nFileSystemNameBuffer:"<<lpFileSystemNameBuffer;
            }

  
}

 

Posted in Programming | Tagged: | 2 Comments »

 
%d bloggers like this: