WriteFile() with WRITE_THROUGH is slow on system disk - winapi

On Windows Server 2008 R2 the following very simple program behaves different on system disk and on any other disk. Seems that on system disk FILE_FLAG_WRITE_THROUGH makes something ...
On disk C: (system disk, commodity SATA, no RAID)
$ time ./test.exe
real 1m8.281s
user 0m0.000s
sys 0m0.015s
On disk E: (another physical SATA disk)
$ time ./test.exe
real 0m5.445s
user 0m0.000s
sys 0m0.000s
-
#include <stdio.h>
#include <windows.h>
#define BUFFER_SIZE 1024
#define ITERATIONS 10240
#define FILEFLAGS FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH
BYTE buff[BUFFER_SIZE];
BOOL SyncWriteFile(HANDLE fd,
LPCVOID buf,
DWORD to_write) {
DWORD written = 0, already_written = 0;
BOOL res = FALSE;
while(written < to_write) {
res = WriteFile(fd,
(BYTE*)buf + written,
to_write - written,
&already_written,
NULL);
if (FALSE == res)
return FALSE;
else
written += already_written;
}
return TRUE;
}
void main()
{
HANDLE hFile;
int i;
hFile = CreateFile(TEXT("test"),
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_NEW,
FILEFLAGS,
NULL);
if (hFile == INVALID_HANDLE_VALUE) {
fprintf(stderr, "Could not create test file.");
exit(1);
}
for(i=0; i<ITERATIONS; i++) {
SyncWriteFile(hFile, buff, sizeof(buff));
}
CloseHandle(hFile);
}
What's going on?
Can somebody try to reproduce this on Win Server?

It was weird behavior of Samsung SATA 500GB disk (dying?) with SD15 firmware. We've fixed eventually this with dd utility and new disk. Everything works ok now. Sorry for "false alarm".

Related

Windows memory metric to detect memory leak

We have large old legacy server code running as a 64bit windows service.
The service has a memory leak which, at the moment, we do not have the resources to fix.
As the service is resilient to restart, a temporary terrible 'solution' we want is to detect when the service's memory exceeded, e.g., 5GB, and exit the service (which has auto restart for such cases).
My question is which metric should I go for? Is using GlobalMemoryStatusEx to get
MEMORYSTATUSEX.ullTotalVirtual- MEMORYSTATUSEX.ullAvailVirtual right?
GlobalMemoryStatusEx is wrong. You do not want to fill up the machine memory until 5 GB are left in total.
You need GetProcessMemoryInfo.
BOOL WINAPI GetProcessMemoryInfo(
__in HANDLE Process,
__out PPROCESS_MEMORY_COUNTERS ppsmemCounters,
__in DWORD cb
);
From an example using GetProcessMemoryInfo:
#include <windows.h>
#include <stdio.h>
#include <psapi.h>
// To ensure correct resolution of symbols, add Psapi.lib to TARGETLIBS
// and compile with -DPSAPI_VERSION=1
void PrintMemoryInfo( DWORD processID )
{
HANDLE hProcess;
PROCESS_MEMORY_COUNTERS pmc;
// Print the process identifier.
printf( "\nProcess ID: %u\n", processID );
// Print information about the memory usage of the process.
hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, processID );
if (NULL == hProcess)
return;
if ( GetProcessMemoryInfo( hProcess, &pmc, sizeof(pmc)) )
{
printf( "\tWorkingSetSize: 0x%08X\n", pmc.WorkingSetSize );
printf( "\tPagefileUsage: 0x%08X\n", pmc.PagefileUsage );
}
CloseHandle( hProcess );
}
int main( void )
{
// Get the list of process identifiers.
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
{
return 1;
}
// Calculate how many process identifiers were returned.
cProcesses = cbNeeded / sizeof(DWORD);
// Print the memory usage for each process
for ( i = 0; i < cProcesses; i++ )
{
PrintMemoryInfo( aProcesses[i] );
}
return 0;
}
Although unintuitive you need to read PagefileUsage which gets you the committed memory which was allocated by your process. WorkingSetSize is unreliable because if the machine gets tight on memory the OS will write all data to the page file. That can cause WorkingSetSize to be small (e.g. 100 MB) but in reality you leaked already 20 GB of memory. This would result in a saw tooth pattern in memory consumption until the page file is full. Working set is only the actively used memory which might hide the multi GB memory leak if the machine is under memory pressure.

GetThreadSelectorEntry throwing ERROR_NOT_SUPPORTED for x64 App

I trying to write a very simple app to debug a Win32 64-bit app. My end goal is to get the TIB and PEB of the remote thread, but for some reason the way I did this on 32-bit app is not working for 64-bit ones (Aside from looking at Esp vs Rsp and checking SegFs vs SegGs). The code I'm trying to use is here:
#include <windows.h>
#include <stdio.h>
#include <tlhelp32.h>
int main(int argc, char *argv[]){
LDT_ENTRY entry;
DWORD pid;
HANDLE hThread;
HANDLE hSnapshot;
CONTEXT context;
context.ContextFlags = CONTEXT_CONTROL;
if(argc < 2){
printf("Usage: %s PID\n", argv[0]);
exit(1);
}
pid = atoi(argv[1]);
THREADENTRY32 te32;
te32.dwSize = sizeof(te32);
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);
while(Thread32Next(hSnapshot, &te32)){
if(pid == te32.th32OwnerProcessID){
hThread = OpenThread(THREAD_ALL_ACCESS, 0, te32.th32ThreadID);
if(!hThread)
exit(1);
if(SuspendThread(hThread) == (DWORD) -1)
exit(1);
if(!GetThreadContext(hThread, &context))
exit(1);
printf("Rsp = 0x%x\n", context.Rsp);
if(!GetThreadSelectorEntry(hThread, context.SegGs, &entry)){
LPSTR buff = NULL;
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&buff, 0, NULL);
printf("Error: %s\n", buff); //ERROR_NOT_SUPPORTED 50 0x32 The request is not supported.
LocalFree(buff);
exit(1);
}
}
}
CloseHandle(hSnapshot);
return 0;
}
but it's always throwing an error at "GetThreadSelectorEntry". The error code that's thrown is ERROR_NOT_SUPPORTED: The request is not supported.
I am not able to understand why it's not supported. Does anyone know why?
[EDIT]
Okay GetThreadSelectorEntry is not available to x86_64 processes, does anyone know how I can get the TIB/PEB addresses of a remote process?

Windows Named Pipe is invalid

I have no idea why this pipe is invalid. everything seems fine to me. This is just a test, i don't write or read from it. Anyone can tell me what's wrong?
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#define BUFSIZE 4096
int main()
{
HANDLE hPipe;
LPTSTR Pipename = TEXT("\\\\.\\pipe\\mypipe");
printf("Start Server\n");
for(;;)
{
hPipe = CreateNamedPipe( Pipename,
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
BUFSIZE,
BUFSIZE,
NMPWAIT_USE_DEFAULT_WAIT,
NULL );
if ( hPipe == INVALID_HANDLE_VALUE )
{
printf("CreatePipe failed");
return 0;
}
CloseHandle(hPipe);
}
return 1;
}
Without more detail about the error it is difficult to help. However, as a general rule create the server using CreateNamedPipe then use ConnectNamedPipe.
On the client side you can now use CreateFile, which ConnectNamedPipe is waiting for on the server side.

How to access specific address of a USB drive

I need to access the partition table of a USB stick and change the first byte of partition 0 to make it bootable. And I also want to copy a bin file to a specific address of that USB drive. So can any one tell me how to perform these kind of tasks?
I badly in need of some examples... If you could provide any links of such kinds of works it would be great. I am working in C.
I am in the beginning stage. Here is my code:
// DeviceIoControl.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <winioctl.h>
#include <stdio.h>
BOOL GetMBR(PARTITION_INFORMATION *pdg)
{
HANDLE hDevice; // handle to the drive to be examined
BOOL bResult; // results flag
DWORD junk; // discard results
hDevice = CreateFile(TEXT("\\\\.\\H:"), // drive to open
GENERIC_READ | GENERIC_WRITE, // no access to the drive
FILE_SHARE_READ | // share mode
FILE_SHARE_WRITE,
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
NULL // do not copy file attributes
);
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
{
printf("CreateFile() failed!\n");
return (FALSE);
}
bResult = DeviceIoControl(
hDevice, // device to be queried
IOCTL_DISK_GET_PARTITION_INFO, // operation to perform
NULL, 0, // no input buffer
pdg, sizeof(*pdg), // output buffer
&junk, // # bytes returned
(LPOVERLAPPED) NULL // synchronous I/O
);
CloseHandle(hDevice);
return (bResult);
}
int _tmain(int argc, _TCHAR* argv[])
{
PARTITION_INFORMATION pdg; // disk drive geometry structure
BOOL bResult; // generic results flag
ULONGLONG DiskSize; // size of the drive, in bytes
bResult = GetMBR(&pdg);
if (bResult)
{
printf ("BootIndicator %lld\n", pdg.BootIndicator);
printf ("HiddenSectors %lld\n", pdg.HiddenSectors);
printf ("PartitionLength %u\n", pdg.PartitionLength);
printf ("PartitionNumber %u\n", pdg.PartitionNumber);
printf ("PartitionType %x\n", pdg.PartitionType);
printf ("RecognizedPartition %s\n", pdg.RecognizedPartition);
printf ("RewritePartition %ld.\n", pdg.RewritePartition);
printf ("StartingOffset %lld\n", pdg.StartingOffset);
}
else
{
printf ("PARTITION INFORMATION failed. Error %ld.\n", GetLastError ());
}
getchar();
return ((int)bResult);
}
Do you have to do it in code? You can use the built-in diskpart tool to make a USB drive bootable by following this tutorial.

How does one use VirtualAllocEx do make room for a code cave?

How does one use VirtualAllocEx do make room for a code cave? I am currently in possession of a piece of software with very little "free space" and I read that VirtualAllocEx is used for making this space..
After the question about "code cave" is cleared, you can find interesting following code which enumerate blocks allocated by VirtualAllocEx in the current process and find all PE (DLLs and the EXE itself).
SYSTEM_INFO si;
MEMORY_BASIC_INFORMATION mbi;
DWORD nOffset = 0, cbReturned, dwMem;
GetSystemInfo(&si);
for (dwMem = 0; dwMem<(DWORD)si.lpMaximumApplicationAddress;
dwMem+=mbi.RegionSize) {
cbReturned = VirtualQueryEx (GetCurrentProcess(), (LPCVOID)dwMem, &mbi,
sizeof(mbi));
if (cbReturned) {
if ((mbi.AllocationProtect & PAGE_EXECUTE_WRITECOPY) &&
(mbi.Protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ |
PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY))) {
if (*(LPWORD)mbi.AllocationBase == IMAGE_DOS_SIGNATURE) {
IMAGE_DOS_HEADER *pDosHeader =
(IMAGE_DOS_HEADER *)mbi.AllocationBase;
if (pDosHeader->e_lfanew) {
IMAGE_NT_HEADERS32 *pNtHeader = (IMAGE_NT_HEADERS32 *)
((PBYTE)pDosHeader + pDosHeader->e_lfanew);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
continue;
// now you can examine of module loaded in current process
}
}
}
}
}
The code could looks like a large loop. In reality it is a typical application it makes about 200 loops, so it is very quickly to goes through all blocks allocated with respect of VirtualAllocEx during loading of EXE all all depended DLLs.
#include <stdio.h>
#include <windows.h>
#include <commctrl.h>
unsigned long pid;
HANDLE process;
GetWindowThreadProcessId(listview, &pid);
process = OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ | PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION, FALSE, pid);
int *vptr = (int *)VirtualAllocEx(process, NULL, sizeof(int), MEM_COMMIT, PAGE_READWRITE);
References
- MSDN VirtualAllocEx Function
- CodeProject Stealing Program's Memory
- StackOver What is a code cave... ?
HTH,

Resources