Ist es irgendwie möglich, eine Vorlage für WinAPI-Funktionen zu erstellen? Beispielsweise gibt es zwei ähnliche Funktionen (LookupPrivilegeName und LookupPrivilegeDisplayName), jedoch mit unterschiedlichen Parametern. Ich rufe beide Funktionen wie folgt auf: der erste Aufruf ruft die erforderliche Puffergröße ab, der zweite Aufruf gibt den gewünschten Wert zurück. Wenn dies nicht möglich ist, gibt es alternative Möglichkeiten, den Code kompakter zu gestalten?Vorlage für WinAPI-Funktionen
Antwort
Sie wollen wahrscheinlich so etwas wie:
template<typename CharT>
bool LookupPriviledgeDisplayName(CharT const *, CharT const *, DWORD *, std::basic_string<CharT> & strDisplayName);
template<>
bool LookupPriviledgeDisplayName<char>(char const * pszSystem, char const * pszName, DWORD * pdwLangID, std::basic_string <char> & strDisplayName)
{
DWORD dwLength = 0;
if(!LookupPrivilegeDisplayNameA(pszSystem, pszName, nullptr, &dwLength, pdwLangID))
return false;
std::vector<char> buffer(dwLength + 1);
if(!LookupPrivilegeDisplayNameA(pszSystem, pszName, &buffer[0], &dwLength, pdwLangID))
return false;
strDisplayName.assign(&buffer[0], &buffer[0] + dwLength);
return true;
}
template<>
bool LookupPriviledgeDisplayName<wchar_t>(wchar_t const * pszSystem, wchar_t const * pszName, DWORD * pdwLangID, std::basic_string <wchar_t> & strDisplayName)
{
DWORD dwLength = 0;
if(!LookupPrivilegeDisplayNameW(pszSystem, pszName, nullptr, &dwLength, pdwLangID))
return false;
std::vector<wchar_t> buffer(dwLength + 1);
if(!LookupPrivilegeDisplayNameW(pszSystem, pszName, &buffer[0], &dwLength, pdwLangID))
return false;
strDisplayName.assign(&buffer[0], &buffer[0] + dwLength);
return true;
}
Dies ist eine Definition von Copy-Pasta, auch gibt es keine Notwendigkeit, 'A' Varianten zu nennen. – VTT
weil 'LookupPrivilege [Display] NameW' ist sehr schwer Call (benutzter RPC Aufruf an lsass) viel besser verwenden Sie einige zugewiesene Puffer im ersten Aufruf, stattdessen 0. und nur wenn es fehlschlägt, neu zugewiesenen Puffer für zweiten Aufruf – RbMm
Vielleicht ich bin nicht so richtig ausdrücken meine Gedanken. Ich meine, gibt es eine Möglichkeit, eine einzige Vorlage für zwei Winapi-Funktionen mit variablen Parametern zu erstellen? Etwas wie '' 'Vorlage
Etwas Ähnliches. Die Grundidee besteht darin, Code nach Funktionalität zu trennen, um Doppelarbeit zu vermeiden.
#include <memory>
#include <string>
#include <iostream>
#include <system_error>
#include <cassert>
// Error handler.
void
On_Error(const ::DWORD error_code)
{
throw ::std::system_error{static_cast<int>(error_code), ::std::system_category()};
}
// Error check.
void
Validate_LookupPrivilegeNameSuccess(const ::BOOL result, const bool expect_insufficient_buffer)
{
if(FALSE == result)
{
auto const error_code{::GetLastError()};
if((ERROR_INSUFFICIENT_BUFFER == error_code) && (!expect_insufficient_buffer))
{
On_Error(error_code);
}
}
}
enum class
t_PrivilegeNameCategoryId
{
name
, display_name
};
// Helper class calling WinAPI methods, checking input and output.
template<t_PrivilegeNameCategoryId> class
t_LookupPrivilegeNameImpl;
template<> class
t_LookupPrivilegeNameImpl<t_PrivilegeNameCategoryId::name> final
{
public: static ::std::size_t
Lookup(const ::LPCWSTR psz_system_name, ::LUID & luid, const ::LPWSTR p_buffer, ::DWORD buffer_capacity_items_count)
{
assert((0 == buffer_capacity_items_count) || (nullptr != p_buffer));
Validate_LookupPrivilegeNameSuccess
(
::LookupPrivilegeNameW
(
psz_system_name
, ::std::addressof(luid)
, p_buffer
, ::std::addressof(buffer_capacity_items_count)
)
, nullptr == p_buffer
);
return(buffer_capacity_items_count);
}
};
template<> class
t_LookupPrivilegeNameImpl<t_PrivilegeNameCategoryId::display_name> final
{
public: static ::std::size_t
Lookup(const ::LPCWSTR psz_system_name, const ::LPCWSTR psz_display_name, const ::LPWSTR p_buffer, ::DWORD buffer_capacity_items_count)
{
assert(psz_display_name);
assert(L'\0' != psz_display_name[0]);
assert((0 == buffer_capacity_items_count) || (nullptr != p_buffer));
::DWORD language_id{};
Validate_LookupPrivilegeNameSuccess
(
::LookupPrivilegeDisplayNameW
(
psz_system_name
, psz_display_name
, p_buffer
, ::std::addressof(buffer_capacity_items_count)
, ::std::addressof(language_id)
)
, nullptr == p_buffer
);
return(buffer_capacity_items_count);
}
};
// Lookup function implementing get size -> resize buffer -> get data algorithm.
template<t_PrivilegeNameCategoryId name_category_id, typename... TArgs> void
Lookup_PrivilegeName(::std::wstring & name, TArgs &&... args)
{
try
{
name.resize(t_LookupPrivilegeNameImpl<name_category_id>::Lookup(::std::forward<TArgs>(args)..., ::LPWSTR{}, ::DWORD{}));
t_LookupPrivilegeNameImpl<name_category_id>::Lookup(::std::forward<TArgs>(args)..., name.data(), static_cast<::DWORD>(name.size()));
if(name.empty() || (L'\0' != name.back()))
{
On_Error(ERROR_UNIDENTIFIED_ERROR);
}
name.pop_back();
}
catch(...)
{
name.clear();
throw;
}
}
int main()
{
::LPCWSTR psz_system_name{};
::LUID privilege_luid{5}; // a wild guess
::std::wstring privilege_name{};
Lookup_PrivilegeName<t_PrivilegeNameCategoryId::name>(privilege_name, psz_system_name, privilege_luid);
::std::wstring privilege_display_name{};
Lookup_PrivilegeName<t_PrivilegeNameCategoryId::display_name>(privilege_display_name, psz_system_name, privilege_name.c_str());
::std::wcout << privilege_name << L"\n" << privilege_display_name << ::std::endl;
return(0);
}
Sie vermeiden den doppelten Code für die Pufferverwaltung, aber Sie tauschen das für höhere Code-Komplexität. Meiner Meinung nach ist dies ein Beispiel, bei dem [DRY] (https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) nicht so weit wie möglich verfolgt werden sollte, da es den Code schwieriger zu verstehen macht. Ich wette, Sie sparen nicht einmal viele LOC im Vergleich zu zwei einfachen Überladungen. – zett42
Mein russischer Freund erklärte mir die Einschränkungen von Vorlagen. Statt dessen schlug er vor, Funktionen mit Kontextwechsel zu verwenden. In meiner Situation wird es so etwas wie diese:
BOOL LookupData(DWORD context, PLUID luid, wstring input, wstring & output) {
BOOL status = TRUE;
DWORD buflen = 0, lang = 0;
switch (context) {
case 0: status = LookupPrivilegeName(NULL, luid, NULL, &buflen); break;
case 1: status = LookupPrivilegeDisplayName(NULL, input.c_str(), NULL, &buflen, &lang); break;
default: return FALSE;
}
if (!status && ERROR_INSUFFICIENT_BUFFER != GetLastError()) return status;
auto buffer = make_unique<wchar_t[]>(buflen);
switch (context) {
case 0: status = LookupPrivilegeName(NULL, luid, buffer.get(), &buflen); break;
case 1: status = LookupPrivilegeDispayName(NULL, input.c_str(), buffer.get(), &buflen, &lang); break;
}
if (!status) {
buf.release();
return status;
}
output = buf.get();
buf.release();
return status;
}
Jetzt kann ich in -Schreibzyklus nach TOKEN_PRIVILEGES Strukturen erhalten:
std::wstring name, desription;
if (!LookupData(0, tp->Privipeges[i].Luid, L"", name)) break;
if (!LookupData(1, NULL, name, description)) break;
std::wcout << name << L" - " << std::endl;
Natürlich, es ist schmutziger Trick, aber es funktioniert.
- 1. Vorlage Abzug für variadische Vorlage Lambda Argumente
- 2. Vorlage für Python Paket Index (PyPi) Vorlage
- 3. Vorlage Argumentabzug für Lambdas
- 4. Vorlage Metaprogrammierung für diese?
- 5. Bearbeitungsstile für normal.dotm Vorlage
- 6. Vorlage Vererbung für Lenker
- 7. Jinja Vorlage für Salz
- 8. HTML-Vorlage für Wikipedia
- 9. Vorlage für Klassenobjekte
- 10. ViewChildren für ng-Vorlage
- 11. Django Vorlage für Schleife
- 12. Vorlage für JSON-Daten?
- 13. Kopfzeile für editorfor Vorlage
- 14. Vorlage Argumente für Klassenobjekt
- 15. Link für neue Vorlage für Register
- 16. Anzeige für Vorlage für eine leere Liste
- 17. Dynamische ElasticSearch-Vorlage für verschachtelte
- 18. R Vorlage für evolutionäre Algorithmen?
- 19. HTML_QuickForm2 Vorlage für Datum Element
- 20. datagridcell benutzerdefinierte Vorlage für Nullwert?
- 21. Standardgröße für HTML-Newsletter-Vorlage
- 22. Freemarker Vorlage für Schleife Anweisung
- 23. Keine Vorlage für Mailer gefunden
- 24. Beispiel für grundlegende Ruhe Vorlage
- 25. Vorlage Abzug Anleitung für Funktion?
- 26. w3 Validierungshilfe für blooger Vorlage
- 27. Konvertierungseinschränkung für Bitset-Vorlage vermeiden
- 28. SonataAdmin Vorlage für Administratoren ändern
- 29. Ausgabepfad für freigegebene T4-Vorlage
- 30. Screenshots für iphone Vorlage hinzufügen
Sie könnten eine Metaprogrammierung erstellen, um eine Reihe von Parametertypen einer winapi-Funktion zuzuordnen, um eine Überladungsgruppe zu erstellen, die Sie selbst auflösen, aber dafür gibt es keine magische Lösung. –
Ja, es ist eine gängige Praxis, handliche Wrapper zu erstellen, die eine einfachere Schnittstelle bieten, Eingabeparameter validieren, Fehlercodes überprüfen usw. – VTT
Danke für die Antworten, aber wie wäre es mit einem Beispiel? Oder kannst du mich auf die nützlichen Links zu diesem Thema hinweisen? Ich muss das wirklich verstehen. – kate