21 #include"../NTSecuritySettings.hpp"
22 #include"../RegistryKey.hpp"
23 #include"../DumpWinMsg.hpp"
24 #include"../NTLocking.hpp"
58 inline const std::string &
Name(
void)
const noexcept(
true);
60 virtual inline unsigned long Capacity(
void)
const noexcept(
true);
66 inline bool IsCreator(
void)
const noexcept(
true);
74 inline operator const contents *()
const;
80 virtual inline std::ostream &operator<<(
std::ostream &strm)
const;
85 inline unsigned long UsageCount(
void)
const noexcept(
true);
105 inline contents *
MapDataPtr(HANDLE file,
const DWORD access,
const DWORD hi_offset,
const DWORD low_offset,
const unsigned long size);
110 const std::string name;
112 unsigned long raw_size;
114 unsigned long pub_size;
116 HANDLE rw_raw_mapping;
118 inline bool Create(HANDLE file,
const SECURITY_ATTRIBUTES *
const security,
const DWORD protection);
119 inline void Delete(
void);
122 inline RawSharedMemory(
const RawSharedMemory &) : ss( NULL ) {assert(
false);}
137 inline contents *
Allocate(
const unsigned long n,
const void *
const hint);
138 inline void Construct(contents *
const ptr,
const contents &val);
139 inline void Deallocate(
const contents *
const p,
const unsigned long n);
162 virtual inline contents *
BaseAllocate(
const unsigned long n,
const void *
const hint) = 0;
163 virtual inline unsigned long BaseDeallocate(
const contents *
const p,
const unsigned long n) = 0;
186 inline unsigned long Capacity(
void)
const noexcept(
true);
189 struct private_data_block_type {
196 inline contents *BaseAllocate(
const unsigned long n,
const void *
const hint);
197 inline unsigned long BaseDeallocate(
const contents *
const p,
const unsigned long n);
198 static inline std::pair<
std::string,
std::string> GetMgrAreaName(
const bool first, contents *
const rw_raw_data);
200 inline bool Capacity(
const unsigned long sz,
const DWORD protection = PAGE_READWRITE, HANDLE file = INVALID_HANDLE_VALUE);
211 inline unsigned long Capacity(
void)
const noexcept(
true);
216 struct free_memory_list_type {
217 free_memory_list_type *next;
221 free_memory_list_type *free_list;
223 inline contents *BaseAllocate(
const unsigned long n,
const void *
const hint);
224 inline unsigned long BaseDeallocate(
const contents *
const p,
const unsigned long n);
226 inline bool Capacity(
const unsigned long sz,
const DWORD protection = PAGE_READWRITE, HANDLE file = INVALID_HANDLE_VALUE);
258 template <
class heap_type,
class heap_contents >
class SMAllocator :
private std::allocator<heap_type::contents_type> {
271 inline SMAllocator()
noexcept(
true) : heap( heap_type::GetHeapID() ) {}
278 value_type::allocator_type::value_type *
const ptr=_P->get_allocator()._Charalloc(_V.size());
279 _P->get_allocator().construct(ptr, _V);
286 }
while (i!=_V.end());
293 template <
class alloc>
inline bool operator==(
const alloc &a)
const {
return heap.Name()==a.heap.Name();}
294 template <
class alloc>
inline bool operator!=(
const alloc &a)
const {
return !operator==(a);}
295 inline const heap_type &
Heap()
const noexcept(
true) {
return heap;}
301 template <
class ook,
class ook1 >
inline SMAllocator &operator=(
const SMAllocator< ook, ook1 > &)
noexcept(
true) {assert(
false);
return *
this;}
306 NTUtils::MutexLock lock(mutex.Name(), INFINITE,
const_cast<SECURITY_ATTRIBUTES *
const>(&(ss->SA())));
307 Create(file, &(ss->SA()), protection);
315 assert(
reinterpret_cast<private_data_block_type *>(rw_raw_data)->usage_ctr);
328 template <
class contents >
inline bool RawSharedMemory<contents>::
Capacity(
const unsigned long sz,
const DWORD protection, HANDLE file) {
329 NTUtils::MutexLock lock(mutex.Name(), INFINITE,
const_cast<SECURITY_ATTRIBUTES *
const>(&(ss->SA())));
335 std::auto_ptr<contents> tmp(
new contents[raw_size]);
339 unsigned long old_raw_size=raw_size;
341 if (Create(file, &(ss->SA()), protection)) {
342 std::cerr <<
"RawSharedMemory<...>::Capacity(...) : Failed to re-size the shared memory area to: " << raw_size <<
", named: '" << name <<
"' - 'Create(...)' failed." << std::endl;
348 std::cerr <<
"RawSharedMemory<...>::Capacity(...) : Failed to re-size the shared memory area to: " << raw_size <<
", named: '" << name <<
"' - reference count of: "<<
reinterpret_cast<private_data_block_type *>(rw_raw_data)->usage_ctr <<
", must be 1." << std::endl;
375 }
while (++i<pub_size);
380 std::cerr <<
"RawSharedMemory<...>::operator>>(...) : Not implemented!!!" << std::endl;
385 }
while (++i<pub_size);
395 NTUtils::MutexLock lock(mutex.Name(), INFINITE,
const_cast<SECURITY_ATTRIBUTES *
const>(&(ss->SA())));
396 Create(file, &(ss->SA()), protection);
403 template <
class contents >
inline contents *
RawSharedMemory<contents>::
MapDataPtr(HANDLE mapping,
const DWORD access,
const DWORD hi_offset,
const DWORD low_offset,
const unsigned long size) {
409 contents *raw_data=
static_cast<contents *>(::MapViewOfFile(mapping, access, hi_offset, low_offset, size));
411 unsigned long err=::GetLastError();
412 std::cerr <<
"RawSharedMemory<...>::MapDataPtr(...) : Failed to map view of file. Name: '" << name
413 <<
"'. With access: 0x" << std::setw(8) << std::setfill(
'0') << std::setbase(std::ios_base::hex)
414 << access <<
" and offset: 0x" << hi_offset <<
":" << low_offset <<
", size: 0x"
415 << size <<
". Windows error: '" << NTUtils::DumpWinMessage(err) <<
"'." << std::endl;
422 ::UnmapViewOfFile(raw_data);
426 template <
class contents >
inline bool RawSharedMemory<contents>::Create(HANDLE file,
const SECURITY_ATTRIBUTES *
const security, DWORD protection) {
428 ::GetSystemInfo(&info);
430 raw_size=((raw_size-pub_size*
sizeof(contents))/info.dwAllocationGranularity+1)*info.dwAllocationGranularity+pub_size*
sizeof(contents);
431 rw_raw_mapping=::CreateFileMapping(file,
const_cast<SECURITY_ATTRIBUTES *
const>(security), protection, 0, raw_size, name.c_str());
432 if (!rw_raw_mapping || rw_raw_mapping==INVALID_HANDLE_VALUE) {
433 std::cerr <<
"RawSharedMemory<...>::Create() : Failed to allocate the read/write raw memory mapped file. Size: " << raw_size <<
", name: '" << name <<
"'." << std::endl;
436 creator=(::GetLastError() != ERROR_ALREADY_EXISTS);
439 rw_pub_mapping=::CreateFileMapping(file,
const_cast<SECURITY_ATTRIBUTES *
const>(security), protection, 0, raw_size, name.c_str());
440 ro_pub_mapping=::CreateFileMapping(file,
const_cast<SECURITY_ATTRIBUTES *
const>(security), protection, 0, raw_size, name.c_str());
442 rw_raw_data=MapDataPtr(rw_raw_mapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
444 rw_pub_data=MapDataPtr(rw_pub_mapping, FILE_MAP_ALL_ACCESS, 0, raw_size-pub_size*
sizeof(contents), pub_size*
sizeof(contents));
445 ro_pub_data=MapDataPtr(ro_pub_mapping, FILE_MAP_READ, 0, raw_size-pub_size*
sizeof(contents), pub_size*
sizeof(contents));
454 template <
class contents >
inline void RawSharedMemory<contents>::Delete(
void) {
458 ::CloseHandle(ro_pub_mapping);
459 ::CloseHandle(rw_pub_mapping);
460 ::CloseHandle(rw_raw_mapping);
463 template <
class contents >
inline unsigned long RawSharedMemory<contents>::GetEndPrivateDataBlock(
void) {
468 NTUtils::MutexLock lock(mutex.Name(), INFINITE,
const_cast<SECURITY_ATTRIBUTES *
const>(&(ss->SA())));
470 reinterpret_cast<private_data_block_type *>(rw_raw_data+RawSharedMemory<contents>::GetEndPrivateDataBlock())->used_memory=0;
471 memcpy(&(
reinterpret_cast<private_data_block_type *>(rw_raw_data+RawSharedMemory<contents>::GetEndPrivateDataBlock())->manager_name), mgr_name.c_str(), mgr_name.size()+1);
472 }
else if (strcmp(&(
reinterpret_cast<private_data_block_type *>(rw_raw_data+RawSharedMemory<contents>::GetEndPrivateDataBlock())->manager_name), mgr_name.c_str())) {
473 std::cerr <<
"ManagedSharedMemory<...>::ManagedSharedMemory(...) : Attempting to use wrong memory manager '"<< mgr_name <<
"', on existing shared memory, which is managed by '" << &(
reinterpret_cast<private_data_block_type *>(rw_raw_data+RawSharedMemory<contents>::GetEndPrivateDataBlock())->manager_name) <<
"'." << std::endl;
484 reinterpret_cast<private_data_block_type *>(rw_raw_data+RawSharedMemory<contents>::GetEndPrivateDataBlock())->used_memory+=n;
492 reinterpret_cast<private_data_block_type *>(rw_raw_data+RawSharedMemory<contents>::GetEndPrivateDataBlock())->used_memory-=amnt;
515 memcpy(ptr, &tmp,
sizeof(contents));
523 NTUtils::MutexLock lock(mutex.Name(), INFINITE,
const_cast<SECURITY_ATTRIBUTES *
const>(&(ss->SA())));
525 reinterpret_cast<private_data_block_type *>(rw_raw_data+RawSharedMemory<contents>::GetEndPrivateDataBlock())->used_memory=0;
526 memcpy(&(
reinterpret_cast<private_data_block_type *>(rw_raw_data+RawSharedMemory<contents>::GetEndPrivateDataBlock())->manager_name), mgr_name.c_str(), mgr_name.size()+1);
527 }
else if (strcmp(&(
reinterpret_cast<private_data_block_type *>(rw_raw_data+RawSharedMemory<contents>::GetEndPrivateDataBlock())->manager_name), mgr_name.c_str())) {
528 std::cerr <<
"ManagedSharedMemory<...>::ManagedSharedMemory(...) : Attempting to use wrong memory manager '"<< mgr_name <<
"', on existing shared memory, which is managed by '" <<
reinterpret_cast<private_data_block_type *>(rw_raw_data+RawSharedMemory<contents>::GetEndPrivateDataBlock())->manager_name <<
"'." << std::endl;
533 template <
class contents >
inline unsigned long ManagedSharedMemory<contents>::GetEndPrivateDataBlock(
void) {
537 template <
class contents >
inline CrapManagedSharedMemory<contents>::
CrapManagedSharedMemory(
const HeapID &details) :
ManagedSharedMemory<
contents>( 2*
sizeof(
NTUtils::
guid_type),
typeid(
this).
name(),
details,
PAGE_READWRITE,
INVALID_HANDLE_VALUE),
in_use_list(
HeapID(
details.
size*(1+
sizeof(
allocated_data_block_info)/
sizeof(
unsigned long)),
GetMgrAreaName(
IsCreator(),
rw_raw_data),
ss),
PAGE_READWRITE,
INVALID_HANDLE_VALUE ) {
538 NTUtils::MutexLock lock(mutex.Name(), INFINITE,
const_cast<SECURITY_ATTRIBUTES *
const>(&(ss->SA())));
540 memset((
unsigned long *)in_use_list, CMSM_free_marker, in_use_list.Capacity()*
sizeof(
unsigned long));
547 if (
reinterpret_cast<RawSharedMemory<contents>::private_data_block_type *>(rw_raw_data)->usage_ctr==1) {
549 const unsigned long *used=(
const unsigned long *)in_use_list;
552 unsigned long beginning_of_block=CMSM_free_marker;
553 if (beginning_of_block!=used[s+
sizeof(allocated_data_block_info)/
sizeof(
unsigned long)]) {
554 beginning_of_block=used[s+
sizeof(allocated_data_block_info)/
sizeof(
unsigned long)];
556 if (beginning_of_block!=CMSM_free_marker) {
557 std::cerr <<
"Allocating process ID: 0x" << std::setw(8) << std::setfill(
'0') << std::setbase(std::ios_base::hex) <<
reinterpret_cast<
const allocated_data_block_info *>(used+s)->allocating_pid << std::endl;
558 std::cerr <<
"Allocating process handle: 0x" << std::setw(8) << std::setfill(
'0') << std::setbase(std::ios_base::hex) <<
reinterpret_cast<
const allocated_data_block_info *>(used+s)->allocating_phandle << std::endl;
559 std::cerr <<
"Allocating thread ID: 0x" << std::setw(8) << std::setfill(
'0') << std::setbase(std::ios_base::hex) <<
reinterpret_cast<
const allocated_data_block_info *>(used+s)->allocating_tid << std::endl;
560 std::cerr <<
"Allocating thread handle: 0x" << std::setw(8) << std::setfill(
'0') << std::setbase(std::ios_base::hex) <<
reinterpret_cast<
const allocated_data_block_info *>(used+s)->allocating_thandle << std::endl;
561 std::cerr <<
"Allocating process name: '" <<
reinterpret_cast<
const allocated_data_block_info *>(used+s)->allocating_pname <<
"'" << std::endl;
562 std::cerr <<
"Line number in allocating file: " <<
reinterpret_cast<
const allocated_data_block_info *>(used+s)->allocating_line << std::endl;
563 std::cerr <<
"Allocating source file name: '" <<
reinterpret_cast<
const allocated_data_block_info *>(used+s)->allocating_src <<
"'" << std::endl;
564 std::cerr <<
"Address: 0x" << std::setw(8) << std::setfill(
'0') << std::setbase(std::ios_base::hex) << ((contents *)*
this)+s << std::endl;
565 std::cerr <<
"Block size: " << (
reinterpret_cast<
const allocated_data_block_info *>(used+s)->block_size<<2) <<
" bytes." << std::endl;
566 std::cerr <<
"Data: <";
567 const unsigned long start=s;
568 while (beginning_of_block==used[s+
sizeof(allocated_data_block_info)/
sizeof(
unsigned long)]) {
569 std::cerr << *
reinterpret_cast<
char *>(&(((contents *)*
this)[s]));
572 std::cerr <<
">" << std::endl;
573 std::cerr <<
"Hex: <";
574 for (s=start;beginning_of_block==used[s];++s) {
575 std::cerr <<
" 0x" << std::setw(8) << std::setfill(
'0') << std::setbase(std::ios_base::hex) << *
reinterpret_cast<
unsigned long *>(&(((contents *)*
this)[s]));
577 std::cerr <<
">" << std::endl;
579 s+=
sizeof(allocated_data_block_info)/
sizeof(
unsigned long);
580 assert(used[s]==CMSM_free_marker);
581 }
while (++s<in_use_list.Capacity());
591 template <
class contents >
inline contents *
CrapManagedSharedMemory<contents>::BaseAllocate(
const unsigned long m,
const void *
const ) {
601 NTUtils::MutexLock lock(in_use_list.Lock().Name(), INFINITE,
const_cast<SECURITY_ATTRIBUTES *
const>(&(ss->SA())));
605 unsigned long *used=(
unsigned long *)in_use_list;
606 unsigned long s=
sizeof(allocated_data_block_info)/
sizeof(
unsigned long);
610 if (used[s]==CMSM_free_marker) {
613 if ((s+m)<=in_use_list.Capacity()) {
616 bool big_enough=
true;
618 if (used[e]!=CMSM_free_marker) {
631 reinterpret_cast<allocated_data_block_info *>(used+s-
sizeof(allocated_data_block_info)/
sizeof(
unsigned long))->allocating_pid=::GetCurrentProcessId();
632 reinterpret_cast<allocated_data_block_info *>(used+s-
sizeof(allocated_data_block_info)/
sizeof(
unsigned long))->allocating_phandle=::GetCurrentProcess();
633 reinterpret_cast<allocated_data_block_info *>(used+s-
sizeof(allocated_data_block_info)/
sizeof(
unsigned long))->allocating_tid=::GetCurrentThreadId();
634 reinterpret_cast<allocated_data_block_info *>(used+s-
sizeof(allocated_data_block_info)/
sizeof(
unsigned long))->allocating_thandle=::GetCurrentThread();
635 ::GetModuleFileName(NULL,
reinterpret_cast<allocated_data_block_info *>(used+s-
sizeof(allocated_data_block_info)/
sizeof(
unsigned long))->allocating_pname, MAX_PATH);
636 reinterpret_cast<allocated_data_block_info *>(used+s-
sizeof(allocated_data_block_info)/
sizeof(
unsigned long))->block_size=m;
639 reinterpret_cast<allocated_data_block_info *>(used+s-
sizeof(allocated_data_block_info)/
sizeof(
unsigned long))->allocating_line=__LINE__;
640 strcpy(
reinterpret_cast<allocated_data_block_info *>(used+s-
sizeof(allocated_data_block_info)/
sizeof(
unsigned long))->allocating_src,__FILE__);
647 return ((contents *)*
this)+s;
656 s+=
sizeof(allocated_data_block_info)/
sizeof(
unsigned long)+
reinterpret_cast<allocated_data_block_info *>(used-s)->block_size;
662 }
while (++s<in_use_list.Capacity());
667 template <
class contents >
inline unsigned long CrapManagedSharedMemory<contents>::BaseDeallocate(
const contents *
const p,
const unsigned long m) {
669 NTUtils::MutexLock lock(in_use_list.Lock().Name(), INFINITE,
const_cast<SECURITY_ATTRIBUTES *
const>(&(ss->SA())));
671 std::cerr<<p<<
" "<<m<<std::endl;
672 contents *
const beginning=(contents *)*
this;
676 assert(p>=beginning);
677 assert(m*
sizeof(contents)<Capacity());
678 const unsigned long mgr_ptr=p-beginning;
679 assert((mgr_ptr+m*
sizeof(contents))<Capacity());
680 unsigned long *used=(
unsigned long *)in_use_list;
681 assert(mgr_ptr<in_use_list.Capacity());
682 assert((mgr_ptr+m*
sizeof(contents))<in_use_list.Capacity());
683 std::cerr << used[(mgr_ptr+(m-1)*
sizeof(allocated_data_block_info))/
sizeof(
unsigned long)] <<
" " << mgr_ptr << std::endl;
684 assert(used[(mgr_ptr+m*
sizeof(allocated_data_block_info))/
sizeof(
unsigned long)]==mgr_ptr);
685 unsigned long s=mgr_ptr+
sizeof(allocated_data_block_info)/
sizeof(
unsigned long);
687 if (used[s]!=mgr_ptr) {
690 unsigned long i=(s-mgr_ptr-
sizeof(allocated_data_block_info)/
sizeof(
unsigned long));
691 std::cerr<<i<<std::endl;
693 std::cerr<<i<<std::endl;
696 memset(used+mgr_ptr, CMSM_free_marker, (s-mgr_ptr)*
sizeof(
unsigned long)+
sizeof(allocated_data_block_info));
699 memset(beginning+mgr_ptr, 0, (s-mgr_ptr)*
sizeof(contents));
705 assert(used[s]!=CMSM_free_marker);
706 }
while (++s<in_use_list.Capacity());
712 template <
class contents >
inline std::pair<
std::string,
std::string>
CrapManagedSharedMemory<contents>::GetMgrAreaName(
const bool first, contents *
const rw_raw_data) {
713 std::pair<
std::string,
std::string> names;
715 names.first=NTUtils::GetGUID();
716 names.second=NTUtils::GetGUID();
718 memcpy(
reinterpret_cast<private_data_block_type *>(rw_raw_data+ManagedSharedMemory<contents>::GetEndPrivateDataBlock()+strlen(&(
reinterpret_cast<ManagedSharedMemory<contents>::private_data_block_type *>(rw_raw_data+RawSharedMemory<contents>::GetEndPrivateDataBlock())->manager_name)))->mem_id, names.first.c_str(),
sizeof(NTUtils::guid_type));
719 memcpy(
reinterpret_cast<private_data_block_type *>(rw_raw_data+ManagedSharedMemory<contents>::GetEndPrivateDataBlock()+strlen(&(
reinterpret_cast<ManagedSharedMemory<contents>::private_data_block_type *>(rw_raw_data+RawSharedMemory<contents>::GetEndPrivateDataBlock())->manager_name)))->mtx_id, names.second.c_str(),
sizeof(NTUtils::guid_type));
724 assert(strlen(raw_name)==(
sizeof(NTUtils::guid_type)-1));
725 names.first=raw_name;
727 assert(strlen(raw_name)==(
sizeof(NTUtils::guid_type)-1));
728 names.second=raw_name;
733 template <
class contents >
inline bool CrapManagedSharedMemory<contents>::Capacity(
const unsigned long,
const DWORD, HANDLE) {
734 std::cerr <<
"CrapManagedSharedMemory<...>::Capacity(...) : Not supported!!!" << std::endl;
740 free_list=
reinterpret_cast<free_memory_list_type *>(rw_pub_data);
741 free_list->next=free_list;
747 if (
reinterpret_cast<RawSharedMemory<contents>::private_data_block_type *>(rw_raw_data)->usage_ctr==1) {
749 assert(free_list->size==Capacity());
758 template <
class contents >
inline contents *
KnRManagedSharedMemory<contents>::BaseAllocate(
const unsigned long m,
const void *
const ) {
768 NTUtils::MutexLock lock(mutex.Name(), INFINITE,
const_cast<SECURITY_ATTRIBUTES *
const>(&(ss->SA())));
769 const unsigned long nunits=m*
sizeof(contents)+
sizeof(free_memory_list_type);
770 free_memory_list_type *prevp=free_list;
772 for (free_memory_list_type *p=prevp->next; ;prevp=p, p=p->next) {
773 if (p->size>=nunits) {
775 if (p->size==nunits) {
781 p+=p->size/
sizeof(free_memory_list_type);
787 memset(
reinterpret_cast<
void *>(p+1), 0xFE, m*
sizeof(contents));
789 return reinterpret_cast<contents *>(p+1);
800 template <
class contents >
inline unsigned long KnRManagedSharedMemory<contents>::BaseDeallocate(
const contents *
const ptr,
const unsigned long m) {
802 NTUtils::MutexLock lock(mutex.Name(), INFINITE,
const_cast<SECURITY_ATTRIBUTES *
const>(&(ss->SA())));
804 free_memory_list_type *p;
805 free_memory_list_type *
const bp=
reinterpret_cast<free_memory_list_type *
const>(
const_cast<contents *
const>(ptr))-1;
811 assert(m || (bp->size==m*
sizeof(contents)+
sizeof(free_memory_list_type)));
813 memset(
const_cast<contents *
const>(ptr), 0xFD, m*
sizeof(contents));
815 for (p=free_list; !(bp>p && bp<p->next); p=p->next) {
816 if (p>=p->next && (bp>p || bp<p->next)) {
820 if (bp+bp->size/
sizeof(free_memory_list_type)==p->next) {
821 bp->size+=p->next->size;
822 bp->next=p->next->next;
826 if (p+p->size/
sizeof(free_memory_list_type)==bp) {
833 return bp->size/
sizeof(contents);
836 template <
class contents >
inline bool KnRManagedSharedMemory<contents>::Capacity(
const unsigned long,
const DWORD, HANDLE) {
837 std::cerr <<
"KnRManagedSharedMemory<...>::Capacity(...) : Not supported!!!" << std::endl;