NT Security API: SECURITY_DESCRIPTOR.Control, when can I see SE_OWNER_DEFAULTED? - winapi

From Windows NT security API, SE_OWNER_DEFAULTED is a flag bit from SECURITY_DESCRIPTOR_CONTROL.
MSDN states it quite briefly:
(SE_OWNER_DEFAULTED) Indicates that the SID of the owner of the security descriptor was provided by a default mechanism. This flag can be used by a resource manager to identify objects whose owner was set by a default mechanism.
I'm curious that when I can see this flag set.
I write NtfsOwner.cpp to display owner SID of an NTFS file/directory's security descriptor, and use GetSecurityDescriptorOwner to query that SE_OWNER_DEFAULTED flag, but have no chance seeing it even once.
Could somebody give me some clue. Could it be possible that SE_OWNER_DEFAULTED exhibits on other type of NT objects(not on a file/directory)?
#include <Windows.h>
#include <AclAPI.h>
#include <sddl.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
#include <locale.h>
template<typename T1, typename T2>
bool IsSameBool(T1 a, T2 b)
{
if(a && b)
return true;
else if(!a && !b)
return true;
else
return false;
}
void myDisplayNtfsOwner(const TCHAR *szfn)
{
DWORD succ = 0;
HANDLE hFile = CreateFile(szfn,
READ_CONTROL, // dwDesiredAccess=GENERIC_READ etc
FILE_SHARE_READ|FILE_SHARE_WRITE, // shareMode
NULL, // SecuAttr, no need bcz we are opening existing file
OPEN_EXISTING, // dwCreationDisposition
FILE_FLAG_BACKUP_SEMANTICS, // this is required for open a directory
NULL);
if(hFile==INVALID_HANDLE_VALUE)
{
_tprintf(_T("Warning: CreateFile() failed!(WinErr=%d) But I will go on calling GetSecurityInfo(0xFFFFffff, ...)\n"),
GetLastError());
}
SECURITY_DESCRIPTOR *pSD = nullptr;
DWORD winerr = GetSecurityInfo(hFile, SE_FILE_OBJECT,
OWNER_SECURITY_INFORMATION,
NULL, NULL, NULL, NULL,
(PSECURITY_DESCRIPTOR*)&pSD);
assert(winerr==0);
SID* psidOwner = nullptr;
BOOL isOwnerDefaulted = 0;
succ = GetSecurityDescriptorOwner(pSD, (PSID*)&psidOwner, &isOwnerDefaulted);
assert(succ);
PTSTR strOwner = nullptr;
succ = ConvertSidToStringSid(psidOwner, &strOwner);
assert(succ);
_tprintf(_T("Owner SID is: %s\n"), strOwner);
_tprintf(_T("Is owner SID defaulted? %s\n"), isOwnerDefaulted?_T("yes"):_T("no"));
assert(IsSameBool(pSD->Control & SE_OWNER_DEFAULTED, isOwnerDefaulted));
LocalFree(strOwner);
LocalFree(pSD);
CloseHandle(hFile);
}
int _tmain(int argc, TCHAR* argv[])
{
setlocale(LC_ALL, "");
if(argc==1)
{
const TCHAR *s = _T("D:\\test\\foo.txt");
_tprintf(_T("Missing parameters.\n"));
_tprintf(_T("Example:\n"));
_tprintf(_T(" NtfsOwner1 %s\n"), s);
exit(1);
}
const TCHAR *szfn = argv[1];
myDisplayNtfsOwner(szfn);
return 0;
}

Related

Getting Enviroment Variable with cpp

So I have been trying to figure out how to find an environment variable and print it out on the screen in c++
but for the last 3 hours or so, I have been stuck. When I print out the currentDesktop variable it only prints out "/Desktop". But what I'm looking for is the username in front of it.
I have been reading the documentation on the GetEnviromentVariable function from Microsoft's forum and this is what I have come up with so far.
Help would be greatly appreciated since I'm not so experienced yet, Thx.
#include <iostream>
#include <string>
#include <windows.h>
#include <fstream>
#define BUFSIZE 4096
using namespace std;
int main()
{
LPCWSTR Env = L"%USERPROFILE";
LPTSTR pszOldVal;
string IPADD;
pszOldVal = (LPTSTR)malloc(BUFSIZE * sizeof(TCHAR));
if (NULL == pszOldVal)
{
printf("Out of memory\n");
return FALSE;
}
string currentDesktop = GetEnvironmentVariable(Env,pszOldVal,BUFSIZE) + "\\Desktop";
cout << currentDesktop;
return 0;
}
You are misusing the GetEnvironmentVariable() function. For one thing, you are missing the trailing % on the variable name L"%USERPROFILE". For another thing, the return value is the number of characters copied into the supplied buffer. You are adding that integer to the string literal "\\Desktop", which is not what you want.
Try this instead:
#include <iostream>
#include <string>
#include <windows.h>
std::wstring GetEnv(const std::wstring &varName)
{
std::wstring str;
DWORD len = GetEnvironmentVariableW(varName.c_str(), NULL, 0);
if (len > 0)
{
str.resize(len);
str.resize(GetEnvironmentVariableW(varName.c_str(), &str[0], len));
}
return str;
}
std::wstring GetUserDesktopPath()
{
std::wstring path = GetEnv(L"%USERPROFILE%");
if (!path.empty()) path += L"\\Desktop";
return path;
}
int main()
{
std::wstring currentDesktop = GetUserDesktopPath();
std::wcout << currentDesktop;
return 0;
}
That being said, if you just want the username, use %USERNAME% instead of %USERPROFILE%. Or better, use GetUserName() instead of GetEnvironmentVariable():
#include <iostream>
#include <string>
#include <windows.h>
std::wstring GetUserName()
{
std::wstring str;
DWORD len = 0;
if (!GetUserNameW(NULL, &len))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
str.resize(len);
if (GetUserNameW(&str[0], &len))
str.resize(len-1);
else
str = L"";
}
}
return str;
}
int main()
{
std::wstring currentUser = GetUserName();
std::wcout << currentUser;
return 0;
}
However, the correct way to get the path to the user's desktop is to just ask Windows for that specific path, don't assume it is in the root of the user's profile, or that is is named Desktop. Use SHGetFolderPath() or SHGetKnownFolderPath() for that query, eg:
#include <iostream>
#include <string>
#include <windows.h>
#include <shlobj.h>
std::wstring GetFolderPath(CSIDL folderID)
{
WCHAR path[MAX_PATH] = {};
SHGetFolderPathW(NULL, folderID, NULL, SHGFP_TYPE_CURRENT, path);
return path;
}
/* or:
std::wstring GetFolderPath(REFKNOWNFOLDERID folderID)
{
std::wstring str;
PWSTR path = NULL;
if (SHGetKnownFolderPath(folderID, 0, NULL, &path) == S_OK)
str = path;
CoTaskMemFree(path);
return str;
}
*/
std::wstring GetUserDesktopPath()
{
return GetFolderPath(CSIDL_DESKTOPDIRECTORY);
// or: return GetFolderPath(FOLDERID_Desktop);
}
int main()
{
std::wstring currentDesktop = GetUserDesktopPath();
std::wcout << currentDesktop;
return 0;
}

Enumerating application's process name only

How to list process names only? I looked at Enumerating All Modules For a Process. The example code works with process names and modules, but I want only process names.
#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <psapi.h>
#include <iostream>
using namespace std;
int main()
{
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;
HANDLE hProcess;
if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))
{
return 1;
}
cProcesses = cbNeeded / sizeof(DWORD);
for (i = 0; i < cProcesses; i++)
{
DWORD processID = aProcesses[i];
cout << processID << endl;
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
}
CloseHandle(hProcess);
return 0;
}
Get the process ids using your code and then use EnumProcessModules in combination with GetModuleBaseName to print the name of all the executables.
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <psapi.h>
void PrintProcessName( DWORD processID )
{
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
// Get a handle to the process.
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, processID );
// Get the process name.
if (NULL != hProcess )
{
HMODULE hMod;
DWORD cbNeeded;
if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod),
&cbNeeded) )
{
GetModuleBaseName( hProcess, hMod, szProcessName,
sizeof(szProcessName)/sizeof(TCHAR) );
}
}
// Print the process name and identifier.
_tprintf( TEXT("%s\n"), szProcessName );
// Release the handle to the process.
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 name and process identifier for each process.
for ( i = 0; i < cProcesses; i++ )
{
if( aProcesses[i] != 0 )
{
PrintProcessName( aProcesses[i] );
}
}
return 0;
}

ReadFile/WriteFile crahes

Something wrong with next ReadFile/WriteFile code.
I need to use copy file by using this functions (yes, it's better to use CopyFile, but now I need it), but it crashed at read/write loop.
What can be wrong?
PS C:\Users\user\Documents\SysLab1\dist\Debug\MinGW-Windows> g++ --version
g++.exe (x86_64-posix-sjlj-rev0, Built by MinGW-W64 project) 4.8.3
I used next code :
#include <windows.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define BLOCK_SIZE 1024
uint32_t copy_c(char* source, char* destination) {...}
uint32_t copy_api_readwrite(char* source, char* destination) {
bool result;
HANDLE input = CreateFile(source, GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (input!=INVALID_HANDLE_VALUE) {
HANDLE output = CreateFile(destination, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(output!=INVALID_HANDLE_VALUE) {
DWORD readed;
char block[BLOCK_SIZE];
while(ReadFile(input, block, BLOCK_SIZE * sizeof(char), &readed, NULL)>0) {
WriteFile(output, block, readed, NULL, NULL);
}
if(GetLastError()==ERROR_HANDLE_EOF) {
result = true;
}
else {
result = false;
}
CloseHandle(output);
}
else {
result = false;
}
CloseHandle(input);
}
else {
result = true;
}
if(result) {
return 0;
}
else {
return GetLastError();
}
return result;
}
uint32_t copy_api(char* source, char* destination) {...}
#define COPY_READWRITE
#ifdef COPY_C
#define COPY copy_c
#else
#ifdef COPY_READWRITE
#define COPY copy_api_readwrite
#else
#ifdef COPY_API
#define COPY copy_api
#endif
#endif
#endif
int main(int argc, char** argv) {
if(argc<3) {
std::cout << "Bad command line arguments\n";
return 1;
}
uint32_t result = COPY(argv[1], argv[2]);
if(result==0) {
std::cout << "Success\n";
return 0;
}
else {
std::cout << "Error : " << result << "\n";
return 2;
}
}
From the documentation of WriteFile:
lpNumberOfBytesWritten
This parameter can be NULL only when the lpOverlapped parameter is not NULL.
You are not meeting that requirement. You will have to pass the address of a DWORD variable into which the number of bytes written will be stored.
Another mistake is in the test of the return value of ReadFile. Instead of testing ReadFile(...) > 0 you must test ReadFile(...) != 0, again as described in the documentation.
You don't check the return value of WriteFile which I also would regard as a mistake.
By definition, sizeof(char) == 1. It is idiomatic to make use of that.
When dealing with binary data, as you are, again it is idiomatic to use unsigned char.
More idiom. Write the assignment of result like this:
result = (GetLastError() == ERROR_HANDLE_EOF);

Possible to capture unhandled exception in win32 user application ? (setunhandledexceptionfilter())

I spent much time to capture unhandled exceptions in my process (win32) using API so called setunhandledexceptionfilter().
But I haven't captured exception when WER(Windows Error Report - which is well know for DR.watson) is showed.
Is impossible to catch all of exceptions without third-party in my APP?
I think that there is method for handling, but I don't get it.
I am not accustomed to Windows DEV environment. that's why I lost my mental in googling.
Below is my test-case in vc110(Visual Studio 2012).
chat test[65];
int main() {
// after attaching unhandled exception call-back using setunhandledexceptionfilter()
// die point (ACCESS_VIOLATION c0000005)
for (int k=0; k<1000000; k++)
test[k]=65;
My callback isn't called after WER(windows Error Report) occurs. It doesn't work as my intend.
*But strcpy(NULL, "TEST") which is okay (SUCCESS)*
Below is my source code.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/stat.h>
#include <assert.h>
#include <process.h>
#include <direct.h>
#include <conio.h>
#include <time.h>
#include <Windows.h>
#include <tchar.h>
#include <dbghelp.h>
#include <stdio.h>
#include <crtdbg.h>
#include <WinBase.h>
#pragma comment ( lib, "dbghelp.lib" )
void CreateMiniDump( EXCEPTION_POINTERS* pep );
BOOL CALLBACK MyMiniDumpCallback(
PVOID pParam,
const PMINIDUMP_CALLBACK_INPUT pInput,
PMINIDUMP_CALLBACK_OUTPUT pOutput
);
///////////////////////////////////////////////////////////////////////////////
// Minidump creation function
//
#if 0
LONG WINAPI lpTopLevelExceptionFilter(EXCEPTION_POINTERS* ExceptionInfo);
#endif
void CreateMiniDump( EXCEPTION_POINTERS* pep )
{
time_t t;
struct tm *tinfo;
wchar_t dump_name[128];
HANDLE hFile;
time(&t);
tinfo = localtime(&t);
wcsftime(dump_name, 128, L"MiniDump[%Y%m%d][%H_%M_%S].dmp", tinfo);
// file format MiniDump[YYYYMMDD][HH_MM_SEC]
hFile = CreateFile(dump_name, GENERIC_READ | GENERIC_WRITE,
0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if( ( hFile != NULL ) && ( hFile != INVALID_HANDLE_VALUE ) )
{
// Create the minidump
MINIDUMP_EXCEPTION_INFORMATION mdei;
MINIDUMP_CALLBACK_INFORMATION mci;
MINIDUMP_TYPE mdt;
BOOL rv;
mdei.ThreadId = GetCurrentThreadId();
mdei.ExceptionPointers = pep;
mdei.ClientPointers = FALSE;
mci.CallbackRoutine = (MINIDUMP_CALLBACK_ROUTINE)MyMiniDumpCallback;
mci.CallbackParam = 0;
mdt = (MINIDUMP_TYPE)(MiniDumpWithIndirectlyReferencedMemory | MiniDumpScanMemory| MiniDumpWithThreadInfo);
rv = MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(),
hFile, mdt, (pep != 0) ? &mdei : 0, 0, &mci );
if( !rv )
_tprintf( _T("MiniDumpWriteDump failed. Error: %u \n"), GetLastError() );
else
_tprintf( _T("Minidump created.\n") );
// Close the file
CloseHandle( hFile );
}
else
{
_tprintf( _T("CreateFile failed. Error: %u \n"), GetLastError() );
}
}
///////////////////////////////////////////////////////////////////////////////
// Custom minidump callback
//
BOOL CALLBACK MyMiniDumpCallback(
PVOID pParam,
const PMINIDUMP_CALLBACK_INPUT pInput,
PMINIDUMP_CALLBACK_OUTPUT pOutput
)
{
BOOL bRet = FALSE;
// Check parameters
if( pInput == 0 )
return FALSE;
if( pOutput == 0 )
return FALSE;
// Process the callbacks
switch( pInput->CallbackType )
{
case IncludeModuleCallback:
{
// Include the module into the dump
bRet = TRUE;
}
break;
case IncludeThreadCallback:
{
// Include the thread into the dump
bRet = TRUE;
}
break;
case ModuleCallback:
{
// Does the module have ModuleReferencedByMemory flag set ?
if( !(pOutput->ModuleWriteFlags & ModuleReferencedByMemory) )
{
// No, it does not - exclude it
wprintf( L"Excluding module: %s \n", pInput->Module.FullPath );
pOutput->ModuleWriteFlags &= (~ModuleWriteModule);
}
bRet = TRUE;
}
break;
case ThreadCallback:
{
// Include all thread information into the minidump
bRet = TRUE;
}
break;
case ThreadExCallback:
{
// Include this information
bRet = TRUE;
}
break;
case MemoryCallback:
{
// We do not include any information here -> return FALSE
bRet = FALSE;
}
break;
case CancelCallback:
break;
}
return bRet;
}
LONG WINAPI exception_filter_func(EXCEPTION_POINTERS* pep)
{
if (pep == NULL) {
return EXCEPTION_EXECUTE_HANDLER;
}
if (pep->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW) {
HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CreateMiniDump, pep, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
} else {
CreateMiniDump(pep);
}
return EXCEPTION_EXECUTE_HANDLER;
}
char test[65];
int main(int argc, char **argv)
{
int k;
SetUnhandledExceptionFilter(exception_filter_func);
// exception occured (ACCESS_VIOLATION)
for (k=0; k<1000000; k++)
test[k]=65;
}

Convert a char * to inizialite an entity of type LPCTSTR for RegCreateKeyEx

I know I am a Windows programming nob, so I am just learning.
I am writing a Command Line tool to work with some of the Registry Functions of the Windows API, but I need to convert a char * that comes from an argv[] array to initialize a LPCTSTR variable with the content but I don't know how to do that.
This is the code I have so far:
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
int main(int argc, char *argv [])
{
int count;
DWORD Reserved = 0;
LPTSTR lpClass = NULL;
DWORD dwOptions = REG_OPTION_NON_VOLATILE;
REGSAM samDesired = KEY_ALL_ACCESS;
LPSECURITY_ATTRIBUTES lpSecurityAttributes = NULL;
HKEY phkResult;
DWORD lpdwDisposition;
if (argv[1] == 0)
{
printf("There are no arguments, pleas type one at least. \n");
}
else if (std::string(argv[1]) == "-Clave")
{
if (std::string(argv[2]) == "HKCU")
{
printf("You are going to create a HKCU sub-key \n");
HKEY hKey = HKEY_CURRENT_USER;
if (std::string(argv[3]) != "")
{
printf("You are going to create this sub-key: %s \n",argv[3]);
//This is what I tried.
LPCTSTR lpSubKey = TEXT("%s",argv[3]);
RegCreateKeyEx(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, &phkResult, &lpdwDisposition);
if (lpdwDisposition == REG_CREATED_NEW_KEY)
{
printf("The registry key has been created. \n");
}
}
else
printf("No one");
}
else
{
printf("No key has been specified \n");
}
}
system("Pause");
}
Can you help me out?
Thanks a lot.
Have a look at the MultiByteToWideChar function in Windows.h. Here's a nice and quick example:
const char * orig = "text1";
WCHAR buffer[6];
MultiByteToWideChar(0, 0, orig, 5, buffer, 6 );
LPCWSTR text = buffer;
Whoops, that's for LPCWSTR. For LPCTSTR, just use :
LPCTSTR text = _T("text1");
Another possible solution is to change main function declaration in this way :
int _tmain(int argc, TCHAR* argv[])
Quote from MSDN :
You can also use _tmain, which is defined in TCHAR.h. _tmain resolves
to main unless _UNICODE is defined. In that case, _tmain resolves to
wmain.
Second parameter on RegCreateKeyEx is on type* LPCTSTR.
lpSubKey is declared by the same type and will be initialized properly when passed as an argument to the RegCreateKeyEx function .
Here is your source code compiled with Visual C++, and uses Multi-byte Character Set (_MBCS macro is defined) :
// RegCreate.cpp : Defines the entry point for the console application.
// VC++ Compiler Options :
// cl /W3 /MT /O2 /D WIN32 /D _CONSOLE /D _MBCS /EHsc /TP RegCreate.cpp
#include <Windows.h>
#include <iostream>
#include <string>
#include <tchar.h>
#ifndef _MBCS
#define _MBCS
#endif
#pragma comment(lib, "Advapi32.lib")
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
DWORD Reserved = 0;
LPTSTR lpClass = NULL;
DWORD dwOptions = REG_OPTION_NON_VOLATILE;
REGSAM samDesired = KEY_ALL_ACCESS;
LPSECURITY_ATTRIBUTES lpSecurityAttributes = NULL;
HKEY phkResult;
DWORD lpdwDisposition;
if(argc < 3)
{
std::cout << "There are no arguments, pleas type one at least. " << std::endl;
return 1;
}
if((std::string(argv[1]) == "-Clave") && (std::string(argv[2]) == "HKCU") && (argc == 4))
{
std::cout << "You are going to create a HKCU sub-key " << std::endl;
HKEY hKey = HKEY_CURRENT_USER;
if(std::string(argv[3]) != "")
{
std::cout << "You are going to create this sub-key: " << argv[3] << std::endl;
//This is what I tried.
LPCTSTR lpSubKey = argv[3];
if(ERROR_SUCCESS != RegCreateKeyEx(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired,
lpSecurityAttributes, &phkResult, &lpdwDisposition))
{
return 1;
}
if(lpdwDisposition == REG_CREATED_NEW_KEY)
{
std::cout << "The registry key has been created. " << std::endl;
}
RegCloseKey(phkResult);
}
else
{
std::cout << "No one";
}
}
else
{
std::cout << "No key has been specified " << std::endl;
}
return 0;
}
We can use the TEXT macro to define a string as being Unicode or not, but in the above example this is not necessary .
If you use C++ I suggest you to change printf with std::cout, that works with ASCII characters .
The simplest solution is to explicitly call the Ansi versions of the Registry functions (RegCreateKeyExA, etc) and let Windows handle the conversions for you. You are currently calling the Unicode versions of the functions (RegCreateKeyExW, etc), or you wouldn't be having conversion problems in the first place:
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
int main(int argc, char *argv [])
{
int count;
HKEY hkResult;
DWORD dwDisposition;
if (argc < 1)
{
printf("There are no arguments, pleas type one at least. \n");
}
else if (strcmp(argv[1], "-Clave") == 0)
{
if (argc < 3)
{
printf("There are not enough arguments typed in. \n");
}
else if (strcmp(argv[2], "HKCU") == 0)
{
if (strcmp(argv[3], "") != 0)
{
printf("You are going to create HKCU sub-key: %s \n", argv[3]);
if (RegCreateKeyExA(HKEY_CURRENT_USER, argv[3], 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkResult, &dwDisposition) == 0)
{
if (dwDisposition == REG_CREATED_NEW_KEY)
{
printf("The registry key has been created. \n");
}
else
{
printf("The registry key already exists. \n");
}
RegCloseKey(hkResult);
}
else
{
printf("Unable to create the registry key. \n");
}
}
else
{
printf("No HKCU sub-key has been specified \n");
}
}
else
{
printf("No root key has been specified \n");
}
}
system("Pause");
return 0;
}
Update: If you want to be politically correct, most Win32 APIs that deal with text data actually deal with TCHAR (which is what you were attempting to use, but not successfully) so that they can be compiled for both Ansi and Unicode with a single codebase, eg:
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <tchar.h>
int _tmain(int argc, TCHAR *argv [])
{
int count;
HKEY hkResult;
DWORD dwDisposition;
if (argc < 1)
{
_tprintf(_T("There are no arguments, pleas type one at least. \n"));
}
else if (_tcscmp(argv[1], _T("-Clave")) == 0)
{
if (argc < 3)
{
_tprintf(_T("There are not enough arguments typed in. \n"));
}
else if (_tcsicmp(argv[2], _T("HKCU")) == 0)
{
if (_tcscmp(argv[3], _T("")) != 0)
{
_tprintf(_T("You are going to create HKCU sub-key: %s \n"), argv[3]);
if (RegCreateKeyEx(HKEY_CURRENT_USER, argv[3], 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkResult, &dwDisposition) == 0)
{
if (dwDisposition == REG_CREATED_NEW_KEY)
{
_tprintf(_T("The registry key has been created. \n"));
}
else
{
_tprintf(_T("The registry key already exists. \n"));
}
RegCloseKey(hkResult);
}
else
{
_tprintf(_T("Unable to create the registry key. \n"));
}
}
else
{
_tprintf(_T("No HKCU sub-key has been specified \n"));
}
}
else
{
_tprintf(_T("No root key has been specified \n"));
}
}
_tsystem(_T("Pause"));
return 0;
}
With that said, since you are starting a new project, you are best off forgetting that Ansi even exists and just use Unicode for everything:
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
int wmain(int argc, WCHAR *argv [])
{
int count;
HKEY hkResult;
DWORD dwDisposition;
if (argc < 1)
{
wprintf(L"There are no arguments, pleas type one at least. \n");
}
else if (wcscmp(argv[1], L"-Clave") == 0)
{
if (argc < 3)
{
wprintf(L"There are not enough arguments typed in. \n");
}
else if (_wcsicmp(argv[2], L"HKCU") == 0)
{
if (wcscmp(argv[3], L"") != 0)
{
wprintf(L"You are going to create HKCU sub-key: %s \n", argv[3]);
if (RegCreateKeyExW(HKEY_CURRENT_USER, argv[3], 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkResult, &dwDisposition) == 0)
{
if (dwDisposition == REG_CREATED_NEW_KEY)
{
wprintf(L"The registry key has been created. \n");
}
else
{
wprintf(L"The registry key already exists. \n");
}
RegCloseKey(hkResult);
}
else
{
wprintf(L"Unable to create the registry key. \n");
}
}
else
{
wprintf(L"No HKCU sub-key has been specified \n");
}
}
else
{
wprintf(L"No root key has been specified \n");
}
}
_wsystem(L"Pause");
return 0;
}

Resources