KDECore
kuser_win.cpp
Go to the documentation of this file.
00001 /* 00002 * KUser - represent a user/account (Windows) 00003 * Copyright (C) 2007 Bernhard Loos <nhuh.put@web.de> 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Library General Public 00007 * License as published by the Free Software Foundation; either 00008 * version 2 of the License, or (at your option) any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Library General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Library General Public License 00016 * along with this library; see the file COPYING.LIB. If not, write to 00017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 * Boston, MA 02110-1301, USA. 00019 */ 00020 00021 #include "kuser.h" 00022 00023 #include <QtCore/QMutableStringListIterator> 00024 #include <QtCore/QDebug> 00025 #include <QtCore/QDir> 00026 00027 #include <windows.h> 00028 #include <lm.h> 00029 #include <Sddl.h> 00030 00031 class KUser::Private : public KShared 00032 { 00033 public: 00034 PUSER_INFO_11 userInfo; 00035 PSID sid; 00036 00037 Private() : userInfo(0), sid(0) {} 00038 00039 Private(PUSER_INFO_11 userInfo_, PSID sid_ = 0) : userInfo(userInfo_) {} 00040 00041 Private(const QString &name, PSID sid_ = 0) : userInfo(0), sid(NULL) 00042 { 00043 LPBYTE servername; 00044 NET_API_STATUS status = NetGetAnyDCName(0, 0, &servername); 00045 if (status != NERR_Success) 00046 { 00047 servername = NULL; 00048 } 00049 00050 if (NetUserGetInfo((LPCWSTR) servername, (LPCWSTR) name.utf16(), 11, (LPBYTE *) &userInfo) != NERR_Success) { 00051 goto error; 00052 } 00053 if (servername) 00054 { 00055 NetApiBufferFree(servername); 00056 servername = 0; 00057 } 00058 00059 if (!sid_) { 00060 DWORD size = 0; 00061 SID_NAME_USE nameuse; 00062 DWORD cchReferencedDomainName = 0; 00063 WCHAR* referencedDomainName = NULL; 00064 00065 // the following line definitely fails: 00066 // both the sizes for sid and for referencedDomainName are Null 00067 // the needed sizes are set in size and cchReferencedDomainName 00068 LookupAccountNameW(NULL, (LPCWSTR) name.utf16(), sid, &size, referencedDomainName, &cchReferencedDomainName, &nameuse); 00069 sid = (PSID) new SID[size + 1]; 00070 referencedDomainName = new WCHAR[cchReferencedDomainName + 1]; 00071 if (!LookupAccountNameW(NULL, (LPCWSTR) name.utf16(), sid, &size, referencedDomainName, &cchReferencedDomainName, &nameuse)) { 00072 delete[] referencedDomainName; 00073 goto error; 00074 } 00075 00076 // if you want to see both the DomainName and the sid of the user 00077 // uncomment the following lines 00078 /* LPWSTR sidstring; 00079 ConvertSidToStringSidW(sid, &sidstring); 00080 qDebug() << QString("\\\\") + QString::fromUtf16(reinterpret_cast<ushort*>(referencedDomainName)) + \ 00081 "\\" + name + "(" + QString::fromUtf16(reinterpret_cast<ushort*>(sidstring)) + ")"; 00082 00083 LocalFree(sidstring);*/ 00084 delete[] referencedDomainName; 00085 } 00086 else { 00087 if (!IsValidSid(sid_)) 00088 goto error; 00089 00090 DWORD sidlength = GetLengthSid(sid_); 00091 sid = (PSID) new BYTE[sidlength]; 00092 if (!CopySid(sidlength, sid, sid_)) 00093 goto error; 00094 } 00095 00096 return; 00097 00098 error: 00099 delete[] sid; 00100 sid = 0; 00101 if (userInfo) { 00102 NetApiBufferFree(userInfo); 00103 userInfo = 0; 00104 } 00105 if (servername) 00106 { 00107 NetApiBufferFree(servername); 00108 servername = 0; 00109 } 00110 } 00111 00112 ~Private() 00113 { 00114 if (userInfo) 00115 NetApiBufferFree(userInfo); 00116 00117 delete[] sid; 00118 } 00119 }; 00120 00121 KUser::KUser(UIDMode mode) 00122 : d(0) 00123 { 00124 Q_UNUSED(mode) 00125 00126 DWORD bufferLen = UNLEN + 1; 00127 ushort buffer[UNLEN + 1]; 00128 00129 if (GetUserNameW((LPWSTR) buffer, &bufferLen)) 00130 d = new Private(QString::fromUtf16(buffer)); 00131 } 00132 00133 KUser::KUser(K_UID uid) 00134 : d(0) 00135 { 00136 DWORD bufferLen = UNLEN + 1; 00137 ushort buffer[UNLEN + 1]; 00138 SID_NAME_USE eUse; 00139 00140 if (LookupAccountSidW(NULL, uid, (LPWSTR) buffer, &bufferLen, NULL, NULL, &eUse)) 00141 d = new Private(QString::fromUtf16(buffer), uid); 00142 } 00143 00144 KUser::KUser(const QString &name) 00145 : d(new Private(name)) 00146 { 00147 } 00148 00149 KUser::KUser(const char *name) 00150 :d(new Private(QString::fromLocal8Bit(name))) 00151 { 00152 } 00153 00154 KUser::KUser(const KUser &user) 00155 : d(user.d) 00156 { 00157 } 00158 00159 KUser &KUser::operator=(const KUser &user) 00160 { 00161 d = user.d; 00162 return *this; 00163 } 00164 00165 bool KUser::operator==(const KUser &user) const 00166 { 00167 if (!isValid() || !user.isValid()) 00168 return false; 00169 return EqualSid(d->sid, user.d->sid); 00170 } 00171 00172 bool KUser::operator !=(const KUser &user) const 00173 { 00174 return !operator==(user); 00175 } 00176 00177 bool KUser::isValid() const 00178 { 00179 return d->userInfo != 0 && d->sid != 0; 00180 } 00181 00182 bool KUser::isSuperUser() const 00183 { 00184 return d->userInfo && d->userInfo->usri11_priv == USER_PRIV_ADMIN; 00185 } 00186 00187 QString KUser::loginName() const 00188 { 00189 return (d->userInfo ? QString::fromUtf16((ushort *) d->userInfo->usri11_name) : QString()); 00190 } 00191 00192 #ifndef KDE_NO_DEPRECATED 00193 QString KUser::fullName() const 00194 { 00195 return (d->userInfo ? QString::fromUtf16((ushort *) d->userInfo->usri11_full_name) : QString()); 00196 } 00197 #endif 00198 00199 QString KUser::homeDir() const 00200 { 00201 return QDir::fromNativeSeparators(QString::fromLocal8Bit(qgetenv("USERPROFILE"))); 00202 } 00203 00204 QString KUser::faceIconPath() const 00205 { 00206 // FIXME: this needs to be adapted to windows systems (BC changes) 00207 return QString(); 00208 } 00209 00210 QString KUser::shell() const 00211 { 00212 return QString::fromAscii("cmd.exe"); 00213 } 00214 00215 QList<KUserGroup> KUser::groups() const 00216 { 00217 QList<KUserGroup> result; 00218 00219 Q_FOREACH (const QString &name, groupNames()) { 00220 result.append(KUserGroup(name)); 00221 } 00222 00223 return result; 00224 } 00225 00226 QStringList KUser::groupNames() const 00227 { 00228 QStringList result; 00229 00230 if (!d->userInfo) { 00231 return result; 00232 } 00233 00234 PGROUP_USERS_INFO_0 pGroups = NULL; 00235 DWORD dwEntriesRead = 0; 00236 DWORD dwTotalEntries = 0; 00237 NET_API_STATUS nStatus; 00238 00239 nStatus = NetUserGetGroups(NULL, d->userInfo->usri11_name, 0, (LPBYTE *) &pGroups, MAX_PREFERRED_LENGTH, &dwEntriesRead, &dwTotalEntries); 00240 00241 if (nStatus == NERR_Success) { 00242 for (DWORD i = 0; i < dwEntriesRead; ++i) { 00243 result.append(QString::fromUtf16((ushort *) pGroups[i].grui0_name)); 00244 } 00245 } 00246 00247 if (pGroups) { 00248 NetApiBufferFree(pGroups); 00249 } 00250 00251 return result; 00252 } 00253 00254 K_UID KUser::uid() const 00255 { 00256 return d->sid; 00257 } 00258 00259 QVariant KUser::property(UserProperty which) const 00260 { 00261 if (which == FullName) 00262 return QVariant(d->userInfo ? QString::fromUtf16((ushort *) d->userInfo->usri11_full_name) : QString()); 00263 00264 return QVariant(); 00265 } 00266 00267 QList<KUser> KUser::allUsers() 00268 { 00269 QList<KUser> result; 00270 00271 NET_API_STATUS nStatus; 00272 PUSER_INFO_11 pUser = NULL; 00273 DWORD dwEntriesRead = 0; 00274 DWORD dwTotalEntries = 0; 00275 DWORD dwResumeHandle = 0; 00276 00277 KUser tmp; 00278 00279 do { 00280 nStatus = NetUserEnum(NULL, 11, 0, (LPBYTE*) &pUser, 1, &dwEntriesRead, &dwTotalEntries, &dwResumeHandle); 00281 00282 if ((nStatus == NERR_Success || nStatus == ERROR_MORE_DATA) && dwEntriesRead > 0) { 00283 tmp.d = new Private(pUser); 00284 result.append(tmp); 00285 } 00286 } while (nStatus == ERROR_MORE_DATA); 00287 00288 return result; 00289 } 00290 00291 QStringList KUser::allUserNames() 00292 { 00293 QStringList result; 00294 00295 NET_API_STATUS nStatus; 00296 PUSER_INFO_0 pUsers = NULL; 00297 DWORD dwEntriesRead = 0; 00298 DWORD dwTotalEntries = 0; 00299 00300 nStatus = NetUserEnum(NULL, 0, 0, (LPBYTE*) &pUsers, MAX_PREFERRED_LENGTH, &dwEntriesRead, &dwTotalEntries, NULL); 00301 00302 if (nStatus == NERR_Success) { 00303 for (DWORD i = 0; i < dwEntriesRead; ++i) { 00304 result.append(QString::fromUtf16((ushort *) pUsers[i].usri0_name)); 00305 } 00306 } 00307 00308 if (pUsers) { 00309 NetApiBufferFree(pUsers); 00310 } 00311 00312 return result; 00313 } 00314 00315 KUser::~KUser() 00316 { 00317 } 00318 00319 class KUserGroup::Private : public KShared 00320 { 00321 public: 00322 PGROUP_INFO_0 groupInfo; 00323 00324 Private() : groupInfo(NULL) {} 00325 Private(PGROUP_INFO_0 groupInfo_) : groupInfo(groupInfo_) {} 00326 Private(const QString &Name) : groupInfo(NULL) 00327 { 00328 NetGroupGetInfo(NULL, (PCWSTR) Name.utf16(), 0, (PBYTE *) &groupInfo); 00329 } 00330 00331 ~Private() 00332 { 00333 if (groupInfo) { 00334 NetApiBufferFree(groupInfo); 00335 } 00336 } 00337 }; 00338 00339 KUserGroup::KUserGroup(const QString &_name) 00340 : d(new Private(_name)) 00341 { 00342 } 00343 00344 KUserGroup::KUserGroup(const char *_name) 00345 : d(new Private(QLatin1String(_name))) 00346 { 00347 } 00348 00349 KUserGroup::KUserGroup(const KUserGroup &group) 00350 : d(group.d) 00351 { 00352 } 00353 00354 KUserGroup& KUserGroup::operator =(const KUserGroup &group) 00355 { 00356 d = group.d; 00357 return *this; 00358 } 00359 00360 bool KUserGroup::operator==(const KUserGroup &group) const 00361 { 00362 if (d->groupInfo == NULL || group.d->groupInfo == NULL) { 00363 return false; 00364 } 00365 return wcscmp(d->groupInfo->grpi0_name, group.d->groupInfo->grpi0_name) == 0; 00366 } 00367 00368 bool KUserGroup::operator!=(const KUserGroup &group) const 00369 { 00370 return !operator==(group); 00371 } 00372 00373 bool KUserGroup::isValid() const 00374 { 00375 return d->groupInfo != NULL; 00376 } 00377 00378 QString KUserGroup::name() const 00379 { 00380 if(d && d->groupInfo) 00381 return QString::fromUtf16((ushort *) d->groupInfo->grpi0_name); 00382 return QString(); 00383 } 00384 00385 QList<KUser> KUserGroup::users() const 00386 { 00387 QList<KUser> Result; 00388 00389 Q_FOREACH(const QString &user, userNames()) { 00390 Result.append(KUser(user)); 00391 } 00392 00393 return Result; 00394 } 00395 00396 QStringList KUserGroup::userNames() const 00397 { 00398 QStringList result; 00399 00400 if (!d->groupInfo) { 00401 return result; 00402 } 00403 00404 PGROUP_USERS_INFO_0 pUsers = NULL; 00405 DWORD dwEntriesRead = 0; 00406 DWORD dwTotalEntries = 0; 00407 NET_API_STATUS nStatus; 00408 00409 nStatus = NetGroupGetUsers(NULL, d->groupInfo->grpi0_name, 0, (LPBYTE *) &pUsers, MAX_PREFERRED_LENGTH, &dwEntriesRead, &dwTotalEntries, NULL); 00410 00411 if (nStatus == NERR_Success) { 00412 for (DWORD i = 0; i < dwEntriesRead; ++i) { 00413 result.append(QString::fromUtf16((ushort *) pUsers[i].grui0_name)); 00414 } 00415 } 00416 00417 if (pUsers) { 00418 NetApiBufferFree(pUsers); 00419 } 00420 00421 return result; 00422 } 00423 00424 QList<KUserGroup> KUserGroup::allGroups() 00425 { 00426 QList<KUserGroup> result; 00427 00428 NET_API_STATUS nStatus; 00429 PGROUP_INFO_0 pGroup=NULL; 00430 DWORD dwEntriesRead=0; 00431 DWORD dwTotalEntries=0; 00432 DWORD dwResumeHandle=0; 00433 00434 KUserGroup tmp(""); 00435 00436 do { 00437 nStatus = NetGroupEnum(NULL, 0, (LPBYTE*) &pGroup, 1, &dwEntriesRead, &dwTotalEntries, (PDWORD_PTR)&dwResumeHandle); 00438 00439 if ((nStatus == NERR_Success || nStatus == ERROR_MORE_DATA) && dwEntriesRead > 0) { 00440 tmp.d = new Private(pGroup); 00441 result.append(tmp); 00442 } 00443 } while (nStatus == ERROR_MORE_DATA); 00444 00445 return result; 00446 } 00447 00448 QStringList KUserGroup::allGroupNames() 00449 { 00450 QStringList result; 00451 00452 NET_API_STATUS nStatus; 00453 PGROUP_INFO_0 pGroups=NULL; 00454 DWORD dwEntriesRead=0; 00455 DWORD dwTotalEntries=0; 00456 00457 nStatus = NetGroupEnum(NULL, 0, (LPBYTE*) &pGroups, MAX_PREFERRED_LENGTH, &dwEntriesRead, &dwTotalEntries, NULL); 00458 00459 if (nStatus == NERR_Success) { 00460 for (DWORD i = 0; i < dwEntriesRead; ++i) { 00461 result.append(QString::fromUtf16((ushort *) pGroups[i].grpi0_name)); 00462 } 00463 } 00464 00465 if (pGroups) { 00466 NetApiBufferFree(pGroups); 00467 } 00468 00469 return result; 00470 } 00471 00472 KUserGroup::~KUserGroup() 00473 { 00474 }
KDE 4.6 API Reference