C++ Windows API Process Ownership

Merhabalar, Windows API kullanarak bir processin sahibini değiştirmeye çalışıyorum. Program çıktısında sıkıntısız çalıştığı yazıyor ancak processin sahibini kontrol ettiğimde değişmemiş halde görüyorum. Bu sorunun çözümü nedir? Kodu bırakıyorum.

#include "windows.h"
#include "aclapi.h"
#include "sddl.h"
#include <iostream>

using namespace std;

int main(void){
    int pid;

    cout << "Please input process id: ";
    cin >> pid;

    HANDLE process = OpenProcess(0x00080000L, TRUE, pid);

    cout << GetLastError() << endl;

    if(!process){

        cout << "An error occured while opening the process." << endl;
        cout << "Exiting...";

        return 1;

    }

    cout << "Process succesfully opened!" << endl;

    PSID psid; 
    BOOL convertion = ConvertStringSidToSid(TEXT("psid"), &psid);

    PSID *ppsid = &psid;



    DWORD security_set = SetSecurityInfo(process, SE_KERNEL_OBJECT, OWNER_SECURITY_INFORMATION, *ppsid, NULL, NULL, NULL);

    cout << GetLastError() << endl;

    if(security_set==ERROR_SUCCESS){
        cout << "Process owner has been changed!" << endl;
    }



    return 0;
}

Taking Object Ownership in C++ - Win32 apps | Microsoft Learn

Anahtar kelimeler de vereyim:

SE_TAKE_OWNERSHIP_NAME

AdjustTokenPrivileges

Yetkili olmayan bir kullanıcı yada process kafasına göre process sahipliğini alabilse aşırı güvensiz bir işletim sistemi olmaz mıydı?

Anladığım kadarıyla process sahibini değiştirmenin yönetici hesabıyla mümkün olduğunu söylüyorsunuz, doğru muyum? Zaten yetkisiz hesapla olmayacağını bildiğim için programı yönetici olarak çalıştırıyordum, ancak gene bir fark olmuyordu. Programı yetkili kılmak için illa ki windows api’den mi yararlanmamız gerek? Eğer öyleyse belirli bir örnek verebilir misiniz?

Yok bunu söylemek istemedim. Söylemek istediğimi biraz daha netleştireyim. Bir process’in bir sahibi var, ve biz bu process in sahibini değiştireceğiz.

Process’in ilk sahibi kim ve yetki seviyesi nedir?

Process’in sahibi olacak kim ve yetki seviyesi nedir?

Son olarak sahibini değiştirdiğimiz process i biz hangi yetki seviyesinde göreceğiz?

Fark eder.

Process Managerden bende mevcut bir process list parçası;

Mesela svchost.exe PID:2160 olanı ele alalım;

Hemen normal bir konsol açalım ve sizin kodu çalıştıralım ve 2160 verelim.

Evet hatamızı aldık. Sahipliğini alabilecek kadar yetkili bir konsolumuz yokmuş.

Tamam bunu admin konsol ile yeniden deneyelim.

Şimdi gelelim succesfully oppened kısmına.

Peki biz başarılı bir şekilde process’in sahibini değiştirdiysek neden 1337 hatası alıyoruz?

Asıl bunun üzerinde ayrıca durmak gerekir.

Hayır programı yetkili kılmak için api kullanmak zorunda değiliz. Ama processimizin sahibini değiştirirken onun yetkilerini ayarlamamız gerekiyor.

Soruna dönersek.

Baştaki sorularım bu konunu ve kodların belirleyicisi olacaktır.

Biz, kimin sahip olduğu process in sahipliğini kime vereceğiz? Sahibini değiştirmek için sahibinin yetkilerine sahip olacağından onları nasıl ayarlayacağız sorusuna götürecek.

Şimdi 1337 hatasına geri dönelim.

Ben nasıl 1337 hatası alırken başarılı bir şekilde process sahibini değiştirmiş olabilirim?

System Error Codes (1300-1699) (WinError.h) - Win32 apps | Microsoft Learn

ERROR_INVALID_SID

1337 (0x539)

The security ID structure is invalid.

Geçersiz ID yapısının sebebi ne olabilir?

Doğru yetkilerlerle erişilmemiş bir process kopyalanmamıi ID yapısı.

Çalışan bir processin sahipliğini almak kolay değildir.

Kimden alıp kime verdiğimize dikkat etmeliyiz.

Kodun kaynağı nedir neyi amaçladın açıklarsan daha eli yüzü düzgün somut bir koda çevirmeye çalışabiliriz.

Amacım aslında admin hesabı ile dahi terminate edilemeyen programların terminate etmeyi sağlamak. Programın sahipliğini bu yüzden almak istiyordum. Koddaki sid kısmını bilgisayarımda terminal üzerinden whoami komuduyla almıştım (sid’i hatırlamadığım için buraya yazmadım.). Program ben denediğimde hiçbir hata vermemesinin yanında processin sahibini değiştirmiyordu. Zaten bu konuyu hiçbir hata vermemesine rağmen process ownerın değişmemesi yüzünden açtım. Programın elle tutulur bir hata vermemesinin sebebi ne olabilir?

Buna ayrıca bakalım güzel hedef.

Bütün sid leri denedim sonuçta hep aynı hata oluşuyor.

Program aslında hata veriyor.

Process successfully opened!
Mesajının altındaki 1337 kodu hata kodu.

Yani başarı ile açıldı demesine rağmen geçersiz sid hatası döndürüyor.

Program elle tutulur hata veriyor. Fonksiyonun başarımı ile hata mesajı biraz farklı konular.

Kodun gerçekten hata döndürmediği tek

SID değeri;

S-1-5-32-544

Bu değeri verdiğimizde hata kodu 0 oluyor.

Tabi, bu arada sahibini listelemek için ufak bir fonksiyon ekleyip, mevcut kodunu bir başka fonksiyona aktardım.

Sadece burada 0 döndürebiliyor, yukarıdaki önceki ekran görüntülerine bakarsan, hangi sid değerini verirsem vereyim 1337 hatası aldım.

Ve fakat hala sahipliği değişmedi.

Sadece sahibini öğrenmek için bile tokenprivilege gerekiyor ki o kodu ekliyorum:


#include <windows.h>
#include <tchar.h>
#include <psapi.h>
#include <iostream>
#include "aclapi.h"
#include "sddl.h"

#pragma comment(lib, "psapi.lib")

using namespace std;

void GetProcessOwner(DWORD processID)
{
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, processID);
    if (hProcess == NULL)
    {
        // Failed to open the process
        return;
    }

    HANDLE hToken;
    if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken))
    {
        // Failed to open the process token
        CloseHandle(hProcess);
        return;
    }

    // Get the process owner SID
    DWORD dwSize = 0;
    GetTokenInformation(hToken, TokenUser, NULL, dwSize, &dwSize);
    TOKEN_USER* pUser = (TOKEN_USER*)new BYTE[dwSize];
    if (!GetTokenInformation(hToken, TokenUser, pUser, dwSize, &dwSize))
    {
        // Failed to get the process owner SID
        delete[] pUser;
        CloseHandle(hToken);
        CloseHandle(hProcess);
        return;
    }

    // Convert the SID to a username
    SID_NAME_USE sidType;
    TCHAR lpName[MAX_PATH];
    TCHAR lpDomain[MAX_PATH];
    DWORD dwNameSize = MAX_PATH;
    DWORD dwDomainSize = MAX_PATH;
    if (!LookupAccountSid(NULL, pUser->User.Sid, lpName, &dwNameSize, lpDomain, &dwDomainSize, &sidType))
    {
        // Failed to get the process owner name
        delete[] pUser;
        CloseHandle(hToken);
        CloseHandle(hProcess);
        return;
    }

    // Print the process owner name
    _tprintf(_T("Process owner: %s\\%s\n"), lpDomain, lpName);

    delete[] pUser;
    CloseHandle(hToken);
    CloseHandle(hProcess);
}
int ChangeOwner(DWORD processID) {
    int pid;

    pid= processID;

    HANDLE process = OpenProcess(0x00080000L, TRUE, pid);

    cout << GetLastError() << endl;

    if (!process) {

        cout << "An error occured while opening the process." << endl;
        cout << "Exiting...";

        return 1;

    }

    cout << "Process succesfully opened!" << endl;

    PSID psid;
    BOOL convertion = ConvertStringSidToSid(TEXT("S-1-5-32-544"), &psid);

    PSID* ppsid = &psid;



    DWORD security_set = SetSecurityInfo(process, SE_KERNEL_OBJECT, OWNER_SECURITY_INFORMATION, *ppsid, NULL, NULL, NULL);

    cout << GetLastError() << endl;

    if (security_set == ERROR_SUCCESS) {
        cout << "Process owner has been changed!" << endl;
    }



    return 0;
}

////////////////////////////////////////////////////////////////////////
int main()
{  
    DWORD processID;

    cout << "Please input process id: ";
    cin >> processID;

 
    GetProcessOwner(processID);
    ChangeOwner(processID);
    GetProcessOwner(processID);

    return 0;
}

Yukarıdaki kod , ekran görüntüsündeki gibi, önce process in sahibini buluyor. Sonra verdiğiniz kodda sid değeri ile sahibini değiştirmeye çalışıyor.

Ve fakat sahibi değişmiyor.

Yazdığınız kodun daha önce sorduğum soruların cevaplarının hala net bir durumu yok.

Ben bir kullanıcı seviyesindeyim, bir process çağırıyorum, sonra çağırdığım process başka bir etki alanında bunu alıp bir başka yetki seviyesine ve etki alanına çekiyorum ki buna yetkim var mı emin değiliz.

Windowsta Admin yetkisi ile admin grubundaki super user aynı yetkide değil.

Ve logon olmayan bir kullanıcı nasıl sahipliğini alacak, üzerinede çalışan bir process in sahipliği doğrudan alınabilir mi?

Dll injection geliyor aklıma, advapi32.dll ile bir şeyler yapılabilir mi diye düşünüyorum.

Ama henüz sizin kodun nasıl bu sahipliği alacağını anlamadım.

Söylediğim gibi tokenprivileges ile yükseltip sonra uygun guruba çekmeyi denemek lazım. Burası koda dönük olan kısım.

Tabi bu arada msdn referansları c ile kodlar da c++ ile çalışan bir örnek için kütüphaneleri bile dikkatle seçmek gerekecek.

Üzerinde düşünülmesi gereken bir çok husus var. Yani doğrudan çalışan bir process i log on olmamış bir kullanıcının sahipliğine geçirmek kafamı karıştırdı.

Yine de inceleyeceğim bir şeyler bulursam eklerim.

Söylediklerinize göre ne demek istediğimi tam anlamamışsınız. Yapmak istediğim program tam olarak şu: Program, yönetici yetkisiyle (en azından bizim programın alabileceği en yüksek yetkiyle), seçtiğimiz terminate edilemeyen 3. taraf bir processin sahipliğini değiştirerek bu processi terminate edecek. Burada işletim sistemine aykırı bir şey yapmak istemiyorum aslında, dll injection gibi yöntemleri kullanmadan windows api ile yapılabileceğini düşünüyordum. Haksız mıyım? Eğer windows api ile bunu yapmak mümkün değilse araştırabileceğim bir yöntem önerir misiniz?

Evet anlamadım. Anlamak istediğim şey şu;

Bilgisayarda Admin Grubunda bir kullanıcı ile log on oldunuz. Ve Admin veya System yetkisindeki bir programın sahipliğini almak istiyorsunuz.

Bu durumda bu process’i Admin yada System kullanıcılarının başlatmış olduğunu varsayıyoruz. Veya Guest bir kullanıcı bile olabilir. Ve bu kullanıcılar bu processleri başlattıklarına göre de aktif olarak onlarında log on olmaları gerekiyor.

Şimdi yukarıda saydığım kullanıcılardan birinin başlattığı bir process i, biz de Admin grubundaki kendi kullanıcımızın üzerine almaya çalıştık. Ve aldık. Kapatsak bile diğer kullanıcının etki alanında kapanır mı?

Mesela kendi kullanıcı hesabım Administrator grubunda ama tüm Admin yetkilerine sahip değilim. Bazıları için admin izni isteniyor.

Etki alanınının dışındaki bir alana erişmek için dll injection gerekebilir.

Dll injection da windows apiye aykırı bir durum yok.

Ne yapabiliriz diye düşünüyorum.

Acaba olaya tersten mi bakıyoruz;

Şöyle düşünsek ne olur?

Process in sahibini bulsak, o hesaba geçsek, ve o hesap üzerinden kapatsak daha kolay olmaz mı?

#include <windows.h>
#include <iostream>

using namespace std;

HANDLE LogonUserTest()
{
    HANDLE hToken;
    LPCWSTR username = L"TestUser";
    LPCWSTR password = L"Password";

    BOOL result = LogonUser(
        username,
        NULL,
        password,
        //LOGON32_LOGON_NETWORK,
        LOGON32_LOGON_INTERACTIVE,
        LOGON32_PROVIDER_DEFAULT,
        &hToken
    );

    if (!result)
    {
        cout << "LogonUser failed with error code " << GetLastError() << endl;
        //return 1;
    }

    // Use hToken to impersonate the user and perform actions on their behalf

    CloseHandle(hToken);

    return hToken;
}

Yani basitçe sahibi olan kullanıcıya geçip bunun üzerinden kapatmak daha kolay gibi geldi bana.

Merhabalar, haftaiçi müsait olamadığımdan bilgisayar başına geçememiştim. Kendi yazdığım kodu kendi bilgisayarımda denediğimde INVALID_SID hatası vermiyor. Hatta bir tane örnek yapayım:

pic1
İlk önce bu processi seçiyorum


pic2
Kodu “S-1-5-32-544” SID’i ile resimdeki gibi çalıştırıyorum. Ne yetki hatası ne de geçersiz SID hatası veriyor.



Program sıkıntısız çalışmasına rağmen processin sahibi değişmiyor.

Hiçbir şekilde hata vermemesine rağmen processin sahibini değiştirmem için nasıl bir yol uygun olur acaba?

Mantıklı geldi, deneyeceğim. Teşekkürler.

Benim için denemeniz önemliydi zaten.

Sahiplik değiştirmek ile ilgili size bir ip ucu vereyim.

Sahiplik, çalışan process’in midir? Yoksa çalışan dosyanın mıdır?

Dosya sahipliği değiştirmek için örnek bir kod bırakayım, orada dosya sahipliğinin nasıl alındığını görebilirsiniz.

Ama çalışan bir process in sahibi derken ilk kimin çalıştırdığı mı önemlidir, o prcess’e sizin terminate komutu göndrecek yetkiye sahip olmak mı önemlidir?

Yani aslında istediğimiz bir process i sonlandırmak istiyorsak sahibi olmamız gerekmez, sadece kapatacak yetkiye sahip olmamız gerekir.

Bu nedenle size;

Demiştim.

Çünkü aslında bizim yapmamız gereken şey şu, admin yetkisini alıp, process i kapatma komutu göndermek.

Şimdi sizin resmini koyduğunuz Gelişmiş güvenlik ayarları dosyalar/object ler/nesneler için geçerlidir. Çalışan bir kod parçası bellekte bir yer kaplar ve buna memory bölgesine erişmek bambaşka bir konudur. Bu nedenle dll injection anahtar kelimesini mesajımda geçirmiştim.

Aslında çok da mantıklı değil. Evet bir kullanıcının kontrolünü kaybettiği bir process’ten bahsediyorsak kullanıcı değiştirmek mantıklı.

Peki burada şunu sormanız gerekir.

Peki SYSTEM ve SERVICE gibi sahibi olan durumda ne yapacağım.

Çünkü bunlar aslında logon olamayacağınız, aktif olmayan/disabled kullanıcılar.

Zaten burada kafamı karıştıran bu, bir SYSTEM yada SERVICE process’inin sahibi olmak demek, bilgisayarın tanrısı olmak demektir. Bunu nasıl bir kullanıcı üstlenebilir?

Genelde kernel/çekirdek yetki yükseltmeleri ve açıklar ile kernel exploit leri konusuna gelir ki bu da dümdüz kodlama ile konuştuğumuz API konusu olmaktan çıkıp, windows açığı bulmak demektir. Ki bunu burada çözebilir miyiz bilemem.

Daha da ilginci;

Sizin sorunuzun üzerine, söylediğim gibi, bir nesne/dosyanın sahipliğini alacak kodlar yazdım. Fırsat bulursam eklerim.

Admin gurubundaki kullanıcımda sahipliği olan bir dosyamı, Guest kullanıcısının almasını sağladım.

İlginç olan evet sahibi Guest oldu, fakat yetkilerine baktığımda bu sefer hala Admin yetkileri duruyordu. Admin yetkilerine sahip bir Guest sahipliğindeki dosya. Yani bomba. Bu dosya neler yapabilir henüz denemedim.

Çünkü ben sadece sahipliğini değiştirdim ama güvenlik alanında hala Admin yetkisinde görünüyor ve bunu değiştirecek bir şey yapmasam da yapabilmesini beklerdim.

Neyse kodu eklersem dener fikrinizi söylersiniz.

Şimdi privilege konusuna dönelim.

komut satırından “taskkill” komutunu inceleyebilirsiniz.

Ben bu komut ile Admin yetkili bir terminal açıp system ve service owner lı bir process i silebildim.

Tabi bu donmuş bir process değildi, yani kilitlenmiş donmuş/zombiye dönüşmüş bir process im olmadığından process i sonlandırabilir miyim deneyemedim ama.

Komutla bir system ve service kapatabildim.

Bu da gösteriyor ki, taskkill yetki yükseltip bu process i normalde silemediğimiz duruma durdurabiliyor.

Eskilerden hatırlayabildiğim, debug privilege dediğimiz bir debug seviyesi bir yetki alınca yetkiniz Mevcut kullanıcı yetkinizden yükseltiliyor ve bu tür işlemleri yapabiliyorsunuz.

Bununla ilgili sizin sorunuz üzerine bir kaç kod daha yazdım.

Neredeyse, processleri listeleyen, pid ve sid lerini alan, sonra da processleri öldürebilecek bir çok kod parçasına dönüştü.

Tabi hepsini derleyip toplamak gerekiyor.

Belki sizin verdiğiniz sahiplik durumu da denenebilir, ama söylediğim gibi debug veya kernel yetkileri ödünç almak gerekebilir.

Gelelim asıl sorumuza.

Biz silinemeyen dosyaları silmek istiyoruz ve silinmeme nedeni, bir process tarafından açık tutulup alıkonulması ve açık kalması olabilir. Her zaman sadece yetki sorunu yüzünden silememek söz konusu olmayabilir.

Bu durum için hatırladığım 2005 model bir mesaj vardı.

Unkillable Processes - Microsoft Community Hub

Sysinernal tools bu konuda zamanında çok baktığım araçlardı,

Mark Russinovich bu konuda bir mesaj atmıştı mesajın orijinalini bulamadım ama microsoft bunu bir şekilde yeniden yayınlamış.

Buradan bakarsanız, bir giriş çıkış aygının yanlış sürücüsünün böyle bir process’e neden olabileceğini görebilirsiniz.

Bununla ilgileniyorsak bu farklı bir konu, ona ayrıca bakmamız gerekir. Ama tek sorun sadece yetki problemi ise, yukarıda söylediğim, yetki yükseltip process i öldürüp silmek mümkün görünüyor.

Yani sahipliğini almak yada, kullanıcı değiştirmek hem çözüm olmayacak, hemde her kullanıcıya uzaktan bağlanamayabilirsiniz.

Bu arada kodu buldum.

///////////////////////CHANGING FILE OWNER//////////////////////
#include <atlpath.h>
#include <atlsecurity.h>
#include <atlfile.h>

VOID EnablePrivilege(LPCTSTR pszPrivilege)
{
    CAccessToken Token;
    if (!Token.GetThreadToken(TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES))
    {
        const HRESULT nResult = AtlHresultFromLastError();
        ATLENSURE_THROW(nResult == HRESULT_FROM_WIN32(ERROR_NO_TOKEN), nResult);
        ATLENSURE_THROW(Token.GetProcessToken(TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES), AtlHresultFromLastError());
    }
        ATLENSURE_THROW(Token.EnablePrivilege(pszPrivilege), AtlHresultFromLastError());
}

VOID PrintOwner(LPCTSTR pszPath)
{
    PSID pSecurityIdentifer = NULL;
    CSecurityDesc SecurityDescriptor;
    ATLENSURE_SUCCEEDED(HRESULT_FROM_WIN32(GetNamedSecurityInfo(const_cast<LPTSTR>(pszPath), SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, &pSecurityIdentifer, NULL, NULL, NULL, reinterpret_cast<PSECURITY_DESCRIPTOR*>(&SecurityDescriptor))));
    CSid SecurityIdentifer((const SID*)pSecurityIdentifer);
    _tprintf(_T("Owner: %s\\%s\n"), SecurityIdentifer.Domain(), SecurityIdentifer.AccountName());
}

VOID SetOwner(LPCTSTR pszPath, const CSid & SecurityIdentifer)
{
                ATLENSURE_SUCCEEDED(HRESULT_FROM_WIN32(SetNamedSecurityInfo(const_cast<LPTSTR>(pszPath), SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, const_cast<SID*>((const SID*)SecurityIdentifer), NULL, NULL, NULL)));
}

int _tmain(int argc, _TCHAR * argv[])
    {
     static LPCTSTR g_pszPath = _T("C:\\Project Sources\\Deneme\\run.py");
     EnablePrivilege(SE_RESTORE_NAME);
     PrintOwner(g_pszPath);
     CSid SecurityIdentifer;
     ATLENSURE_THROW(SecurityIdentifer.LoadAccount(_T("Guest")), AtlHresultFromLastError());
     _tprintf(_T("New Owner: %s\\%s\n"), SecurityIdentifer.Domain(), SecurityIdentifer.AccountName());
     _ATLTRY
     {
        SetOwner(g_pszPath, SecurityIdentifer);
     }
     _ATLCATCH(Exception)
     {
        _tprintf(_T("Exception 0x%08x\n"), (HRESULT)Exception);
        // NOTE: This might be the worst case scenario: changing ownership is perhaps protected by DACL
        EnablePrivilege(SE_TAKE_OWNERSHIP_NAME);
        SetOwner(g_pszPath, SecurityIdentifer);
     }
     PrintOwner(g_pszPath);
     return 0;

}

Bu kod ile bir dosyanın (konumu önceden verilmiş) sahibi değiştiriliyor.

Ama söylediğim gibi bunu sizin baktığınız yetki penceresinden değil, dosyanın özellikler sekmesi içinde ayrıca görebilirsiniz. Yetkiler ayrı sahipliği ayrı bir hale geliyor.

Gerekirse resimli örneklerim.

Özellikle py dosyasına bunu yaptım, çünkü merak ettiğim acaba Guest kullanıcısı bu dosyaya Admin yetkili bir iş yaptıracak mı? Siz buraya kendi dosya yollarınızı ve dosyalarınızı yazarak deneyebilirsiniz.

Bunu denemedim. Denediğimde o kısmı da paylaşabilirim.

Son olarak size bir kaç ipucu daha vereyim.

Amacımız bir process i sonlandırım sonrasında silmeyi denemekse.

Bir process nasıl sonlanrılabilire bir görsel örnek göstermek istiyorum.

image

Kaynak: Really killing a process in Windows - Stack Overflow

Yani bir process farklı metodlarla kapatılmaya zorlanabilir.

Yani ana penceresini tespit edip, WM_DESTROY, WM_CLOSE mesajı göndermekten, terminate ve kill API leri ile de yapılabilir.

Fikir vermesi açısından bırakıyorum.

Biraz daha derinlemesine process ler üzerine bakmak isterseniz:

Overview - Process Hacker (sourceforge.io)

Process hacker açık kaynak.

Sysinternals kapalı kod olduğundan kodları göremezken belki process hacker size biraz fikir verebilir.

Process Hacker download | SourceForge.net

Burada hem binary hem de kaynak kodlarını indirip inceleyebilirsiniz.

Burada biraz dikkatli davranmaya çalışıyorum. Kimseye virüs yazmak yada yetki yükselterek bilgisayara sızmak gibi garip edinimler kazandırmamak için bazı konuları üstün körü geçmiş olabilirim.

Bu nedenle olabildiğince microsoft tarafından dökümante edilmiş tarafta kalarak örnekler vermeye çalışıyorum.

Umarım işinize yarar.

Bir de çoğunluk microsoft dokümantasyonu C ile örneklenmiş. C++ ile sorduğunuz için kodlamada sorun yaşıyorum.

Yani konsola çıktı almak için cout>> yerine wsprintf, _tprintf ve tchar gibi alternatifleri kullanıp kullanmamakta tereddüte kalıyorum.

Açıkcası API kodlarını bir de nesnelere dönüştürüp çağırmak kodu göründüğünden daha karmaşık görünmesine neden olabilir endişemden.

Her ne kadar c++ kodları kullansamda, kodlama C gibi basit C fonksiyonları şeklinde görünüyor.

API çalışırken “bence” C ile kodlamak daha tutarlı görünüyor. Bu nedenle C stili kodlarsam çok yadırgamanızı rica edeceğim.

Denemelerinizi burada paylaşırsanız bakar üzeriden konuşabiliriz.

Kolay gelsin.