Getting login name in a service routine

Posted on 2009-07-07
Last Modified: 2013-12-04
I have the following code in a dummy windows app that works just fine, but when I move the code to a service application (an application that will run as a service) it errors. By erroring I mean that the service starts and stops itself. Is there something in the code that is 'illegal' in a service app? Is there a way I can see WHY it stopped itself? I am using CBuilder++ Rad studio 2007

      NET_API_STATUS netStatus;
      WKSTA_USER_INFO_0 *buf;
      char buffer[1000];
      netStatus = NetWkstaUserGetInfo(NULL, 0, (LPBYTE *)&buf);
      wcstombs(buffer, buf->wkui0_username, 100);
      FILE* file=fopen("C:\\systemlog.txt","at");
      if (file) {
            fprintf(file,"Start : %s\n",DateTimeToStr(Now()).c_str());
            fprintf(file,"        User : %s\n", buffer);

Question by:BrianDumas
  • 2
LVL 86

Accepted Solution

jkr earned 250 total points
ID: 24794949
'NetWkstaUserGetInfo()' is most likely to fail in a service (services running under the 'LocalSystem' account have almost OS privileges, but are not allowed to use _any_ networking facilities), and since you're not checking the return value, 'wcstombs()' might cause an access violation. Since you apparently want to get the name of the logged on user, there's a new problem - with XP and later, there might be more than one. The following code should help, though:




// DisplayLocalLogons


// Scans the HKEY_USERS key of the specified computer to see who

// has their profile loaded. Returns true if someone is logged on.



BOOLEAN DisplayLocalLogons( LPWSTR ServerName, LPWSTR UserName  )


    BOOLEAN          first = TRUE;

   TCHAR          errorMessage[1024];

   TCHAR          userName[MAX_NAME_STRING], domainName[MAX_NAME_STRING];

   TCHAR          subKeyName[MAX_PATH];

   DWORD          subKeyNameSize, index;

   DWORD          userNameSize, domainNameSize;

   FILETIME     lastWriteTime;

   HKEY          usersKey;

   PSID          sid;

   SID_NAME_USE sidType;


    BYTE          subAuthorityCount;

   DWORD          authorityVal, revision;

   DWORD          subAuthorityVal[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };



   // Use RegConnectRegistry so that we work with remote computers


    if( ServerName ) {


         wprintf(L"Connecting to Registry of %s...", ServerName );

         fflush( stdout );

         if( RegConnectRegistry( ServerName, HKEY_USERS, &usersKey ) != ERROR_SUCCESS) {


              wprintf(L"\r                                                      \r");

              wprintf( L"Error opening HKEY_USERS for %s\n", ServerName );

              return FALSE;


         wprintf(L"\r                                                      \r");

    } else {

         if( RegOpenKey( HKEY_USERS, NULL, &usersKey ) != ERROR_SUCCESS ) {

              wprintf( errorMessage, L"Error opening HKEY_USERS" );

              PrintWin32Error( errorMessage, GetLastError() );

              return FALSE;





   // Enumerate keys under HKEY_USERS


   index = 0;

   subKeyNameSize = sizeof( subKeyName );

   while( RegEnumKeyEx( usersKey, index, subKeyName, &subKeyNameSize,

                        NULL, NULL, NULL, &lastWriteTime ) == ERROR_SUCCESS ) {


       // Ignore the default subkey and win2K user class subkeys


       if( wcsicmp( subKeyName, L".default" ) &&

              !wcsstr( subKeyName, L"Classes")) {


              // Convert the textual SID into a binary SID


           subAuthorityCount= swscanf( subKeyName, L"S-%d-%x-%lu-%lu-%lu-%lu-%lu-%lu-%lu-%lu",

                                       &revision, &authorityVal,








                                       &subAuthorityVal[7] );

           if( subAuthorityCount >= 3 ) {

               subAuthorityCount -= 2;



               // Note: we can only deal with authority values

               // of 4 bytes in length


               authority.Value[5] = *(PBYTE) &authorityVal;

               authority.Value[4] = *((PBYTE) &authorityVal+1);

               authority.Value[3] = *((PBYTE) &authorityVal+2);

               authority.Value[2] = *((PBYTE) &authorityVal+3);

               authority.Value[1] = 0;

               authority.Value[0] = 0;


               // Initialize variables for subsequent operations


               sid = NULL;

               userNameSize   = MAX_NAME_STRING;

               domainNameSize = MAX_NAME_STRING;

               if( AllocateAndInitializeSid( &authority,










                                              &sid )) {


                        // We can finally lookup the account name


                        if( LookupAccountSid( ServerName,






                                                   &sidType )) {


                             // We've successfully looked up the user name


                           if( first && !UserName ) {


                                   wprintf(L"Users logged on locally:\n");

                                  first = FALSE;


                           if( !UserName || !wcsicmp( UserName, userName )) {


                                first = FALSE;

                                if( UserName ) wprintf(RESETLINE L"%s\\%s logged onto %s locally.\n",

                                                                 domainName, UserName, ServerName );

                                else                 wprintf( L"     %s\\%s\n", domainName, userName );




                if( sid ) FreeSid( sid );



       subKeyNameSize = sizeof( subKeyName );



    RegCloseKey( usersKey );

    if( first && !UserName ) wprintf(L"No one is logged on locally.\n");

    return !first;


// Code taken from

// (no longer available)

Open in new window

LVL 86

Expert Comment

ID: 24804109
So, what would you have requested to grade that 'A'? What is missing?

Author Comment

ID: 24809624
t wouldn't compile as you had written it. So I made some changes to it to make it work. I meant no disfavor though.

Featured Post

Get up to 2TB FREE CLOUD per backup license!

An exclusive Black Friday offer just for Expert Exchange audience! Buy any of our top-rated backup solutions & get up to 2TB free cloud per system! Perform local & cloud backup in the same step, and restore instantly—anytime, anywhere. Grab this deal now before it disappears!

Join & Write a Comment

As with any other System Center product, the installation for the Authoring Tool can be quite a pain sometimes. This article serves to help you avoid making these mistakes and hopefully save you a ton of time on troubleshooting :)  Step 1: Make sur…
Deploying a Microsoft Access application in a Citrix environment is not difficult but takes a few steps. However, Citrix system people are often of little help, as they typically know next to nothing about Access. The script provided here will take …
The viewer will learn how to use a discrete random variable to simulate the return on an investment over a period of years, create a Monte Carlo simulation using the discrete random variable, and create a graph to represent the possible returns over…
The viewer will learn how to use and create keystrokes in Netbeans IDE 8.0 for Windows.

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now