OpenClonk
StdRegistry.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 1998-2000, Matthes Bender
5  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
6  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
7  *
8  * Distributed under the terms of the ISC license; see accompanying file
9  * "COPYING" for details.
10  *
11  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
12  * See accompanying file "TRADEMARK" for details.
13  *
14  * To redistribute this file separately, substitute the full license texts
15  * for the above references.
16  */
17 
18 /* Some wrappers for easier access to the Windows registry */
19 
20 #include "C4Include.h"
21 #include "platform/StdRegistry.h"
22 
23 #ifdef _WIN32
24 
25 StdCopyStrBuf GetRegistryString(const char *szSubKey, const char *szValueName)
26 {
27  HKEY ckey;
28 
29  // Open the key
30  if (RegOpenKeyExW(HKEY_CURRENT_USER, GetWideChar(szSubKey), 0, KEY_READ, &ckey)!=ERROR_SUCCESS)
31  return StdCopyStrBuf();
32 
33  // Get the value
34  DWORD dwValSize = 128;
35  BYTE *sValue = new BYTE[dwValSize];
36  while(true)
37  {
38  DWORD valtype;
39  switch(RegQueryValueExW(ckey, GetWideChar(szValueName), nullptr, &valtype,
40  sValue, &dwValSize))
41  {
42  case ERROR_SUCCESS:
43  RegCloseKey(ckey);
44  if (valtype == REG_SZ)
45  {
46  StdCopyStrBuf nrv(reinterpret_cast<wchar_t*>(sValue));
47  delete[] sValue;
48  return nrv;
49  } else {
50  default:
51  delete[] sValue;
52  return StdCopyStrBuf();
53  }
54  break;
55  case ERROR_MORE_DATA:
56  delete[] sValue;
57  sValue = new BYTE[dwValSize];
58  break;
59  }
60  }
61 }
62 
63 bool SetRegistryString(const char *szSubKey,
64  const char *szValueName,
65  const char *szValue)
66 {
67 
68  long qerr;
69  HKEY ckey;
70  DWORD disposition;
71 
72  // Open the key
73  if ((qerr=RegCreateKeyExW(HKEY_CURRENT_USER,
74  GetWideChar(szSubKey),
75  0,
76  nullptr,
77  REG_OPTION_NON_VOLATILE,
78  KEY_ALL_ACCESS,
79  nullptr,
80  &ckey,
81  &disposition
82  ))!=ERROR_SUCCESS) return false;
83 
84  // Set the value
85  StdBuf v = GetWideCharBuf(szValue);
86  if ((qerr=RegSetValueExW(ckey,
87  GetWideChar(szValueName),
88  0,
89  REG_SZ,
90  getBufPtr<BYTE>(v),
91  v.getSize()
92  ))!=ERROR_SUCCESS) { RegCloseKey(ckey); return false; }
93 
94  // Close the key
95  RegCloseKey(ckey);
96 
97  return true;
98 }
99 
100 static bool DeleteRegistryKey(HKEY hKey, const wchar_t *szSubKey)
101 {
102  HKEY ckey;
103  // Open the key
104  if (RegOpenKeyExW(hKey, szSubKey, 0, KEY_ALL_ACCESS, &ckey) != ERROR_SUCCESS) return false;
105  // Delete all subkeys
106  wchar_t strChild[1024 + 1];
107  while (RegEnumKeyW(ckey, 0, strChild, 1024) == ERROR_SUCCESS)
108  if (!DeleteRegistryKey(ckey, strChild))
109  return false;
110  // Close the key
111  RegCloseKey(ckey);
112 
113  // Delete the key
114  if (RegDeleteKeyW(hKey, szSubKey) != ERROR_SUCCESS) return false;
115  // Success
116  return true;
117 }
118 
119 static bool SetRegClassesRoot(const wchar_t *szSubKey,
120  const wchar_t *szValueName,
121  const wchar_t *szStringValue)
122 {
123 
124  long qerr;
125  HKEY ckey;
126  DWORD disposition;
127 
128  // Open the key
129  if ((qerr=RegCreateKeyExW(HKEY_CLASSES_ROOT,
130  szSubKey,
131  0,
132  nullptr,
133  REG_OPTION_NON_VOLATILE,
134  KEY_ALL_ACCESS,
135  nullptr,
136  &ckey,
137  &disposition
138  ))!=ERROR_SUCCESS) return false;
139 
140  // Set the value
141  if ((qerr=RegSetValueExW(ckey,
142  szValueName,
143  0,
144  REG_SZ,
145  (const BYTE*)szStringValue,
146  (wcslen(szStringValue) + 1) * sizeof(wchar_t)
147  ))!=ERROR_SUCCESS) { RegCloseKey(ckey); return false; }
148 
149  // Close the key
150  RegCloseKey(ckey);
151 
152  return true;
153 }
154 
155 bool SetRegShell(const wchar_t *szClassName,
156  const wchar_t *szShellName,
157  const wchar_t *szShellCaption,
158  const wchar_t *szCommand,
159  bool fMakeDefault)
160 {
161  wchar_t szKeyName[256+1];
162  // Set shell caption
163  _snwprintf(szKeyName,256,L"%s\\Shell\\%s",szClassName,szShellName);
164  if (!SetRegClassesRoot(szKeyName, nullptr, szShellCaption)) return false;
165  // Set shell command
166  _snwprintf(szKeyName,256,L"%s\\Shell\\%s\\Command",szClassName,szShellName);
167  if (!SetRegClassesRoot(szKeyName, nullptr, szCommand)) return false;
168  // Set as default command
169  if (fMakeDefault)
170  {
171  _snwprintf(szKeyName, 256,L"%s\\Shell", szClassName);
172  if (!SetRegClassesRoot(szKeyName, nullptr, szShellName)) return false;
173  }
174  return true;
175 }
176 
177 bool RemoveRegShell(const char *szClassName,
178  const char *szShellName)
179 {
180  wchar_t strKey[256+1];
181  _snwprintf(strKey, 256, L"%s\\Shell\\%s", GetWideChar(szClassName).p, GetWideChar(szShellName).p);
182  if (!DeleteRegistryKey(HKEY_CLASSES_ROOT, strKey)) return false;
183  return true;
184 }
185 
186 //------------------------------ Window Position ------------------------------------------
187 
188 bool StoreWindowPosition(HWND hwnd,
189  const char *szWindowName,
190  const char *szSubKey,
191  bool fStoreSize)
192 {
193  RECT winpos;
194  char regstr[100];
195  if (IsZoomed(hwnd))
196  return SetRegistryString(szSubKey,szWindowName,"Maximized");
197  if (IsIconic(hwnd))
198  return SetRegistryString(szSubKey,szWindowName,"Minimized");
199  if (!GetWindowRect(hwnd,&winpos)) return false;
200  if (fStoreSize) sprintf(regstr,"%ld,%ld,%ld,%ld",winpos.left,winpos.top,winpos.right-winpos.left,winpos.bottom-winpos.top);
201  else sprintf(regstr,"%ld,%ld",winpos.left,winpos.top);
202  return SetRegistryString(szSubKey,szWindowName,regstr);
203 }
204 
205 bool RestoreWindowPosition(HWND hwnd,
206  const char *szWindowName,
207  const char *szSubKey,
208  bool fHidden)
209 {
210  char buffer2[5];
211  int x,y,wdt,hgt;
212  bool fSetSize=true;
213  StdCopyStrBuf regstr = GetRegistryString(szSubKey,szWindowName);
214  // No position stored: cannot restore
215  if (regstr.isNull())
216  return false;
217  if (regstr == "Maximized")
218  return !!ShowWindow(hwnd,SW_MAXIMIZE | SW_NORMAL);
219  if (regstr == "Minimized")
220  return !!ShowWindow(hwnd,SW_MINIMIZE | SW_NORMAL);
221  SCopySegment(regstr.getData(),0,buffer2,',',4); sscanf(buffer2,"%i",&x);
222  SCopySegment(regstr.getData(),1,buffer2,',',4); sscanf(buffer2,"%i",&y);
223  if (SCopySegment(regstr.getData(),2,buffer2,',',4)) sscanf(buffer2,"%i",&wdt); else fSetSize=false;
224  if (SCopySegment(regstr.getData(),3,buffer2,',',4)) sscanf(buffer2,"%i",&hgt); else fSetSize=false;
225  if (!fSetSize)
226  {
227  RECT winpos; if (!GetWindowRect(hwnd,&winpos)) return false;
228  wdt=winpos.right-winpos.left; hgt=winpos.bottom-winpos.top;
229  }
230  // Move window
231  WINDOWPLACEMENT wp; memset(&wp, 0, sizeof(WINDOWPLACEMENT)); wp.length = sizeof(WINDOWPLACEMENT);
232  GetWindowPlacement(hwnd, &wp);
233  RECT normalpos;
234  normalpos.left = x; normalpos.right = wdt + x;
235  normalpos.top = y; normalpos.bottom = hgt + y;
236  wp.rcNormalPosition = normalpos;
237  if (SetWindowPlacement(hwnd, &wp))
238  return false;
239  // Hide window
240  if (fHidden)
241  return !!ShowWindow(hwnd, SW_HIDE);
242  // Show window
243  return !!ShowWindow(hwnd, SW_NORMAL);
244 }
245 
246 //------------------------------ Registry compiler ------------------------------------------
247 
248 // *** StdCompilerConfigWrite
249 
250 StdCompilerConfigWrite::StdCompilerConfigWrite(HKEY hRoot, const char *szPath)
251  : iDepth(0), pKey(new Key())
252 {
253  pKey->Name = szPath;
254  pKey->subindex = 0;
255  pKey->Handle = nullptr;
256  CreateKey(hRoot);
257 }
258 
259 StdCompilerConfigWrite::~StdCompilerConfigWrite()
260 {
261  assert(!iDepth);
262  if (pKey->Handle) RegCloseKey(pKey->Handle);
263  delete pKey;
264 }
265 
266 bool StdCompilerConfigWrite::Name(const char *szName)
267 {
268  // Open parent key (if not already done so)
269  CreateKey();
270  // Push new subkey onto the stack
271  auto *pnKey = new Key();
272  pnKey->Handle = nullptr;
273  pnKey->subindex = 0;
274  if (pKey->LastChildName == szName)
275  pnKey->Name.Format("%s%d", szName, (int)++pKey->subindex);
276  else
277  {
278  pnKey->Name = szName;
279  pKey->LastChildName = szName;
280  }
281  pnKey->Parent = pKey;
282  pKey = pnKey;
283  iDepth++;
284  last_written_string.clear();
285  return true;
286 }
287 
288 void StdCompilerConfigWrite::NameEnd(bool fBreak)
289 {
290  assert(iDepth);
291  // Close current key
292  if (pKey->Handle)
293  RegCloseKey(pKey->Handle);
294  // Pop
295  Key *poKey = pKey;
296  pKey = poKey->Parent;
297  delete poKey;
298  iDepth--;
299  last_written_string.clear();
300 }
301 
302 bool StdCompilerConfigWrite::FollowName(const char *szName)
303 {
304  NameEnd(); return Name(szName);
305 }
306 
307 bool StdCompilerConfigWrite::Default(const char *szName)
308 {
309  // Open parent
310  CreateKey();
311  // Remove key/value (failsafe)
312  DeleteRegistryKey(pKey->Handle, GetWideChar(szName));
313  RegDeleteValueW(pKey->Handle, GetWideChar(szName));
314  // Handled
315  return true;
316 }
317 
318 bool StdCompilerConfigWrite::Separator(Sep eSep)
319 {
320  // Just append separator and re-write last string
321  const char s[2] = { SeparatorToChar(eSep) , '\0' };
322  WriteString(s);
323  return true;
324 }
325 
326 void StdCompilerConfigWrite::DWord(int32_t &rInt)
327 {
328  WriteDWord(rInt);
329 }
330 void StdCompilerConfigWrite::DWord(uint32_t &rInt)
331 {
332  WriteDWord(rInt);
333 }
334 void StdCompilerConfigWrite::Word(int16_t &rInt)
335 {
336  WriteDWord(rInt);
337 }
338 void StdCompilerConfigWrite::Word(uint16_t &rInt)
339 {
340  WriteDWord(rInt);
341 }
342 void StdCompilerConfigWrite::Byte(int8_t &rInt)
343 {
344  WriteDWord(rInt);
345 }
346 void StdCompilerConfigWrite::Byte(uint8_t &rInt)
347 {
348  WriteDWord(rInt);
349 }
350 void StdCompilerConfigWrite::Boolean(bool &rBool)
351 {
352  WriteDWord(rBool ? 1 : 0);
353 }
354 void StdCompilerConfigWrite::Character(char &rChar)
355 {
356  WriteString(FormatString("%c", rChar).getData());
357 }
358 
359 void StdCompilerConfigWrite::String(char *szString, size_t iMaxLength, RawCompileType eType)
360 {
361  WriteString(szString);
362 }
363 
364 void StdCompilerConfigWrite::String(char **pszString, RawCompileType eType)
365 {
366  WriteString(pszString ? *pszString : "");
367 }
368 
369 void StdCompilerConfigWrite::String(std::string &str, RawCompileType eType)
370 {
371  WriteString(str.c_str());
372 }
373 
374 void StdCompilerConfigWrite::Raw(void *pData, size_t iSize, RawCompileType eType)
375 {
376  excCorrupt("Raw values aren't supported for registry compilers!");
377 }
378 
379 void StdCompilerConfigWrite::Begin()
380 {
381  assert(!iDepth);
382 }
383 
384 void StdCompilerConfigWrite::End()
385 {
386  assert(!iDepth);
387 }
388 
389 void StdCompilerConfigWrite::CreateKey(HKEY hParent)
390 {
391  // Already open?
392  if (pKey->Handle)
393  return;
394  // Open/Create registry key
395  if (RegCreateKeyExW(hParent ? hParent : pKey->Parent->Handle,
396  pKey->Name.GetWideChar(),
397  0, nullptr, REG_OPTION_NON_VOLATILE,
398  KEY_WRITE, nullptr,
399  &pKey->Handle, nullptr) != ERROR_SUCCESS)
400  excCorrupt("Could not create key %s!", pKey->Name.getData());
401 }
402 
403 void StdCompilerConfigWrite::WriteDWord(uint32_t iVal)
404 {
405  // Set the value
406  if (RegSetValueExW(pKey->Parent->Handle, pKey->Name.GetWideChar(),
407  0, REG_DWORD, reinterpret_cast<const BYTE *>(&iVal),
408  sizeof(iVal)) != ERROR_SUCCESS)
409  excCorrupt("Could not write key %s!", pKey->Name.getData());
410 }
411 
412 void StdCompilerConfigWrite::WriteString(const char *szString)
413 {
414  // Append to write-string and just re-write
415  // This is probably pretty inefficient, but config saving only uses it for a few key overloads
416  last_written_string += szString;
417  StdBuf v = GetWideCharBuf(last_written_string.c_str());
418  if (RegSetValueExW(pKey->Parent->Handle, pKey->Name.GetWideChar(),
419  0, REG_SZ, getBufPtr<BYTE>(v), v.getSize()) != ERROR_SUCCESS)
420  excCorrupt("Could not write key %s!", pKey->Name.getData());
421 }
422 
423 // *** StdCompilerConfigRead
424 
425 StdCompilerConfigRead::StdCompilerConfigRead(HKEY hRoot, const char *szPath)
426  : iDepth(0), pKey(new Key())
427 {
428  pKey->Name = szPath;
429  pKey->Virtual = false;
430  pKey->subindex = 0;
431  // Open root
432  if (RegOpenKeyExW(hRoot, GetWideChar(szPath),
433  0, KEY_READ,
434  &pKey->Handle) != ERROR_SUCCESS)
435  pKey->Handle = nullptr;
436 }
437 
438 StdCompilerConfigRead::~StdCompilerConfigRead()
439 {
440  assert(!iDepth);
441  if (pKey->Handle) RegCloseKey(pKey->Handle);
442  delete pKey;
443 }
444 
445 bool StdCompilerConfigRead::Name(const char *szName)
446 {
447  // Adjust key name for lists
448  StdCopyStrBuf sName;
449  if (pKey->LastChildName == szName)
450  sName.Format("%s%d", szName, (int)++pKey->subindex);
451  else
452  {
453  sName = szName;
454  pKey->LastChildName = szName;
455  }
456  bool fFound = true;
457  // Try to open registry key
458  HKEY hSubKey; DWORD dwType = 0;
459  if (RegOpenKeyExW(pKey->Handle, sName.GetWideChar(),
460  0, KEY_READ,
461  &hSubKey) != ERROR_SUCCESS)
462  {
463  hSubKey = nullptr;
464  // Try to query value (exists?)
465  if (RegQueryValueExW(pKey->Handle, sName.GetWideChar(),
466  nullptr, &dwType, nullptr, nullptr) != ERROR_SUCCESS)
467  fFound = false;
468  }
469  // Push new subkey on the stack
470  Key *pnKey = new Key();
471  pnKey->Handle = hSubKey;
472  pnKey->Name = sName;
473  pnKey->subindex = 0;
474  pnKey->Parent = pKey;
475  pnKey->Virtual = !fFound;
476  pnKey->Type = dwType;
477  pKey = pnKey;
478  iDepth++;
479  ResetLastString();
480  return fFound;
481 }
482 
483 void StdCompilerConfigRead::NameEnd(bool fBreak)
484 {
485  assert(iDepth);
486  // Close current key
487  if (pKey->Handle)
488  RegCloseKey(pKey->Handle);
489  // Pop
490  Key *poKey = pKey;
491  pKey = poKey->Parent;
492  delete poKey;
493  iDepth--;
494  ResetLastString();
495 }
496 
497 void StdCompilerConfigRead::ResetLastString()
498 {
499  has_read_string = false;
500  has_separator_mismatch = false;
501  last_read_string.clear();
502 }
503 
504 bool StdCompilerConfigRead::FollowName(const char *szName)
505 {
506  NameEnd(); return Name(szName);
507 }
508 
509 bool StdCompilerConfigRead::Separator(Sep eSep)
510 {
511  // Make sure there's a string to work on
512  ReadString();
513  // Match?
514  if (last_read_string.size() && (last_read_string.front() == SeparatorToChar(eSep)))
515  {
516  // Match found. Just advance.
517  last_read_string = last_read_string.substr(1);
518  return true;
519  }
520  else
521  {
522  // Separator mismatch? Let all read attempts fail until the correct separator is found or the naming ends.
523  has_separator_mismatch = true;
524  return false;
525  }
526 }
527 
528 void StdCompilerConfigRead::NoSeparator() {
529  has_separator_mismatch = false;
530 }
531 
532 void StdCompilerConfigRead::DWord(int32_t &rInt)
533 {
534  rInt = int32_t(ReadDWord());
535 }
536 void StdCompilerConfigRead::DWord(uint32_t &rInt)
537 {
538  rInt = ReadDWord();
539 }
540 void StdCompilerConfigRead::Word(int16_t &rInt)
541 {
542  rInt = int16_t(ReadDWord());
543 }
544 void StdCompilerConfigRead::Word(uint16_t &rInt)
545 {
546  rInt = uint16_t(ReadDWord());
547 }
548 void StdCompilerConfigRead::Byte(int8_t &rInt)
549 {
550  rInt = int8_t(ReadDWord());
551 }
552 void StdCompilerConfigRead::Byte(uint8_t &rInt)
553 {
554  rInt = uint8_t(ReadDWord());
555 }
556 void StdCompilerConfigRead::Boolean(bool &rBool)
557 {
558  try
559  {
560  ReadString();
561  rBool = (!has_separator_mismatch && (last_read_string == "true"));
562  }
563  catch (NotFoundException *pExc)
564  {
565  delete pExc;
566  uint32_t iVal = ReadDWord();
567  rBool = !! iVal;
568  }
569 }
570 void StdCompilerConfigRead::Character(char &rChar)
571 {
572  try
573  {
574  ReadString();
575  rChar = (last_read_string.length() && !has_separator_mismatch) ? last_read_string.front() : '\0';
576  }
577  catch (NotFoundException *pExc)
578  {
579  delete pExc;
580  uint32_t iVal = ReadDWord();
581  rChar = char(iVal);
582  }
583 }
584 
585 void StdCompilerConfigRead::String(char *szString, size_t iMaxLength, RawCompileType eType)
586 {
587  std::string s;
588  String(s, eType);
589  SCopy(s.c_str(), szString, iMaxLength);
590 }
591 
592 void StdCompilerConfigRead::String(char **pszString, RawCompileType eType)
593 {
594  // Read string, copy into buffer and release buffer (to use buffer allocation method)
595  std::string s;
596  String(s, eType);
597  StdStrBuf sbuf(s.c_str(), true);
598  *pszString = sbuf.GrabPointer();
599 }
600 
601 void StdCompilerConfigRead::String(std::string &str, RawCompileType type)
602 {
603  // Read from string until end marker is found
604  ReadString();
605  if (has_separator_mismatch || !last_read_string.length()) { str = "\0"; return; }
606  size_t string_end_pos = 0;
607  const char *s = last_read_string.c_str();
608  size_t spos = 0;
609  while (!IsStringEnd(s[spos], type)) ++spos;
610  if (spos < last_read_string.length())
611  {
612  str = last_read_string.substr(0, spos);
613  last_read_string = last_read_string.substr(spos);
614  }
615  else
616  {
617  str = last_read_string;
618  last_read_string.clear();
619  }
620 }
621 
622 void StdCompilerConfigRead::Raw(void *pData, size_t iSize, RawCompileType eType)
623 {
624  excCorrupt(nullptr, "Raw values aren't supported for registry compilers!");
625 }
626 
627 void StdCompilerConfigRead::Begin()
628 {
629  assert(!iDepth);
630 }
631 
632 void StdCompilerConfigRead::End()
633 {
634  assert(!iDepth);
635 }
636 
637 uint32_t StdCompilerConfigRead::ReadDWord()
638 {
639  // Virtual key?
640  if (pKey->Virtual)
641  { excNotFound("Could not read value %s! Parent key doesn't exist!", pKey->Name.getData()); return 0; }
642  // Wrong type?
643  if (pKey->Type != REG_DWORD && pKey->Type != REG_DWORD_LITTLE_ENDIAN)
644  { excNotFound("Wrong value type!"); return 0; }
645  // Clear previous string
646  ResetLastString();
647  // Read
648  uint32_t iVal; DWORD iSize = sizeof(iVal);
649  if (RegQueryValueExW(pKey->Parent->Handle, pKey->Name.GetWideChar(),
650  nullptr, nullptr,
651  reinterpret_cast<LPBYTE>(&iVal),
652  &iSize) != ERROR_SUCCESS)
653  { excNotFound("Could not read value %s!", pKey->Name.getData()); return 0; }
654  // Check size
655  if (iSize != sizeof(iVal))
656  { excCorrupt("Wrong size of a DWord!"); return 0; }
657  // Return
658  return iVal;
659 }
660 
661 void StdCompilerConfigRead::ReadString()
662 {
663  // Already read?
664  if (!has_read_string)
665  {
666  ResetLastString();
667  // Virtual key?
668  if (pKey->Virtual)
669  {
670  excNotFound("Could not read value %s! Parent key doesn't exist!", pKey->Name.getData()); return;
671  }
672  // Wrong type?
673  if (pKey->Type != REG_SZ)
674  {
675  excNotFound("Wrong value type!"); return;
676  }
677  // Get size of string
678  DWORD iSize;
679  if (RegQueryValueExW(pKey->Parent->Handle, pKey->Name.GetWideChar(),
680  nullptr, nullptr,
681  nullptr,
682  &iSize) != ERROR_SUCCESS)
683  {
684  excNotFound("Could not read value %s!", pKey->Name.getData()); return;
685  }
686  // Allocate string
687  StdBuf Result; Result.SetSize(iSize);
688  // Read
689  if (RegQueryValueExW(pKey->Parent->Handle, pKey->Name.GetWideChar(),
690  nullptr, nullptr,
691  reinterpret_cast<BYTE *>(Result.getMData()),
692  &iSize) != ERROR_SUCCESS)
693  {
694  excNotFound("Could not read value %s!", pKey->Name.getData()); return;
695  }
696  // Check size
697  if (wcslen(getBufPtr<wchar_t>(Result)) + 1 != iSize / sizeof(wchar_t))
698  {
699  excCorrupt("Wrong size of a string!"); return;
700  }
701  // Remember string
702  StdStrBuf str_result(getBufPtr<wchar_t>(Result));
703  last_read_string = str_result.getData();
704  has_read_string = true;
705  }
706 }
707 
708 #endif // _WIN32
char * GrabPointer()
Definition: StdBuf.h:459
Definition: StdBuf.h:29
void SCopy(const char *szSource, char *sTarget, size_t iMaxL)
Definition: Standard.cpp:152
C4String * String(const char *str)
Definition: C4AulDefFunc.h:30
#define sprintf
Definition: Standard.h:164
StdStrBuf::wchar_t_holder GetWideChar(const char *utf8, bool double_null_terminate=false)
bool SCopySegment(const char *szString, int iSegment, char *sTarget, char cSeparator, int iMaxL, bool fSkipWhitespace)
Definition: Standard.cpp:273
uint8_t BYTE
void Format(const char *szFmt,...) GNUC_FORMAT_ATTRIBUTE_O
Definition: StdBuf.cpp:174
void SetSize(size_t inSize)
Definition: StdBuf.h:204
bool isNull() const
Definition: StdBuf.h:441
size_t getSize() const
Definition: StdBuf.h:101
const char * getData() const
Definition: StdBuf.h:442
StdBuf GetWideCharBuf(const char *utf8)
uint32_t DWORD
#define s
void * getMData()
Definition: StdBuf.h:100
int iSize
Definition: TstC4NetIO.cpp:32
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:270