
This lecture explains the Virtual and Physical Address Spaces. It also explains how the memory layout looks like for a processes loaded by loader in memory.
This video contains information about the loading of an executable by the loader. It also explains the parsing of the import section of the executable to load the additional dlls which it will use at run time
This video explains the Loading of DLL in virtual address space. Parsing of the import section is same as that of exe. The dependent DLLs may again need to load their dependent DLLs and they are also parsed and imported by Loader as Exe
In this video rebasing concept has been mentioned along with the usages of rebase.exe.
This video tells about the bind utility and its significance. It mentions the need and performance improvement at load time for the modules by loader.
This video describes about the default heap of a process and need of additional heaps. It also explains how to set the size for default heap through project properties.
In this video, we have discussed the motivation behind the additional heaps. The additional heaps solve many problems like fragmentation and memory corruption.
In this video, we have discussed about the important heap functions and their usages.
HeapCreate, HeapAlloc, HeapRealloc, HeapSize, HeapFree and HeapDestroy are the functions.
Code: This lecture gives you an idea on usages of Heap APIs we discussed in last video. Here is the code
#include<windows.h>
#include<iostream>
using namespace std;
//Threads
int main()
{
//Create the heap. Allocate memory for heap
//Returns HANDLE
HANDLE hHeap = HeapCreate(HEAP_GENERATE_EXCEPTIONS, 0, 0);
int err = GetLastError();
if (err != 0)
{
cout << endl << "The Heap cannot be allocated.";
}
//Allocate some memory
int* pMem = (int*)HeapAlloc(hHeap, HEAP_GENERATE_EXCEPTIONS, sizeof(int));
if (pMem == NULL)
{
cout << endl << "Failed to allocate the memory";
}
//Assign some value and print
*pMem = 10;
cout << endl << *pMem;
cout << endl << "The address:" << pMem;
//Realloc the block allocated (less size)
pMem = (int*)HeapReAlloc(hHeap, HEAP_GENERATE_EXCEPTIONS,
pMem, sizeof(char));
cout << endl << "Address-1:" << pMem;
//Realloc the block allocated (more size)
pMem = (int*)HeapReAlloc(hHeap,
HEAP_GENERATE_EXCEPTIONS,
pMem, 1240000);
cout << endl << "Address-2:" << pMem;
//HeapFree - Still heap is available for memory allocation
HeapFree(hHeap, HEAP_GENERATE_EXCEPTIONS, pMem);
//HeapDestroy - No more available to allocate memory
HeapDestroy(hHeap);
//Try to allocate now (it will throw an excpetion):
pMem = (int*)HeapAlloc(hHeap, HEAP_GENERATE_EXCEPTIONS,
200);
return 0;
}
In this video, Kernel Objects have been discussed. Along with their introduction, some essential characteristics have been discussed.
In this video we have discussed the need of sharing the Kernel Objects, how they can be shared. There must need to be a parent-child relationship for this to work
In this video, we discussed about the processes and their various components. The kernel object is associated with the process for its scheduling.
Two wait functions (WaitForSingleObject and WaitForMultipleObjects) discussed in this video.
In this video, discussed about the important arguments of CreateProcess function. Most important are CREATE_SUSPENDED flag and Primary thread handle.
In This Video, we have discussed about the creation of suspended/scheduled process, how to resume suspended process (resuming primary thread of the process)
In this video we have discussed about the create process with wait functions. Both Wait functions demonstrated with example of one and three processes
In this lecture, we will elaborate on different methods to pass a handle to child process. There are three ways you could achieve this. One by passing the HANDLE on command line, other by passing the handle through Environment variable and next by passing the handle to the primary thread of child process once it is done with all initialization and waiting for any inputs
This lecture explains through a sample code as how the inheritable kernel handle can be passed to child process through the command line.
Parent Process Code
#include <windows.h>
#include <iostream>
using namespace std;
//Waiting on the process to finish first.
//Parent Program
int main()
{
SECURITY_ATTRIBUTES sa;
sa.lpSecurityDescriptor = NULL;
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
STARTUPINFO siChild = { sizeof(siChild) };
PROCESS_INFORMATION piChild;
//This process will be created but main application will be closed
BOOL bCreated = CreateProcess(NULL, LPSTR("Notepad.exe"),
NULL, &sa, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi);
char szCommand[250] = { 0, };
sprintf_s(szCommand, "ChildProcessTest.exe %i", pi.hThread);
cout << endl << pi.hThread;
cout << endl << szCommand;
bCreated = CreateProcess(NULL, szCommand,
NULL, NULL, TRUE, 0, NULL, NULL, &siChild, &piChild);
return 0;
}
Child Process:
#include <windows.h>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
HANDLE h = HANDLE(atoi(argv[1]));
cout << endl << "The handle:" << h;
DWORD dw = ResumeThread(h);
cout << endl << "The return value of ResumeThread:" << dw;
getchar();
return 0;
}
In this lecture, we have discussed about the basic JOB Kernel object creation with some restrictions.
The code is :
#include <windows.h>
#include <iostream>
using namespace std;
//Example sample taken from Jeffery Book
int main()
{
HANDLE hJob = CreateJobObject(NULL, NULL);
if (hJob == NULL)
{
cout << endl << "Job could not be initiated";
exit(EXIT_FAILURE);
}
//Putting some restrictions on Job Object
JOBOBJECT_BASIC_LIMIT_INFORMATION jLimit = { 0 };
// The process always runs in the idle priority class.
jLimit.PriorityClass = IDLE_PRIORITY_CLASS;
// The job cannot use more than 2 second of CPU time.
jLimit.PerJobUserTimeLimit.QuadPart = 20000000; // 1 sec in 100-ns intervals
//Process inside Job cannot use more than 1 second of CPU time.
jLimit.PerProcessUserTimeLimit.QuadPart = 10000000;
// These are the only 2 restrictions I want placed on the job (process).
jLimit.LimitFlags = JOB_OBJECT_LIMIT_PRIORITY_CLASS
| JOB_OBJECT_LIMIT_JOB_TIME;
SetInformationJobObject(hJob, JobObjectBasicLimitInformation, &jLimit,
sizeof(jLimit));
//Basic UI restriction can also be placed
// Second, set some UI restrictions.
JOBOBJECT_BASIC_UI_RESTRICTIONS jobuir;
jobuir.UIRestrictionsClass = JOB_OBJECT_UILIMIT_NONE; // A fancy zero
// The process can't log off the system.
jobuir.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_EXITWINDOWS;
// The process can't access USER objects (such as other windows)
// in the system.
jobuir.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_HANDLES;
SetInformationJobObject(hJob, JobObjectBasicUIRestrictions, &jobuir,
sizeof(jobuir));
return 0;
}
This lecture, we have discuss a demo code to create a process, assign it to job object and launch it. After launching, waiting till one process in JOB gets done.
Below is the code:
#include <windows.h>
#include <iostream>
using namespace std;
//Waiting on the process to finish first.
//Parent Program
//Example sample taken from Jeffery Book
int main()
{
HANDLE hJob = CreateJobObject(NULL, NULL);
if (hJob == NULL)
{
cout << endl << "Job could not be initiated";
exit(EXIT_FAILURE);
}
//Putting some restrictions on Job Object
JOBOBJECT_BASIC_LIMIT_INFORMATION jLimit = { 0 };
// The process always runs in the idle priority class.
jLimit.PriorityClass = IDLE_PRIORITY_CLASS;
// The job cannot use more than 2 second of CPU time.
jLimit.PerJobUserTimeLimit.QuadPart = 20000000; // 1 sec in 100-ns intervals
//Process inside Job cannot use more than 1 second of CPU time.
jLimit.PerProcessUserTimeLimit.QuadPart = 10000000;
// These are the only 2 restrictions I want placed on the job (process).
jLimit.LimitFlags = JOB_OBJECT_LIMIT_PRIORITY_CLASS
| JOB_OBJECT_LIMIT_JOB_TIME;
SetInformationJobObject(hJob, JobObjectBasicLimitInformation, &jLimit,
sizeof(jLimit));
//Basic UI restriction can also be placed
// Second, set some UI restrictions.
JOBOBJECT_BASIC_UI_RESTRICTIONS jobuir;
jobuir.UIRestrictionsClass = JOB_OBJECT_UILIMIT_NONE; // A fancy zero
// The process can't log off the system.
jobuir.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_EXITWINDOWS;
// The process can't access USER objects (such as other windows)
// in the system.
jobuir.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_HANDLES;
SetInformationJobObject(hJob, JobObjectBasicUIRestrictions, &jobuir,
sizeof(jobuir));
//Creating a process
STARTUPINFO sa = { sizeof(sa) };
PROCESS_INFORMATION pi;
BOOL bCreated = CreateProcess(NULL, PSTR("Notepad.exe"),
NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL,
&sa, &pi);
if (bCreated)
{
AssignProcessToJobObject(hJob, pi.hProcess);
}
ResumeThread(pi.hThread);
CloseHandle(pi.hThread);
HANDLE hArr[2] = { hJob, pi.hProcess };
DWORD dw = WaitForMultipleObjects(2, hArr, FALSE, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(hJob);
return 0;
}
This lecture contains the information about the various structures and APIs which are used to query the job stats.
In this lecture, we have discussed querying the stats of a job object.
Source code:
#include <windows.h>
#include <iostream>
using namespace std;
//Waiting on the process to finish first.
//Parent Program
//Sample code referred from Jeffery Book
void PrintJobObjectInfo(HANDLE hJob)
{
// Calculate the number of bytes needed for structure & process IDs.
DWORD cb = sizeof(JOBOBJECT_BASIC_PROCESS_ID_LIST) +
(2) * sizeof(DWORD);
// Allocate the block of memory.
PJOBOBJECT_BASIC_PROCESS_ID_LIST pjobpil =
(PJOBOBJECT_BASIC_PROCESS_ID_LIST)_alloca(cb);
// Tell the function the maximum number of processes
// that we allocated space for.
pjobpil->NumberOfAssignedProcesses = 2;
// Request the current set of process IDs.
QueryInformationJobObject(hJob, JobObjectBasicProcessIdList,
pjobpil, cb, &cb);
// Enumerate the process IDs.
for (int nIndex = 0; nIndex < pjobpil->NumberOfProcessIdsInList; nIndex++) {
// Use pjobpil->ProcessIdList[x]...
cout << endl << "The Process ID:"<<pjobpil->ProcessIdList[nIndex];
}
}
int main()
{
HANDLE hJob = CreateJobObject(NULL, NULL);
if (hJob == NULL)
{
cout << endl << "Job could not be initiated";
exit(EXIT_FAILURE);
}
//Putting some restrictions on Job Object
JOBOBJECT_BASIC_LIMIT_INFORMATION jLimit = { 0 };
// The process always runs in the idle priority class.
jLimit.PriorityClass = IDLE_PRIORITY_CLASS;
// The job cannot use more than 2 second of CPU time.
jLimit.PerJobUserTimeLimit.QuadPart = 20000000; // 1 sec in 100-ns intervals
//Process inside Job cannot use more than 1 second of CPU time.
jLimit.PerProcessUserTimeLimit.QuadPart = 10000000;
// These are the only 2 restrictions I want placed on the job (process).
jLimit.LimitFlags = JOB_OBJECT_LIMIT_PRIORITY_CLASS
| JOB_OBJECT_LIMIT_JOB_TIME;
SetInformationJobObject(hJob, JobObjectBasicLimitInformation, &jLimit,
sizeof(jLimit));
//Basic UI restriction can also be placed
// Second, set some UI restrictions.
JOBOBJECT_BASIC_UI_RESTRICTIONS jobuir;
jobuir.UIRestrictionsClass = JOB_OBJECT_UILIMIT_NONE; // A fancy zero
// The process can't log off the system.
jobuir.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_EXITWINDOWS;
// The process can't access USER objects (such as other windows)
// in the system.
jobuir.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_HANDLES;
SetInformationJobObject(hJob, JobObjectBasicUIRestrictions, &jobuir,
sizeof(jobuir));
//Creating a process
STARTUPINFO sa = { sizeof(sa) };
PROCESS_INFORMATION pi;
BOOL bCreated = CreateProcess(NULL, PSTR("Notepad.exe"),
NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL,
&sa, &pi);
if (bCreated)
{
AssignProcessToJobObject(hJob, pi.hProcess);
}
//Launch the Notepad process
ResumeThread(pi.hThread);
CloseHandle(pi.hThread);
//Print the Job Object information
PrintJobObjectInfo(hJob);
HANDLE hArr[2] = { hJob, pi.hProcess};
DWORD dw = WaitForMultipleObjects(2, hArr, FALSE, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(hJob);
return 0;
}
In this lecture we have discussed the concepts on threads and it's theoretical knowledge. The need of threads and the various APIs that you will use.
In this example, we demo the simple thread creation in the main function. Also explained as how the main thread will wait till all other threads are done.
In this example, we will see how the two threads could communicate with each other. One thread can send the message to other thread and other thread can print that. A simple introduction to GetMessage and PostThreadMessage also there along with the implementation.
This lecture is all about the basic concepts related to the critical section.
In this video you can see a sample program to use the critical section. I have used two threads. Reader and Writer. Writer writes and reader reads but their access to the array (from/to where they read/write) has been synchronized.
In this lecture another example to send and receive the mesaage by the two threads has been demoed.
In this lecture, we have discussed about the Mutex basic concepts. How they are different from other Kernel Object. Discussed about the APIs used to Create and Release the mutexes.
In this lecture, we will demonstrate the use of WAIT_ABANDONED, WaitForSingleObject for mutex kernel object, Recursion counter for Mutexes and to take care about ReleaseMutex.
In this video we will see the two processes synchronizing the access to a single file. One of them reading from the file and other one writing to the file.
In this Lecture , we have discussed about the Semaphore Kernel Object in windows. The signaling rules have been discussed about semaphore.
CreateSemaphore and ReleaseSemaphore are the two function.
This lecture contains the practical implementation of Semaphore.
In this lecture, we have discussed about the Event Kernel Object basics and Type of Event Objects. There are two types: Manual and Auto-reset kernel objects. Also discussed about the APIs used to manage the Event Kernel Objects.
In this lecture, we will see as to how the Manual or Auto-Reset event objects could be created.
How we could set them signaled or non signaled right at the time of creation.
We also showcase as how all the threads gets scheduled when Manual Reset Event Object gets signaled.
How the SetEvent and ResetEvent could be used to synchronize the three thread communicating to each other using the manual reset event object.
In this Video, you will see how to run only one instance of an exe. Used Mutex for synchronization. Code is available under Resources section
In this lecture we have created a program where two processes are working as flip flop. First process will show message flip and then second will show "flop" and will keep going on for 10 times (just for demo)
In this course we have covered the basics of Windows Programming with sample code to make you comfortable with the Windows synchronization concepts. Also, various other concepts like memory layout etc have been covered in this course.
After attending this course, you will be able to work on Windows Operating System Fundamentals (Like Processes, Kernel Memory, Threads, Kernel Objects etc).
The Objective of this course is to make available all those concepts with code implementation which are usually challenging to understand by many professionals. The concepts related to windows programming in C++ with kernel are really challenging, but with this course, you will find a big sigh of relief.
In this course, under the resources section, we have provided the downloadable code files
You can download them, run yourself on you system to see the code in execution.
Starting from the basics of Windows Programming Like Memory Layout of a process, it covers major concepts related to the windows threading and synchronization.
This course involves the topics like Process, Jobs, Memory Layout, Concept of Heaps, Threads and Thread synchronization objects (Kernel and User mode objects).
The user mode synchronization objects like CRITICAL_SECTION can synchronize the threads in same process.
If you have to synchronize the threads among different processes, then you need to use the Kernel Objects like Mutes, Semaphores, Events etc.