PRACTICAL FILE
OF
Programming in Windows
Environment
(Paper code: OSD-330P)
Submitted to: Submitted by:
Mr. Neeraj Singh Arindam Nandy
Assistant Professor Roll no:10015603121
IT Department Section : T7
Roll no:10015603121
INDEX
S.no Name of the Experiment Date Sign
1 Printing the Current Directory
2 File Listing and Directory Traversal
3 File Processing with Error and Exception
Recovery
4 Sorting a File with Memory Mapping
5 Create an Index File
6 Create a DLL with Explicit linking
7 Parallel Searching using multiple
processes
8 Multithreaded Pattern Searching
9 Write a socket based client
10 Socket-Based Server with In-Process
Servers
11 Write code for A Service Wrapper using
existing services
Roll no:10015603121
EXPERIMENT 1
Aim:Printing the Current Directory
Theory:Printing the directory in Windows serves purposes like quick
reference, documentation, debugging, scripting, and workflow
management. It provides visibility and context, aiding tasks and
workflows.
Code:
#ifdef _WIN32
#include <direct.h>
#define GetCurrentDir _getcwd
#else
#include <unistd.h>
#define GetCurrentDir getcwd
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Roll no:10015603121
char* get_current_dir() {
char buff[FILENAME_MAX];
GetCurrentDir(buff, FILENAME_MAX);
char* current_working_dir = _strdup(buff);
return current_working_dir;
int main() {
char* cwd = get_current_dir();
printf("%s\n", cwd);
free(cwd);
return 0;
Output:
Roll no:10015603121
EXPERIMENT 2
Aim:File Listing and Directory Traversal
Theory:File listing and directory traversal are crucial tasks in Windows
system programming. They allow users and applications to access
information about files and directories, including attributes like names,
sizes, and modification times. These operations enable file
management tasks such as copying, moving, and deleting files, as well
as batch processing and search operations. Additionally, they facilitate
monitoring file system changes and analyzing file system structures,
making them essential for both system administrators and application
developers.
Code:
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#define FILENAME_PATH 256
DWORD FileType(LPWIN32_FIND_DATA pData) {
if (pData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
return FILE_ATTRIBUTE_DIRECTORY;
} else {
Roll no:10015603121
return FILE_ATTRIBUTE_NORMAL;
void ProcessFile(LPWIN32_FIND_DATA pData, LPCTSTR
path,LPCTSTR DirPath) {
if (FileType(pData) == FILE_ATTRIBUTE_DIRECTORY) {
printf("%s\\%s\n",DirPath,pData->cFileName);
} else {
printf("File: %s\n", pData->cFileName);
void TraverseDirectory(LPCTSTR path) {
WIN32_FIND_DATA findData;
HANDLE hFind = INVALID_HANDLE_VALUE;
TCHAR searchPath[MAX_PATH];
LPCTSTR Dirpath=path;
_tcscpy(searchPath, path);
Roll no:10015603121
_tcscat(searchPath, _T("\\*"));
hFind = FindFirstFile(searchPath, &findData);
if (hFind == INVALID_HANDLE_VALUE) {
printf("Error opening directory: %s\n", path);
return;
do {
if (_tcscmp(findData.cFileName, _T(".")) != 0 &&
_tcscmp(findData.cFileName, _T("..")) != 0) {
ProcessFile(&findData, path,Dirpath);
if (FileType(&findData) == FILE_ATTRIBUTE_DIRECTORY) {
TCHAR subDirPath[MAX_PATH];
_tcscpy(subDirPath, path);
_tcscat(subDirPath, _T("\\"));
_tcscat(subDirPath, findData.cFileName);
TraverseDirectory(subDirPath);
Roll no:10015603121
}
} while (FindNextFile(hFind, &findData) != 0);
FindClose(hFind);
int main(int argc, char *argv[]) {
char str[FILENAME_MAX];
printf("Enter the Directory: ");
fgets(str, FILENAME_MAX, stdin);
str[strcspn(str, "\n")] = '\0';
LPCTSTR directoryPath = _T(str);
TraverseDirectory(directoryPath);
return 0;
Roll no:10015603121
Output:
Roll no:10015603121
EXPERIMENT 3
Aim:File Processing with Error and Exception Recovery
Theory:In Windows system programming, adept error and exception
handling in file processing are paramount. Utilize GetLastError() and
FormatMessage() for error management, adapting responses to severity.
Employ structured exception handling (__try, __except) for comprehensive error
handling. Leverage Transactional NTFS (TxF) for atomic file operations,
rolling back transactions upon errors. Ensure robust error handling during
backup and restore processes using Windows APIs. Implement
asynchronous file I/O cautiously to avert data loss.
Code:
#include <WinSock2.h>
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define MAX_FILENAME_LEN 250
Roll no:10015603121
#if defined(UTILITY_4_0_EXPORTS)
#define LIBSPEC __declspec (dllexport)
#elif defined(__cplusplus)
#define LIBSPEC extern "C" __declspec (dllimport)
#else
#define LIBSPEC __declspec (dllimport)
#endif
LIBSPEC VOID ReportError(LPCTSTR, DWORD, BOOL);
LIBSPEC VOID ReportException(LPCTSTR, DWORD);
LIBSPEC BOOL WindowsVersionOK(DWORD, DWORD);
int _tmain(int argc, LPTSTR argv[])
HANDLE hIn = INVALID_HANDLE_VALUE, hOut = INVALID_HANDLE_VALUE;
DWORD nXfer, iFile, j;
TCHAR outFileName[256] = _T(""), * pBuffer = NULL;
OVERLAPPED ov = { 0, 0, 0, 0, NULL };
LARGE_INTEGER fSize;
Roll no:10015603121
if (!WindowsVersionOK(3, 1))
ReportError(_T("This program requires Windows NT 3.1 or greater to
support LockFileEx"),
1, FALSE);
if (argc <= 1)
ReportError(_T("Usage: Win3 files"), 1, FALSE);
for (iFile = 1; iFile < (unsigned int)argc; iFile++) __try {
if (_tcslen(argv[iFile]) > 250)
ReportException(_T("The file name is too long."), 1);
swprintf_s(outFileName, _T("UC_%s"), argv[iFile]);
__try {
hIn = CreateFile(argv[iFile], GENERIC_READ,
0, NULL, OPEN_EXISTING, 0, NULL);
if (hIn == INVALID_HANDLE_VALUE) ReportException(argv[iFile],
1);
if (!GetFileSizeEx(hIn, &fSize) || fSize.HighPart > 0)
ReportException(_T("This file is too large for this program."),
1);
Roll no:10015603121
hOut = CreateFile(outFileName, GENERIC_READ |
GENERIC_WRITE,
0, NULL, CREATE_NEW, 0, NULL);
if (hOut == INVALID_HANDLE_VALUE)
ReportException(outFileName, 1);;
TCHAR* pBuffer = (TCHAR*)malloc(fSize.LowPart);
if (pBuffer == NULL) ReportException(_T("Memory allocation
error"), 1);;
if (!ReadFile(hIn, pBuffer, fSize.LowPart, &nXfer, NULL) || (nXfer !=
fSize.LowPart))
ReportException(_T("ReadFile error"), 1);
for (j = 0; j < fSize.LowPart; j++)
if (isalpha(pBuffer[j])) pBuffer[j] = toupper(pBuffer[j]);
if (!WriteFile(hOut, pBuffer, fSize.LowPart, &nXfer, NULL) || (nXfer
!= fSize.LowPart))
ReportException(_T("WriteFile error"), 1);
__finally {
Roll no:10015603121
if (pBuffer != NULL) free(pBuffer); pBuffer = NULL;
if (hIn != INVALID_HANDLE_VALUE) {
CloseHandle(hIn);
hIn = INVALID_HANDLE_VALUE;
if (hOut != INVALID_HANDLE_VALUE) {
CloseHandle(hOut);
hOut = INVALID_HANDLE_VALUE;
wcscpy_s(outFileName, _T(""));
__except (EXCEPTION_EXECUTE_HANDLER) {
_tprintf(_T("Error occured processing file %s\n"), argv[iFile]);
DeleteFile(outFileName);
_tprintf(_T("All files converted, except as noted above\n"));
return 0;
Roll no:10015603121
Output:
Roll no:10015603121
EXPERIMENT 4
Aim:Sorting a File with Memory Mapping
Theory:In Windows system programming, adept error and exception
handling in file processing are paramount. Utilize GetLastError() and
FormatMessage() for error management, adapting responses to severity.
Employ structured exception handling (__try, __except) for comprehensive error
handling. Leverage Transactional NTFS (TxF) for atomic file operations,
rolling back transactions upon errors. Ensure robust error handling during
backup and restore processes using Windows APIs. Implement
asynchronous file I/O cautiously to avert data loss.
Code:
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <Windows.h>
using namespace std;
const string FILENAME = "data.txt";
Roll no:10015603121
bool compare(int a, int b) {
return a < b;
int main() {
HANDLE hFile = CreateFileA(FILENAME.c_str(), GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
cerr << "Error opening file.\n";
return 1;
DWORD fileSize = GetFileSize(hFile, NULL);
if (fileSize == INVALID_FILE_SIZE) {
cerr << "Error getting file size.\n";
CloseHandle(hFile);
return 1;
Roll no:10015603121
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0,
NULL);
if (hMapping == NULL) {
cerr << "Error creating file mapping.\n";
CloseHandle(hFile);
return 1;
LPVOID lpData = MapViewOfFile(hMapping, FILE_MAP_READ | FILE_MAP_WRITE,
0, 0, 0);
if (lpData == NULL) {
cerr << "Error mapping file into memory.\n";
CloseHandle(hMapping);
CloseHandle(hFile);
return 1;
int* data = static_cast<int*>(lpData);
int numElements = fileSize / sizeof(int);
sort(data, data + numElements, compare);
Roll no:10015603121
UnmapViewOfFile(lpData);
CloseHandle(hMapping);
CloseHandle(hFile);
cout << "File sorted successfully.\n";
return 0;
Output:
Roll no:10015603121
EXPERIMENT 5
Aim:Create an Index File
Theory:In Windows system programming, indexing files serves to enhance
efficiency and performance by organizing metadata about file contents. This
facilitates quicker data retrieval, especially in large files, by avoiding the need
to scan entire files. Indexing optimizes file access patterns, supports
complex queries, and aids in effective file management, making it a valuable
technique for improving file-related operations in various applications.
Code:
#include <Windows.h>
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
vector<string> GetFileNames(const string& directory) {
vector<string> filenames;
string searchPath = directory + "\\*.*";
Roll no:10015603121
WIN32_FIND_DATA findData;
HANDLE hFind = FindFirstFile(searchPath.c_str(), &findData);
if (hFind != INVALID_HANDLE_VALUE) {
do {
if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
filenames.push_back(findData.cFileName);
} while (FindNextFile(hFind, &findData) != 0);
FindClose(hFind);
sort(filenames.begin(), filenames.end());
return filenames;
int main() {
string directory = "C:\\Users\\HP\\Desktop\\New Files\\New Files\\OS";
vector<string> filenames = GetFileNames(directory);
vector<HANDLE> fileMappings;
Roll no:10015603121
vector<LPVOID> mappedFilePointers;
for (const auto& filename : filenames) {
string filePath = directory + "\\" + filename;
HANDLE hFile = CreateFile(filePath.c_str(), GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0,
NULL);
if (hMapping != NULL) {
LPVOID pData = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
if (pData != NULL) {
fileMappings.push_back(hMapping);
mappedFilePointers.push_back(pData);
else {
CloseHandle(hMapping);
else {
CloseHandle(hFile);
Roll no:10015603121
}
if (!fileMappings.empty() && fileMappings.size() == mappedFilePointers.size()) {
cout << "Memory-mapped file index:\n";
for (size_t i = 0; i < filenames.size(); ++i) {
cout << "Filename: " << filenames[i] << ", Memory-mapped pointer: " <<
mappedFilePointers[i] << endl;
else {
cout << "Error: Failed to map files to memory.\n";
for (size_t i = 0; i < fileMappings.size(); ++i) {
UnmapViewOfFile(mappedFilePointers[i]);
CloseHandle(fileMappings[i]);
return 0;
Roll no:10015603121
}
Output:
Roll no:10015603121
EXPERIMENT 6
Aim:Create a DLL with Explicit linking
Theory:In Windows system programming, indexing files serves to enhance
efficiency and performance by organizing metadata about file contents. This
facilitates quicker data retrieval, especially in large files, by avoiding the need
to scan entire files. Indexing optimizes file access patterns, supports
complex queries, and aids in effective file management, making it a valuable
technique for improving file-related operations in various applications.
Code:
MyMath.cpp = MyMath.dll Declaration
#include <windows.h>
#ifdef __cplusplus
extern "C" {
#endif
__declspec (dllexport) int __cdecl Addition(int x, int y)
int z;
z = x + y;
Roll no:10015603121
return z;
__declspec (dllexport) int __cdecl Subrtaction(int x, int y)
int z;
z = x - y;
return z;
__declspec (dllexport) int __cdecl Multiplication(int x, int y)
int z;
z = x * y;
return z;
__declspec (dllexport) int __cdecl Division(int x, int y)
int z;
z = x / y;
return z;
Roll no:10015603121
#ifdef __cplusplus
#endif
MyMathProgram.cpp
#include <Windows.h>
#include <stdio.h>
typedef int(__cdecl* FunAdd)(int a, int b);
typedef int(__cdecl* FunSub)(int a, int b);
typedef int(__cdecl* FunMul)(int a, int b);
typedef int(__cdecl* FunDiv)(int a, int b);
int main()
HMODULE hModule;
hModule =
LoadLibrary(TEXT("C:\\Users\\HP\\source\\repos\\MyMath\\x64\\Debug\\MyMath
.dll"));
if (hModule == NULL)
Roll no:10015603121
{
printf("Failed to Load the DLL File: %lu\n", GetLastError());
return 1;
printf("Dll File Loaded Successfully\n");
FunSub MulFunc = (FunSub)GetProcAddress(hModule, "Multiplication");
FunSub DivFunc = (FunSub)GetProcAddress(hModule, "Division");
FunSub AddFunc = (FunSub)GetProcAddress(hModule, "Addition");
FunSub SubFunc = (FunSub)GetProcAddress(hModule, "Subtraction");
if (NULL == MulFunc)
printf("Function Address is not valid, error no: %lu\n", GetLastError());
return 1;
printf("Function Address is Valid\n");
printf("Multiplication = %d\n", MulFunc(50, 10));
printf("Division = %d\n", DivFunc(50, 10));
printf("Addition = %d\n", AddFunc(50, 10));
printf("Subtraction = %d\n", SubFunc(50, 10));
Roll no:10015603121
FreeLibrary(hModule);
return 0;
Output:
Roll no:10015603121
EXPERIMENT 7
Aim:Parallel Searching using multiple processes
Theory:Pattern searching, akin to Unix's grep command, is indispensable in
Windows system programming for tasks like text processing, log analysis,
and data extraction. It enables efficient sifting through large text volumes,
aiding in error identification, anomaly detection, and specific event tracing in
system logs. Moreover, it facilitates data extraction from structured
documents, content filtering, and advanced pattern matching using regular
expressions. Integrating pattern searching capabilities into Windows
programming enriches functionality and productivity, making it invaluable for
various tasks requiring text analysis and manipulation.
Code:
#include <Windows.h>
#include <stdio.h>
#include <tchar.h>
#if defined(UTILITY_4_0_EXPORTS)
#define LIBSPEC __declspec (dllexport)
#elif defined(__cplusplus)
#define LIBSPEC extern "C" __declspec (dllimport)
#else
Roll no:10015603121
#define LIBSPEC __declspec (dllimport)
#endif
LIBSPEC VOID ReportError(LPCTSTR, DWORD, BOOL);
int _tmain(int argc, LPTSTR argv[]) {
HANDLE hTempFile;
SECURITY_ATTRIBUTES stdOutSA = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
TCHAR commandLine[MAX_PATH + 100];
STARTUPINFO startUpSearch, startUp;
PROCESS_INFORMATION processInfo;
DWORD exitCode, dwCreationFlags = 0;
int iProc;
HANDLE* hProc;
typedef struct { TCHAR tempFile[MAX_PATH]; } PROCFILE;
PROCFILE* procFile;
#ifdef UNICODE
dwCreationFlags = CREATE_UNICODE_ENVIRONMENT;
#endif
if (argc < 3)
ReportError(_T("Usage: grepMP pattern files."), 1, FALSE);
Roll no:10015603121
GetStartupInfo(&startUpSearch);
GetStartupInfo(&startUp);
procFile = (PROCFILE*)malloc((argc - 2) * sizeof(PROCFILE));
hProc = (HANDLE*)malloc((argc - 2) * sizeof(HANDLE));
for (iProc = 0; iProc < argc - 2; iProc++) {
swprintf_s(commandLine, _T("grep \"%s\" \"%s\""), argv[1], argv[iProc + 2]);
if (GetTempFileName(_T("."), _T("gtm"), 0, procFile[iProc].tempFile) == 0)
ReportError(_T("Temp file failure."), 2, TRUE);
hTempFile = CreateFile(procFile[iProc].tempFile, GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, &stdOutSA, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hTempFile == INVALID_HANDLE_VALUE)
ReportError(_T("Failure opening temp file."), 3, TRUE);
Roll no:10015603121
startUpSearch.dwFlags = STARTF_USESTDHANDLES;
startUpSearch.hStdOutput = hTempFile;
startUpSearch.hStdError = hTempFile;
startUpSearch.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
if (!CreateProcess(NULL, commandLine, NULL, NULL, TRUE, dwCreationFlags,
NULL, NULL, &startUpSearch, &processInfo))
ReportError(_T("ProcCreate failed."), 4, TRUE);
CloseHandle(hTempFile);
CloseHandle(processInfo.hThread);
hProc[iProc] = processInfo.hProcess;
for (iProc = 0; iProc < argc - 2; iProc += MAXIMUM_WAIT_OBJECTS)
WaitForMultipleObjects(min(MAXIMUM_WAIT_OBJECTS, argc - 2 - iProc),
&hProc[iProc], TRUE, INFINITE);
for (iProc = 0; iProc < argc - 2; iProc++) {
Roll no:10015603121
if (GetExitCodeProcess(hProc[iProc], &exitCode) && exitCode == 0) {
if (argc > 3) _tprintf(_T("%s:\n"), argv[iProc + 2]);
swprintf_s(commandLine, _T("cat \"%s\""), procFile[iProc].tempFile);
if (!CreateProcess(NULL, commandLine, NULL, NULL, TRUE, dwCreationFlags,
NULL, NULL, &startUp, &processInfo))
ReportError(_T("Failure executing cat."), 0, TRUE);
else {
WaitForSingleObject(processInfo.hProcess, INFINITE);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
CloseHandle(hProc[iProc]);
if (!DeleteFile(procFile[iProc].tempFile))
ReportError(_T("Cannot delete temp file."), 6, TRUE);
free(procFile);
free(hProc);
return 0;
Roll no:10015603121
}
Output:
Roll no:10015603121
EXPERIMENT 8
Aim:Multithreaded Pattern Searching
Theory:Multithreaded search patterns in Windows system programming
boost performance by utilizing multiple CPU cores concurrently. They
enhance resource utilization, ensuring optimal system performance.
Scalability is improved as workloads can be distributed across threads
efficiently. Multithreading prevents long-running search operations from
blocking the main thread, enhancing application responsiveness.
Asynchronous search operations are enabled, allowing other tasks to
proceed while awaiting search results. Overall, multithreaded search patterns
optimize performance, scalability, and responsiveness in Windows
applications.
Code:
#include <stdio.h>
#include <windows.h>
#include <process.h>
#include <tchar.h>
#define MAX_COMMAND_LINE 1024
#define EOS _T('\0')
Roll no:10015603121
#define ASTRSK 1
#define QM 2
#define BEGCLASS 3
#define ENDCLASS 4
#define ANCHOR 5
typedef struct {
int argc;
TCHAR targv[4][MAX_COMMAND_LINE];
} GREP_THREAD_ARG;
typedef GREP_THREAD_ARG* PGR_ARGS;
static BOOL ignoreCase = FALSE;
static void prepSearchString(TCHAR* p, TCHAR* buf);
static BOOL patternMatch(TCHAR* pattern, TCHAR* string);
unsigned int __stdcall ThGrep(void* pArgs);
TCHAR commandLine[MAX_COMMAND_LINE]; // Declare commandLine variable
BOOL ok;
Roll no:10015603121
int _tmain(int argc, LPTSTR argv[]) {
PGR_ARGS gArg;
HANDLE* tHandle;
DWORD threadIndex, exitCode;
int iThrd, threadCount;
STARTUPINFO startUp;
PROCESS_INFORMATION processInfo;
GetStartupInfo(&startUp);
if (argc < 3) {
_tprintf(_T("No file names.\n"));
return 1;
tHandle = (HANDLE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (argc -
2) * sizeof(HANDLE));
gArg = (PGR_ARGS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (argc - 2)
* sizeof(GREP_THREAD_ARG));
Roll no:10015603121
for (iThrd = 0; iThrd < argc - 2; iThrd++) {
_tcscpy_s(gArg[iThrd].targv[1], MAX_COMMAND_LINE, argv[1]);
_tcscpy_s(gArg[iThrd].targv[2], MAX_COMMAND_LINE, argv[iThrd + 2]);
GetTempFileName(_T("."), _T("Gre"), 0, gArg[iThrd].targv[3]);
gArg[iThrd].argc = 4;
tHandle[iThrd] = (HANDLE)_beginthreadex(NULL, 0, ThGrep,
(void*)&gArg[iThrd], 0, NULL);
if (tHandle[iThrd] == 0) _tprintf(_T("ThreadCreate failed.\n"));
threadCount = argc - 2;
while (threadCount > 0) {
threadIndex = WaitForMultipleObjects(threadCount, tHandle, FALSE, INFINITE);
iThrd = (int)threadIndex - (int)WAIT_OBJECT_0;
if (iThrd < 0 || iThrd >= threadCount) _tprintf(_T("Thread wait error.\n"));
GetExitCodeThread(tHandle[iThrd], &exitCode);
CloseHandle(tHandle[iThrd]);
if (exitCode == 0) {
Roll no:10015603121
if (argc > 3) {
_tprintf(_T("%s\n"), gArg[iThrd].targv[2]);
fflush(stdout);
_stprintf_s(commandLine, MAX_COMMAND_LINE, _T("cat \"%s\""),
gArg[iThrd].targv[3]);
ok = CreateProcess(NULL, commandLine, NULL, NULL, TRUE, 0, NULL, NULL,
&startUp, &processInfo);
if (!ok) _tprintf(_T("Failure executing cat.\n"));
WaitForSingleObject(processInfo.hProcess, INFINITE);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
if (!DeleteFile(gArg[iThrd].targv[3])) _tprintf(_T("Cannot delete temp file.\n"));
tHandle[iThrd] = tHandle[threadCount - 1];
_tcscpy_s(gArg[iThrd].targv[3], MAX_COMMAND_LINE, gArg[threadCount -
1].targv[3]);
Roll no:10015603121
_tcscpy_s(gArg[iThrd].targv[2], MAX_COMMAND_LINE, gArg[threadCount -
1].targv[2]);
threadCount--;
HeapFree(GetProcessHeap(), 0, tHandle);
HeapFree(GetProcessHeap(), 0, gArg);
return 0;
unsigned int __stdcall ThGrep(void* pArgs) {
PGR_ARGS pArguments = (PGR_ARGS)pArgs;
TCHAR pattern[256];
TCHAR string[2048];
int i, patternSeen = FALSE, showName = FALSE, argc, result = 1;
FILE* fp, * fpout;
// Declare ok variable
argc = pArguments->argc;
if (_wfopen_s(&fpout, pArguments->targv[argc - 1], _T("wb")) != 0) {
Roll no:10015603121
printf("Failure to open output file.\n");
return 1;
for (i = 1; i < argc - 1; ++i) {
if (pArguments->targv[i][0] == _T('-')) {
switch (pArguments->targv[i][1]) {
case _T('y'):
ignoreCase = TRUE;
break;
else {
if (!patternSeen++)
prepSearchString(pArguments->targv[i], pattern);
else if (_wfopen_s(&fp, pArguments->targv[i], _T("rb")) == 0) {
if (!showName && i < argc - 2) ++showName;
while (_fgetts(string, sizeof(string), fp) != NULL && !feof(fp)) {
if (ignoreCase) _tcslwr_s(string);
if (patternMatch(pattern, string)) {
Roll no:10015603121
result = 0;
if (showName) {
fputws(pArguments->targv[i], fpout);
fputws(string, fpout);
else
fputws(string, fpout);
fclose(fp);
fclose(fpout);
return result;
static FILE* openFile(TCHAR* file, TCHAR* mode) {
Roll no:10015603121
FILE* fp = NULL;
if (_wfopen_s(&fp, file, mode) != 0) _tperror(file);
return fp;
static void prepSearchString(TCHAR* p, TCHAR* buf) {
register int c;
register int i = 0;
if (*p == _T('^')) {
buf[i++] = ANCHOR;
++p;
for (;;) {
switch (c = *p++) {
case EOS: goto Exit;
case _T('*'): if (i >= 0 && buf[i - 1] != ASTRSK) c = ASTRSK; break;
case _T('?'): c = QM; break;
case _T('['): c = BEGCLASS; break;
Roll no:10015603121
case _T(']'): c = ENDCLASS; break;
case _T('\\'):
switch (c = *p++) {
case EOS: goto Exit;
case _T('a'): c = _T('\a'); break;
case _T('b'): c = _T('\b'); break;
case _T('f'): c = _T('\f'); break;
case _T('t'): c = _T('\t'); break;
case _T('v'): c = _T('\v'); break;
case _T('\\'): c = _T('\\'); break;
break;
buf[i++] = (ignoreCase ? tolower(c) : c);
Exit:
buf[i] = EOS;
Roll no:10015603121
static BOOL patternMatch(TCHAR* pattern, TCHAR* string) {
register TCHAR pc, sc;
TCHAR* pat;
BOOL anchored;
if (anchored = (*pattern == ANCHOR)) ++pattern;
Top:
pat = pattern;
Again:
pc = *pat;
sc = *string;
if (sc == _T('\n') || sc == EOS) {
if (pc == EOS) goto Success;
else if (pc == ASTRSK) {
++pat;
goto Again;
Roll no:10015603121
}
else return (FALSE);
else {
if (pc == sc || pc == QM) {
++pat;
++string;
goto Again;
else if (pc == EOS) goto Success;
else if (pc == ASTRSK) {
if (patternMatch(pat + 1, string)) goto Success;
else {
++string;
goto Again;
else if (pc == BEGCLASS) {
BOOL clmatch = FALSE;
while (*++pat != ENDCLASS) {
Roll no:10015603121
if (!clmatch && *pat == sc) clmatch = TRUE;
if (clmatch) {
++pat;
++string;
goto Again;
if (anchored) return (FALSE);
++string;
goto Top;
Success:
return (TRUE);
Roll no:10015603121
Output:
Roll no:10015603121
EXPERIMENT 9
Aim:Write a socket based client
Theory:Socket-based clients are essential in Windows system programming
for several reasons: They enable communication between client and server
applications over networks. By utilizing sockets, clients can connect to
remote servers, exchange data, and perform various network-related tasks.
Socket-based clients facilitate the implementation of distributed systems,
enabling applications to interact across different machines seamlessly. They
support various protocols such as TCP/IP or UDP, making them versatile for
different communication needs. Socket programming in Windows allows for
the development of robust and scalable networked applications. Overall,
socket-based clients are fundamental for building networked applications in
Windows environments, offering flexibility, reliability, and interoperability.
Code:
#pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <ws2tcpip.h>
Roll no:10015603121
#define MAX_RQRS_LEN 0x1000
#define SERVER_PORT 50000
typedef struct {
LONG32 rqLen;
BYTE record[MAX_RQRS_LEN];
} REQUEST;
typedef struct {
LONG32 rsLen;
BYTE record[MAX_RQRS_LEN];
} RESPONSE;
SOCKET clientSock;
struct sockaddr_in clientSAddr;
BOOL quit = FALSE;
BOOL SendRequestMessage(REQUEST*, SOCKET);
BOOL ReceiveResponseMessage(RESPONSE*, SOCKET);
Roll no:10015603121
int main(int argc, char* argv[]) {
WSADATA WSStartData;
REQUEST request;
RESPONSE response;
WSAStartup(MAKEWORD(2, 0), &WSStartData);
clientSock = socket(AF_INET, SOCK_STREAM, 0);
if (clientSock == INVALID_SOCKET) {
printf("Failed to create socket\n");
WSACleanup();
return 1;
memset(&clientSAddr, 0, sizeof(clientSAddr));
clientSAddr.sin_family = AF_INET;
clientSAddr.sin_port = htons(SERVER_PORT);
if (argc >= 2) {
inet_pton(AF_INET, argv[1], &clientSAddr.sin_addr);
Roll no:10015603121
}
else {
inet_pton(AF_INET, "127.0.0.1", &clientSAddr.sin_addr);
if (connect(clientSock, (struct sockaddr*)&clientSAddr, sizeof(clientSAddr)) ==
SOCKET_ERROR) {
printf("Failed to connect to server\n");
closesocket(clientSock);
WSACleanup();
return 1;
while (!quit) {
printf("Enter Command: ");
fgets(request.record, MAX_RQRS_LEN - 1, stdin);
request.record[strlen(request.record) - 1] = '\0';
if (strcmp(request.record, "$Quit") == 0) {
quit = TRUE;
Roll no:10015603121
continue;
if (!SendRequestMessage(&request, clientSock)) {
printf("Failed to send request\n");
break;
if (!quit && !ReceiveResponseMessage(&response, clientSock)) {
printf("Failed to receive response\n");
break;
shutdown(clientSock, SD_BOTH);
closesocket(clientSock);
WSACleanup();
printf("\n****Leaving client\n");
return 0;
Roll no:10015603121
BOOL SendRequestMessage(REQUEST* pRequest, SOCKET sd) {
int result = send(sd, (char*)pRequest, sizeof(REQUEST), 0);
return result != SOCKET_ERROR;
BOOL ReceiveResponseMessage(RESPONSE* pResponse, SOCKET sd) {
int result = recv(sd, (char*)pResponse, sizeof(RESPONSE), 0);
return result != SOCKET_ERROR;
Output:
Roll no:10015603121
EXPERIMENT 10
Aim:Socket-Based Server with In-Process Servers
Theory:Socket-based servers are integral for in-process servers in Windows
system programming because they enable inter-process communication
within the same machine. Using sockets, servers can listen for incoming
connections and handle client requests efficiently. They facilitate the
development of scalable and modular systems by allowing multiple client
connections concurrently. Socket-based servers support various
communication protocols like TCP/IP or UDP, ensuring flexibility and
interoperability. In-process servers benefit from the lightweight and efficient
nature of socket communication, enhancing overall system performance.
Socket-based servers are essential for building robust and responsive
in-process server applications in Windows environments.
Code:
#pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <ws2tcpip.h>
Roll no:10015603121
struct sockaddr_in srvSAddr;
WSADATA WSStartData;
#define MAX_CLIENTS 10
#define SERVER_PORT 50000
#define MAX_RQRS_LEN 0x1000
typedef struct {
SOCKET sock;
BOOL threadActive;
} THREAD_INFO;
typedef struct {
LONG32 rqLen;
BYTE record[MAX_RQRS_LEN];
} REQUEST;
typedef struct {
LONG32 rsLen;
BYTE record[MAX_RQRS_LEN];
} RESPONSE;
Roll no:10015603121
SOCKET clientSock;
struct sockaddr_in clientSAddr;
BOOL quit = FALSE;
static BOOL ReceiveRequestMessage(REQUEST* pRequest, SOCKET sd);
static BOOL SendResponseMessage(RESPONSE* pResponse, SOCKET sd);
static DWORD WINAPI ServerThread(LPVOID lpParam);
int main() {
DWORD tStatus;
SOCKET SrvSock = INVALID_SOCKET;
THREAD_INFO threads[MAX_CLIENTS];
if (WSAStartup(MAKEWORD(2, 0), &WSStartData) != 0) {
printf("WSAStartup failed\n");
return 1;
SrvSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (SrvSock == INVALID_SOCKET) {
printf("Failed to create server socket\n");
Roll no:10015603121
WSACleanup();
return 1;
srvSAddr.sin_family = AF_INET;
srvSAddr.sin_addr.s_addr = htonl(INADDR_ANY);
srvSAddr.sin_port = htons(SERVER_PORT);
if (bind(SrvSock, (struct sockaddr*)&srvSAddr, sizeof(srvSAddr)) ==
SOCKET_ERROR) {
printf("Bind failed\n");
closesocket(SrvSock);
WSACleanup();
return 1;
if (listen(SrvSock, SOMAXCONN) == SOCKET_ERROR) {
printf("Listen failed\n");
closesocket(SrvSock);
WSACleanup();
return 1;
Roll no:10015603121
for (int i = 0; i < MAX_CLIENTS; ++i) {
threads[i].sock = INVALID_SOCKET;
threads[i].threadActive = FALSE;
while (1) {
int freeThread = -1;
for (int i = 0; i < MAX_CLIENTS; ++i) {
if (!threads[i].threadActive) {
freeThread = i;
break;
if (freeThread != -1) {
threads[freeThread].sock = accept(SrvSock, NULL, NULL);
if (threads[freeThread].sock == INVALID_SOCKET) {
printf("Accept failed\n");
continue;
Roll no:10015603121
threads[freeThread].threadActive = TRUE;
DWORD dwThreadId;
HANDLE hThread = CreateThread(NULL, 0, ServerThread,
&threads[freeThread], 0, &dwThreadId);
if (hThread == NULL) {
printf("Failed to create server thread\n");
closesocket(threads[freeThread].sock);
threads[freeThread].sock = INVALID_SOCKET;
threads[freeThread].threadActive = FALSE;
else {
CloseHandle(hThread);
else {
printf("Too many clients\n");
Sleep(1000);
Roll no:10015603121
closesocket(SrvSock);
WSACleanup();
return 0;
static DWORD WINAPI ServerThread(LPVOID lpParam) {
THREAD_INFO* pInfo = (THREAD_INFO*)lpParam;
SOCKET clientSock = pInfo->sock;
REQUEST request;
RESPONSE response;
while (1) {
if (!ReceiveRequestMessage(&request, clientSock)) {
printf("Failed to receive request\n");
break;
if (strcmp(request.record, "$Quit") == 0) {
break;
Roll no:10015603121
if (!SendResponseMessage(&response, clientSock)) {
printf("Failed to send response\n");
break;
closesocket(clientSock);
pInfo->threadActive = FALSE;
return 0;
static BOOL ReceiveRequestMessage(REQUEST* pRequest, SOCKET sd) {
int result = recv(sd, (char*)pRequest, sizeof(REQUEST), 0);
return result != SOCKET_ERROR;
static BOOL SendResponseMessage(RESPONSE* pResponse, SOCKET sd) {
int result = send(sd, (char*)pResponse, sizeof(RESPONSE), 0);
return result != SOCKET_ERROR;
Roll no:10015603121
Output:
Roll no:10015603121
EXPERIMENT 11
Aim:Write code for A Service Wrapper using existing services
Theory:Windows services, integral to Windows System Programming, are
background processes that run independently of user sessions. They offer
various functionalities, including server processes, device drivers, and
system utilities. Managed through the Service Control Manager, they can
start automatically at system boot or be triggered by specific events.
Services adhere to a defined interface, implementing functions like service
initialization, control handling, and status reporting. They provide essential
system functionalities, such as networking, security, and system
maintenance, contributing to the stability and functionality of the Windows
operating system. Understanding their lifecycle, communication protocols,
and security implications is crucial for effective Windows System
Programming.
Code:
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <time.h>
#define UPDATE_TIME 1000
Roll no:10015603121
BOOL shutDown = FALSE, pauseFlag = FALSE;
SERVICE_STATUS hServStatus;
SERVICE_STATUS_HANDLE hSStat;
TCHAR serviceName[] = _T("SimpleService");
TCHAR logFileName[] = _T(".\\LogFiles\\SimpleServiceLog.txt");
BOOL consoleApp = FALSE, isService;
VOID WINAPI ServiceMain(DWORD argc, LPTSTR argv[]);
VOID WINAPI ServerCtrlHandler(DWORD);
VOID UpdateStatus(DWORD, DWORD);
VOID LogEvent(LPCTSTR, WORD);
int main(int argc, char* argv[]) {
// Initialize log file
FILE* logFp = _tfopen(logFileName, _T("a+"));
if (logFp != NULL) LogEvent(_T("Initialized Logging"), EVENTLOG_SUCCESS);
// Initialize service
SERVICE_TABLE_ENTRY DispatchTable[] = {
Roll no:10015603121
{ serviceName, ServiceMain },
{ NULL, NULL }
};
StartServiceCtrlDispatcher(DispatchTable);
return 0;
VOID WINAPI ServiceMain(DWORD argc, LPTSTR argv[]) {
// Set up service status
hSStat = RegisterServiceCtrlHandler(serviceName, ServerCtrlHandler);
if (hSStat == 0) return;
hServStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
hServStatus.dwCurrentState = SERVICE_START_PENDING;
hServStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
hServStatus.dwWin32ExitCode = NO_ERROR;
hServStatus.dwServiceSpecificExitCode = 0;
hServStatus.dwCheckPoint = 0;
Roll no:10015603121
hServStatus.dwWaitHint = 2 * UPDATE_TIME;
SetServiceStatus(hSStat, &hServStatus);
// Perform service-specific tasks
UpdateStatus(SERVICE_RUNNING, -1);
while (!shutDown) {
Sleep(UPDATE_TIME);
UpdateStatus(-1, -1);
UpdateStatus(SERVICE_STOPPED, 0);
VOID WINAPI ServerCtrlHandler(DWORD dwControl) {
switch (dwControl) {
case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_STOP:
shutDown = TRUE;
UpdateStatus(SERVICE_STOP_PENDING, -1);
break;
Roll no:10015603121
case SERVICE_CONTROL_PAUSE:
pauseFlag = TRUE;
// Handle pause functionality
break;
case SERVICE_CONTROL_CONTINUE:
pauseFlag = FALSE;
// Handle continue functionality
break;
case SERVICE_CONTROL_INTERROGATE:
// Respond to interrogation
break;
default:
// Handle user-defined control codes
break;
UpdateStatus(-1, -1);
VOID UpdateStatus(DWORD NewStatus, DWORD Check) {
if (Check < 0) hServStatus.dwCheckPoint++;
Roll no:10015603121
else hServStatus.dwCheckPoint = Check;
if (NewStatus >= 0) hServStatus.dwCurrentState = NewStatus;
if (isService) SetServiceStatus(hSStat, &hServStatus);
VOID LogEvent(LPCTSTR UserMessage, WORD type) {
TCHAR cTimeString[30];
time_t currentTime = time(NULL);
_tcsncpy_s(cTimeString, _countof(cTimeString), _tctime(¤tTime),
_TRUNCATE);
cTimeString[_tcslen(cTimeString) - 2] = _T('\0');
FILE* logFp = _tfopen(logFileName, _T("a+"));
if (logFp != NULL) {
_ftprintf(logFp, _T("%s. "), cTimeString);
if (type == EVENTLOG_SUCCESS || type == EVENTLOG_INFORMATION_TYPE)
_ftprintf(logFp, _T("%s"), _T("Information. "));
else if (type == EVENTLOG_ERROR_TYPE)
_ftprintf(logFp, _T("%s"), _T("Error. "));
Roll no:10015603121
else if (type == EVENTLOG_WARNING_TYPE)
_ftprintf(logFp, _T("%s"), _T("Warning. "));
else
_ftprintf(logFp, _T("%s"), _T("Unknown. "));
_ftprintf(logFp, _T("%s\n"), UserMessage);
fflush(logFp);
fclose(logFp);
Output:
Roll no:10015603121
Roll no:10015603121