2011-02-08 3 views
0

Я не разработчик на C++, поэтому я думаю, что это моя ошибка, что моя программа не работает. Я хочу найти SID для группы окон и вернуть читаемый SID.Преобразование SID в строку

wchar_t* SpcLookupName(LPCTSTR lpszSystemName, LPCTSTR lpszAccountName) { 

PSID   Sid; 
DWORD  cbReferencedDomainName, cbSid; 
LPTSTR  ReferencedDomainName; 
SID_NAME_USE eUse; 

cbReferencedDomainName = cbSid = 0; 
if (LookupAccountName(lpszSystemName, lpszAccountName, 0, &cbSid, 
        0, &cbReferencedDomainName, &eUse)) { 
    SetLastError(ERROR_NONE_MAPPED); 
    return 0; 
} 

if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return 0; 

if (!(Sid = (PSID)LocalAlloc(LMEM_FIXED, cbSid))) return 0; 

ReferencedDomainName = (LPTSTR)LocalAlloc(LMEM_FIXED, cbReferencedDomainName); 

if (!ReferencedDomainName) { 
    LocalFree(Sid); 
    return 0; 
} 

if (!LookupAccountName(lpszSystemName, lpszAccountName, Sid, &cbSid, 
        ReferencedDomainName, &cbReferencedDomainName, &eUse)) { 
    LocalFree(ReferencedDomainName); 
    LocalFree(Sid); 
    return 0; 
} 

wchar_t* psz; 

// Loading ConvertSidToStringSid 
typedef BOOL (WINAPI *tConvertSidToStringSid)(PSID,wchar_t*); 

tConvertSidToStringSid pConvertSidToStringSid=0; 

HINSTANCE handle = ::LoadLibrary("Advapi32.dll"); 

pConvertSidToStringSid = (tConvertSidToStringSid) ::GetProcAddress(handle, "ConvertSidToStringSidA"); 

if(pConvertSidToStringSid(Sid, psz)){        
    return psz; 
} 
} 

Моя проблема в том, что функция возвращает только некоторые странные символы, а не SID, почему?

+0

Как вы делаете печать? - функция возвращает указатель на строку, я не вижу оператора печати? – Tom

+0

Я протестировал его с помощью окна сообщения, но он не находится в коде прямо сейчас. – Taram777

+0

Действительно, не будет ли это проще в чем-то вроде PowerShell или .net или Python, где он будет завершен для вас. Взлом инструментов, подобных этому на C++, является болезненным, особенно если вы не очень свободно владеете C++. Возможно, есть даже консольное приложение res kit, которое сделает это для вас в любом случае! –

ответ

1

Есть несколько очевидных вещей неправильно с вашим кодом ...

1) прототип ConvertSidToStringSid() является BOOL ConvertSidToStringSid(PSID Sid, LPTSTR *StringSid); Это означает, что ваш ЬурейеЕ должен быть typedef BOOL (WINAPI *tConvertSidToStringSid)(PSID,LPTSTR *);

2) вы отрываясь версию ANSI и пропусканием wchar_t * ... Вы должны либо искать широкий характер версии ConvertSidToStringSid() или, лучшее решение, имхо, искать ConvertSidToStringSid и используйте TCHAR *, а не wchar_t *, так как это будет работать независимо от настроек компиляции юникода и соответствует typedef.

3) наконец, из-за сломанного typedef вам разрешено передать неправильный тип данных в функцию. Он хочет LPTSTR *, и вы передаете ему LPTSTR (ну, на самом деле вы передаете wchar_t * ... LPTSTR - это действительно тип ввода в формате unicode, который сопоставляется с wchar_t *, если вы используете широкие символы, но функцию, которая . вы звоните хочет указатель на этот указатель, а не сам указатель

Таким образом, фиксированный код:

typedef BOOL (WINAPI *tConvertSidToStringSid)(PSID,LPTSTR*); 

tConvertSidToStringSid pConvertSidToStringSid=0; 

HINSTANCE handle = ::LoadLibrary("Advapi32.dll"); 



pConvertSidToStringSid = (tConvertSidToStringSid) ::GetProcAddress(handle, #ConvertSidToStringSid); 

if(pConvertSidToStringSid(Sid, &psz)){        
    return psz; 
} 

Обратите внимание на изменения в ЬурейеЕ, изменения в вызове GetProcAddress (где мы используем # для форматирования имени функции (которая будет либо ConvertSidToStringSidA, либо ConvertSidToStringSidW в зависимости от ваших настроек юникода), и изменение на pas s адрес psz, а не самого указателя.

И теперь ваша единственная проблема в том, что вы потенциально протекаете этот psz, если только вы не уверены, что освободите его в вызывающем абоненте с вызовом LocalFree().

Обратите внимание, что в зависимости от вызывающего кода, вы можете преобразовать ЬурейуЮ в wchar_t **, а не LPTSTR *, а затем использовать версию ConvertSidToStringSidW, чтобы заставить результат всегда быть строкой широких символов.

+0

Я пробовал это так, но теперь я получаю эти два сообщения: «stray» # «в программе» и «ConvertSidToStringSid» не был объявлен в этой области ». – Taram777

+0

Хорошо, я никогда не компилировал его и не мог беспокоиться о том, чтобы прорвать еще один макрос для имени в текстовой форме. Просто используйте версию wchar_t и ConvertSidToStringSidW, но убедитесь, что вы исправили typedef и вызов функции. –

+0

Большое спасибо – Taram777

0

Возможно, ваш звонок pConvertSidToStringSid(Sid, psz) не увенчался успехом и SpcLookupName() Возвращаемое значение не определено, потому что вы ничего не возвращаете.

И почему вы смешиваете ConvertSidToStringSidA с wchar_t? Было бы лучше использовать ConvertSidToStringSid из Sddl.h непосредственно:

#define _WIN32_WINNT 0x0500 
#include <Sddl.h> 

Вы также должны вернуться LPTSTR из вашей функции вместо wchar_t *

+0

pConvertSidToStringSid (Sid, psz) успешно. Я тестировал его с помощью окна сообщений, это просто не в коде, который я вставлял здесь. – Taram777

0

используется ConvertSidToStringSidA, который будет возвращать ANSI строку, в то же время вы ожидаете wchar_t* , Вместо этого попробуйте использовать ConvertSidToStringSidW. Или просто укажите Sddl.h и используйте ConvertSidToStringSid.

+0

Я попробовал это с ConvertSidToStringSidW раньше, и это не сработало. Так что ConvertSidToStringSidA была просто еще одной попыткой, извините за то, что она смешала его здесь. Я включил ssdl.h, но если я назову «ConvertSidToStringSid», компилятор говорит, что «ConvertSidToStringSid» не был объявлен в этой области ». – Taram777

0

Вы вызываете версию функции ANSI, если хотите версию Unicode "ConvertSidToStringSidW".

Также у вас есть небольшая утечка памяти, так как вы не всегда освобождаетесь Sid.