G:/ScriptBasic/source/extensions/nt/interface.c

Go to the documentation of this file.
00001 /* FILE: nt.c
00002    BAS: nt.bas
00003 
00004    AUTHOR: Peter Verhas
00005    DATE:   2002
00006 
00007 This file is a ScriptBasic interface to NT system calls
00008 that are not available under UNIX and thus are not
00009 implemented in the core of ScriptBasic.
00010 
00011 Never try to compile this file under UNIX or MacOS!
00012 
00013 This line tells the program setup.pl that this module can only be
00014 installed under Windows.
00015 
00016 NTLIBS: advapi32.lib user32.lib kernel32.lib
00017 
00018 */
00019 #include <stdio.h>
00020 #include "../../basext.h"
00021 
00022 #include <windows.h>
00023 #include <winbase.h>
00024 #include <winreg.h>
00025 #include <tlhelp32.h>
00026 #include <winsvc.h>
00027 
00028 #include <stdio.h>
00029 #include <winnt.h>
00030 #include <winioctl.h>
00031 #include <string.h>
00032 #include <tchar.h>
00033 
00053 besVERSION_NEGOTIATE
00054 
00055   return (int)INTERFACE_VERSION;
00056 
00057 besEND
00058 
00059 besSUB_START
00060 
00061 besEND
00062 
00063 besSUB_FINISH
00064 
00065 besEND
00066 
00067 #define NT_ERROR_INVALID_KEY        0x00081001
00068 #define NT_ERROR_NOT_DELETED        0x00081002
00069 #define NT_ERROR_REGISTRY           0x00081003
00070 #define NT_ERROR_NOT_SET            0x00081004
00071 
00072 /* Note that this is the maximal length that this module handles
00073    for registry key length or registry binary or string value.
00074 */
00075 #define STRING_BUFFER_LENGTH 256
00076 
00077 static int ChopHive(VARIABLE Argument,
00078                     unsigned long *pLen,
00079                     PHKEY phKey){
00080 
00081 #define IFK(Y) if( STRLEN(Argument) >= (*pLen = strlen(#Y)) && ! memcmp(STRINGVALUE(Argument),#Y,*pLen) ){\
00082                  *phKey = Y;\
00083                  }else
00084 
00085   IFK(HKEY_CLASSES_ROOT)
00086   IFK(HKEY_CURRENT_CONFIG)
00087   IFK(HKEY_CURRENT_USER)
00088   IFK(HKEY_LOCAL_MACHINE)
00089   IFK(HKEY_USERS)
00090   IFK(HKEY_PERFORMANCE_DATA)
00091 #undef IFK
00092 #define IFK(Y,X) if( STRLEN(Argument) >= (*pLen = strlen(#Y)) && ! memcmp(STRINGVALUE(Argument),#Y,*pLen) ){\
00093                    *phKey = X;\
00094                    }else
00095   IFK(HKCR,HKEY_CLASSES_ROOT)
00096   IFK(HKCC,HKEY_CURRENT_CONFIG)
00097   IFK(HKCU,HKEY_CURRENT_USER)
00098   IFK(HKLM,HKEY_LOCAL_MACHINE)
00099   IFK(HKU ,HKEY_USERS)
00100   IFK(HKPD,HKEY_PERFORMANCE_DATA)
00101   /* ELSE */
00102   { return 0; }
00103   return 1;
00104   }
00105 
00145 besFUNCTION(regread)
00146   VARIABLE Argument;
00147   HKEY hKey,hRes;
00148   unsigned long sLen;
00149   char *s,*r,*pszSubKey;
00150   LONG Ret;
00151   char *pszData,szDummy;
00152   DWORD  dwType;
00153   DWORD  cbData;
00154   unsigned char swap;
00155 
00156   besRETURNVALUE = NULL;
00157   if( besARGNR < 1 )return EX_ERROR_TOO_FEW_ARGUMENTS;
00158   /* get the key */
00159   Argument = besARGUMENT(1);
00160   besDEREFERENCE(Argument);
00161   Argument = besCONVERT2STRING(Argument);
00162   if( ! ChopHive(Argument,&sLen,&hKey) )
00163     return NT_ERROR_INVALID_KEY;
00164 
00165   besCONVERT2ZCHAR(Argument,s);
00166   pszSubKey = s + sLen + 1; /* +1 to step over the \\ after HKLM*/
00167   sLen = STRLEN(Argument) - sLen;
00168   r = s + STRLEN(Argument);
00169   while( sLen && *r != '\\' ){
00170     sLen --;
00171     r--;
00172     }
00173 
00174   if( sLen ){
00175     *r = (char)0;
00176     r++;
00177     }else{
00178     besFREE(s);
00179     return NT_ERROR_INVALID_KEY;
00180     }
00181 
00182   Ret = RegOpenKeyEx(hKey,pszSubKey,0,KEY_READ,&hRes);
00183 
00184   if( Ret != ERROR_SUCCESS ){
00185     besFREE(s);
00186     return COMMAND_ERROR_SUCCESS;
00187     }
00188 
00189   cbData = 0;
00190   Ret = RegQueryValueEx(hRes,r,NULL,&dwType,&szDummy,&cbData);
00191   if( Ret == ERROR_MORE_DATA ){
00192     pszData = besALLOC(cbData);
00193     if( pszData == NULL ){
00194       besFREE(s);
00195       return COMMAND_ERROR_MEMORY_LOW;
00196       }
00197     }else{
00198     pszData = besALLOC(cbData=1);
00199     if( pszData == NULL ){
00200       besFREE(s);
00201       return COMMAND_ERROR_MEMORY_LOW;
00202       }
00203     }
00204   Ret = RegQueryValueEx(hRes,r,NULL,&dwType,pszData,&cbData);
00205   RegCloseKey(hRes);
00206   besFREE(s);
00207 
00208   if( Ret != ERROR_SUCCESS ){
00209     besFREE(pszData);
00210     return COMMAND_ERROR_SUCCESS;
00211     }
00212 
00213   switch( dwType ){
00214     case REG_DWORD_BIG_ENDIAN:
00215       if( cbData < 4 ){/* would be strange */
00216         besFREE(pszData);
00217         return NT_ERROR_REGISTRY;
00218         }
00219       swap = pszData[0]; pszData[0] = pszData[3]; pszData[3] = swap;
00220       swap = pszData[1]; pszData[1] = pszData[2]; pszData[2] = swap;
00221       /* ROLL OVER */
00222     case REG_DWORD:
00223       besALLOC_RETURN_LONG;
00224       memcpy(& LONGVALUE(besRETURNVALUE),pszData,sizeof(DWORD));
00225       besFREE(pszData);
00226       return COMMAND_ERROR_SUCCESS;
00227     case REG_BINARY:
00228     case REG_MULTI_SZ:
00229     case REG_SZ:
00230       besALLOC_RETURN_STRING(cbData);
00231       memcpy(STRINGVALUE(besRETURNVALUE),pszData,cbData);
00232       besFREE(pszData);
00233       return COMMAND_ERROR_SUCCESS;
00234     /* this module does NOT handle these types */
00235     case REG_LINK:
00236     case REG_NONE:
00237     case REG_RESOURCE_LIST:
00238       besFREE(pszData);
00239       return COMMAND_ERROR_SUCCESS;
00240       }
00241   besFREE(pszData);
00242 
00243 besEND
00244 
00258 besFUNCTION(regdel)
00259   VARIABLE Argument;
00260   HKEY hKey,hRes;
00261   unsigned long sLen;
00262   char *s,*r,*pszSubKey;
00263   LONG Ret;
00264 
00265   besRETURNVALUE = NULL;
00266   if( besARGNR < 1 )return EX_ERROR_TOO_FEW_ARGUMENTS;
00267   /* get the key */
00268   Argument = besARGUMENT(1);
00269   besDEREFERENCE(Argument);
00270   Argument = besCONVERT2STRING(Argument);
00271   if( ! ChopHive(Argument,&sLen,&hKey) )
00272     return NT_ERROR_INVALID_KEY;
00273 
00274   besCONVERT2ZCHAR(Argument,s);
00275   pszSubKey = s + sLen + 1; /* +1 to step over the \\ after HKLM*/
00276 
00277   /* try to delete it as a key */
00278   Ret = RegDeleteKey(hKey,pszSubKey);
00279   if( Ret == ERROR_SUCCESS ){
00280     besFREE(s);
00281     return COMMAND_ERROR_SUCCESS;
00282     }
00283 
00284   /* if this is not a key then delete the value */
00285   sLen = STRLEN(Argument) - sLen;
00286   r = s + STRLEN(Argument);
00287   while( sLen && *r != '\\' ){
00288     sLen --;
00289     r--;
00290     }
00291 
00292   if( sLen ){
00293     *r = (char)0;
00294     r++;
00295     }else{
00296     besFREE(s);
00297     return NT_ERROR_INVALID_KEY;
00298     }
00299 
00300   Ret = RegOpenKeyEx(hKey,pszSubKey,0,KEY_WRITE,&hRes);
00301   if( Ret != ERROR_SUCCESS ){
00302     besFREE(s);
00303     return NT_ERROR_NOT_DELETED;
00304     }
00305   Ret = RegDeleteValue(hRes,r);
00306   besFREE(s);
00307   RegCloseKey(hRes);
00308   if( Ret != ERROR_SUCCESS ){
00309     return NT_ERROR_NOT_DELETED;
00310     }
00311   return COMMAND_ERROR_SUCCESS;
00312 
00313 besEND
00314 
00327 besFUNCTION(regwrite)
00328   VARIABLE Argument;
00329   HKEY hKey,hRes;
00330   unsigned long sLen;
00331   char *s,*r,*pszSubKey;
00332   LONG Ret;
00333 
00334   besRETURNVALUE = NULL;
00335   if( besARGNR < 2 )return EX_ERROR_TOO_FEW_ARGUMENTS;
00336   /* get the key */
00337   Argument = besARGUMENT(1);
00338   besDEREFERENCE(Argument);
00339   Argument = besCONVERT2STRING(Argument);
00340   if( ! ChopHive(Argument,&sLen,&hKey) )
00341     return COMMAND_ERROR_SUCCESS;
00342 
00343   besCONVERT2ZCHAR(Argument,s);
00344   pszSubKey = s + sLen + 1; /* +1 to step over the \\ after HKLM*/
00345   sLen = STRLEN(Argument) - sLen;
00346   r = s + STRLEN(Argument);
00347   while( sLen && *r != '\\' ){
00348     sLen --;
00349     r--;
00350     }
00351 
00352   if( sLen ){
00353     *r = (char)0;
00354     r++;
00355     }else{
00356     besFREE(s);
00357     return COMMAND_ERROR_SUCCESS;
00358     }
00359 
00360   Ret = RegOpenKeyEx(hKey,pszSubKey,0,KEY_WRITE,&hRes);
00361   if( Ret != ERROR_SUCCESS ){
00362     besFREE(s);
00363     return NT_ERROR_INVALID_KEY;
00364     }
00365 
00366   /* get the value of the registry value */
00367   Argument = besARGUMENT(2);
00368   besDEREFERENCE(Argument);
00369   switch( TYPE(Argument) ){
00370     case VTYPE_DOUBLE:
00371       Argument = besCONVERT2LONG(Argument);
00372     case VTYPE_LONG:
00373       Ret = RegSetValueEx(hRes,r,0,REG_DWORD, (char *)& LONGVALUE(Argument),sizeof(long));
00374       break;
00375     case VTYPE_STRING:
00376       Ret = RegSetValueEx(hRes,r,0,REG_BINARY,STRINGVALUE(Argument),STRLEN(Argument));
00377     }
00378   besFREE(s);
00379   if( Ret == ERROR_SUCCESS )return COMMAND_ERROR_SUCCESS;
00380   return NT_ERROR_NOT_SET;
00381 besEND
00382 
00490 besFUNCTION(msgbox)
00491   char *pszTitle,*pszCaption;
00492   char *pszButtons,*pszStyle;
00493   long lDefault;
00494   int iError;
00495   int iMsgResult;
00496   UINT uType;
00497 
00498   iError = besGETARGS "zz[zzi]", &pszTitle, &pszCaption, &pszButtons , &pszStyle , &lDefault besGETARGE;
00499 
00500   if( iError )return iError;
00501 
00502   uType = MB_OK;
00503 
00504   if(      ! strcmp(pszButtons,"ARI") )uType = MB_ABORTRETRYIGNORE;
00505   else if( ! stricmp(pszButtons,"OK") )uType = MB_OK;
00506   else if( ! stricmp(pszButtons,"O") )uType = MB_OK;
00507   else if( ! stricmp(pszButtons,"OC") )uType = MB_OKCANCEL;
00508   else if( ! stricmp(pszButtons,"RC") )uType = MB_RETRYCANCEL;
00509   else if( ! stricmp(pszButtons,"YN") )uType = MB_YESNO;
00510   else if( ! stricmp(pszButtons,"YNC"))uType = MB_YESNOCANCEL;
00511   else 
00512 
00513   if(      ! stricmp(pszButtons,"AbortRetryIgnore") )uType = MB_ABORTRETRYIGNORE;
00514   else if( ! stricmp(pszButtons,"Ok")               )uType = MB_OK;
00515   else if( ! stricmp(pszButtons,"OkCancel")         )uType = MB_OKCANCEL;
00516   else if( ! stricmp(pszButtons,"RetryCancel")      )uType = MB_RETRYCANCEL;
00517   else if( ! stricmp(pszButtons,"YesNo")            )uType = MB_YESNO;
00518   else if( ! stricmp(pszButtons,"YesNoCancel")      )uType = MB_YESNOCANCEL;
00519 
00520   if(      ! stricmp(pszStyle,"Exclamation") )uType |= MB_ICONEXCLAMATION;
00521   else if( ! stricmp(pszStyle,"Ex")          )uType |= MB_ICONEXCLAMATION;
00522   else if( ! stricmp(pszStyle,"Warning")     )uType |= MB_ICONWARNING;
00523   else if( ! stricmp(pszStyle,"W")           )uType |= MB_ICONWARNING;
00524   else if( ! stricmp(pszStyle,"Information") )uType |= MB_ICONINFORMATION;
00525   else if( ! stricmp(pszStyle,"Info")        )uType |= MB_ICONINFORMATION;
00526   else if( ! stricmp(pszStyle,"I")           )uType |= MB_ICONINFORMATION;
00527   else if( ! stricmp(pszStyle,"Asterix")     )uType |= MB_ICONASTERISK;
00528   else if( ! stricmp(pszStyle,"A")           )uType |= MB_ICONASTERISK;
00529   else if( ! stricmp(pszStyle,"*")           )uType |= MB_ICONASTERISK;
00530   else if( ! stricmp(pszStyle,"Question")    )uType |= MB_ICONQUESTION;
00531   else if( ! stricmp(pszStyle,"Q")           )uType |= MB_ICONQUESTION;
00532   else if( ! stricmp(pszStyle,"?")           )uType |= MB_ICONQUESTION;
00533   else if( ! stricmp(pszStyle,"Stop")        )uType |= MB_ICONSTOP;
00534   else if( ! stricmp(pszStyle,"S")           )uType |= MB_ICONSTOP;
00535   else if( ! stricmp(pszStyle,"Error")       )uType |= MB_ICONERROR;
00536   else if( ! stricmp(pszStyle,"E")           )uType |= MB_ICONERROR;
00537   else if( ! stricmp(pszStyle,"Hand")        )uType |= MB_ICONHAND;
00538   else if( ! stricmp(pszStyle,"H")           )uType |= MB_ICONHAND;
00539 
00540   switch( lDefault ){
00541      case 1: uType |= MB_DEFBUTTON1; break;
00542      case 2: uType |= MB_DEFBUTTON2; break;
00543      case 3: uType |= MB_DEFBUTTON3; break;
00544      case 4: uType |= MB_DEFBUTTON4; break;
00545      }
00546 
00547   iMsgResult = MessageBoxEx(NULL,pszTitle,pszCaption,uType,
00548                             MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US));
00549 
00550   besFREE(pszTitle);
00551   besFREE(pszCaption);
00552   besFREE(pszButtons);
00553   besFREE(pszStyle);
00554 
00555   besALLOC_RETURN_STRING(1);
00556   switch( iMsgResult ){
00557     case IDABORT  : *STRINGVALUE(besRETURNVALUE) = 'A'; break;
00558     case IDCANCEL : *STRINGVALUE(besRETURNVALUE) = 'C'; break;
00559     case IDIGNORE : *STRINGVALUE(besRETURNVALUE) = 'I'; break;
00560     case IDNO     : *STRINGVALUE(besRETURNVALUE) = 'N'; break;
00561     case IDOK     : *STRINGVALUE(besRETURNVALUE) = 'O'; break;
00562     case IDRETRY  : *STRINGVALUE(besRETURNVALUE) = 'R'; break;
00563     case IDYES    : *STRINGVALUE(besRETURNVALUE) = 'Y'; break;
00564     default : *STRINGVALUE(besRETURNVALUE) = ' '; break;
00565     }
00566 
00567 besEND
00568 
00603 besFUNCTION(shutdown_nt)
00604   HANDLE hToken;
00605   TOKEN_PRIVILEGES tkp;
00606   BOOL fResult;
00607   int iError;
00608   char *pszComputerName,*pszMessage;
00609   long lTimeout,lBruteForce,lReboot;
00610 
00611   iError = besGETARGS "[zz]iii", &pszComputerName, &pszMessage, &lTimeout, &lBruteForce, &lReboot besGETARGE;
00612 
00613   if(!OpenProcessToken(GetCurrentProcess(), 
00614         TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
00615     return COMMAND_ERROR_EXTENSION_SPECIFIC;
00616 
00617   LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,&tkp.Privileges[0].Luid); 
00618  
00619   tkp.PrivilegeCount = 1;
00620   tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 
00621  
00622   AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES) NULL, 0); 
00623  
00624   if(GetLastError() != ERROR_SUCCESS)
00625     return COMMAND_ERROR_EXTENSION_SPECIFIC;
00626 
00627   fResult = InitiateSystemShutdown(pszComputerName,
00628                                    pszMessage,
00629                                    (DWORD)lTimeout,
00630                                    (BOOL)(lBruteForce != 0),
00631                                    (BOOL)(lReboot != 0));
00632   if( pszComputerName )besFREE(pszComputerName);
00633   if( pszMessage )besFREE(pszMessage);
00634 
00635   if(!fResult)
00636     return COMMAND_ERROR_EXTENSION_SPECIFIC;
00637  
00638   tkp.Privileges[0].Attributes = 0; 
00639   AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES) NULL, 0); 
00640  
00641   if(GetLastError() != ERROR_SUCCESS) 
00642     return COMMAND_ERROR_EXTENSION_SPECIFIC;
00643 besEND
00674 besFUNCTION(proclist)
00675   HANDLE th;
00676   unsigned long lProcCount;
00677   PROCESSENTRY32 pe;
00678   VARIABLE Argument;
00679   LEFTVALUE Lval;
00680   VARIABLE vPROC;
00681   int i;
00682   unsigned long __refcount_;
00683 
00684   Argument = besARGUMENT(1);
00685   besLEFTVALUE(Argument,Lval);
00686 
00687   if( Lval == NULL )return COMMAND_ERROR_EXTENSION_SPECIFIC;
00688 
00689   th = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
00690   if( th == INVALID_HANDLE_VALUE )return COMMAND_ERROR_EXTENSION_SPECIFIC;
00691 
00692   /* Count the processes to allocate the appropriate size array */
00693   pe.dwSize = sizeof(PROCESSENTRY32);
00694   lProcCount = 0;
00695   if( Process32First(th,&pe) ){/* that could be weird not to have any process running */
00696     lProcCount++;
00697     while( Process32Next(th,&pe) ){
00698       lProcCount++;
00699       pe.dwSize = sizeof(PROCESSENTRY32);
00700       }
00701     }
00702 
00703   if( Lval && *Lval ){ besRELEASE(*Lval); }
00704   if( lProcCount == 0 )return COMMAND_ERROR_SUCCESS;
00705 
00706   *Lval = besNEWARRAY(0,lProcCount-1);
00707   if( *Lval == NULL )return COMMAND_ERROR_MEMORY_LOW;
00708 
00709   lProcCount = 0;
00710   Process32First(th,&pe);
00711   do{
00712     vPROC = (*Lval)->Value.aValue[lProcCount] = besNEWARRAY(0,8);
00713     if( vPROC == NULL )return COMMAND_ERROR_MEMORY_LOW;
00714     for( i=0 ; i < 8 ; i++ ){
00715       vPROC->Value.aValue[i] = besNEWLONG;
00716       if( vPROC->Value.aValue[i] == NULL )return COMMAND_ERROR_MEMORY_LOW;
00717       }
00718     LONGVALUE(vPROC->Value.aValue[0]) = pe.cntUsage;
00719     LONGVALUE(vPROC->Value.aValue[1]) = pe.th32ProcessID; 
00720     LONGVALUE(vPROC->Value.aValue[2]) = pe.th32DefaultHeapID; 
00721     LONGVALUE(vPROC->Value.aValue[3]) = pe.th32ModuleID; 
00722     LONGVALUE(vPROC->Value.aValue[4]) = pe.cntThreads; 
00723     LONGVALUE(vPROC->Value.aValue[5]) = pe.th32ParentProcessID; 
00724     LONGVALUE(vPROC->Value.aValue[6]) = pe.pcPriClassBase; 
00725     LONGVALUE(vPROC->Value.aValue[7]) = pe.dwFlags;
00726     vPROC->Value.aValue[8] = besNEWSTRING(strlen(pe.szExeFile));
00727     if( vPROC->Value.aValue[8] == NULL )return COMMAND_ERROR_MEMORY_LOW;
00728     memcpy(STRINGVALUE(vPROC->Value.aValue[8]),pe.szExeFile,STRLEN(vPROC->Value.aValue[8]));
00729 
00730     lProcCount++;
00731     pe.dwSize = sizeof(PROCESSENTRY32);
00732     }while( Process32Next(th,&pe) );
00733 
00734   CloseHandle(th);
00735 besEND
00736 
00755 besFUNCTION(nt_startservice)
00756   char *pszServiceName;
00757   int iError;
00758   SC_HANDLE hManager,hService;
00759   SERVICE_STATUS SSTAT;
00760 
00761   iError = besGETARGS "z", &pszServiceName besGETARGE;
00762   if( iError )return iError;
00763   hManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
00764   if( hManager == NULL )return COMMAND_ERROR_EXTENSION_SPECIFIC;
00765   hService = OpenService(hManager,pszServiceName,SERVICE_START|SERVICE_QUERY_STATUS);
00766   besFREE(pszServiceName);
00767   if( hService == NULL ){
00768     iError = GetLastError();
00769     return COMMAND_ERROR_EXTENSION_SPECIFIC;
00770     }
00771   memset(&SSTAT,0,sizeof(SSTAT));
00772   if( ! QueryServiceStatus(hService,&SSTAT) ){
00773     iError = GetLastError();
00774     return COMMAND_ERROR_EXTENSION_SPECIFIC;
00775     }
00776   /* we have to query the current state of the service because StartService returns
00777      strange errors instead of ERROR_SERVICE_ALREADY_RUNNING */
00778   if( SSTAT.dwCurrentState == SERVICE_START_PENDING || 
00779       SSTAT.dwCurrentState == SERVICE_RUNNING ||
00780       SSTAT.dwCurrentState == SERVICE_CONTINUE_PENDING )return COMMAND_ERROR_SUCCESS;
00781   iError = StartService(hService,0,NULL);
00782   CloseServiceHandle(hService);
00783   CloseServiceHandle(hManager);
00784   if( iError == 0 )iError = GetLastError(); else iError = 0;
00785   if( iError == 0 || iError == ERROR_SERVICE_ALREADY_RUNNING )return COMMAND_ERROR_SUCCESS;
00786   return COMMAND_ERROR_EXTENSION_SPECIFIC;
00787 besEND
00788 
00789 /* This function is used by most of the service control functions
00790    implemented in this interface file that start stop, pause and continue
00791    service(s)
00792 
00793    This function gets the same argument as the interface function that calls
00794    this function and an extra argument dwControl that tells the function what
00795    to do actually.
00796 */
00797 static int ControlNtService(pSupportTable pSt,
00798                             void **ppModuleInternal,
00799                             pFixSizeMemoryObject pParameters,
00800                             DWORD dwControl
00801   ){
00802   char *pszServiceName;
00803   int iError;
00804   SC_HANDLE hManager,hService;
00805   SERVICE_STATUS SSTAT;
00806 
00807   iError = besGETARGS "z", &pszServiceName besGETARGE;
00808   if( iError )return iError;
00809   hManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
00810   if( hManager == NULL )return COMMAND_ERROR_EXTENSION_SPECIFIC;
00811   hService = OpenService(hManager,pszServiceName,SERVICE_ALL_ACCESS);
00812   besFREE(pszServiceName);
00813   if( hService == NULL )return COMMAND_ERROR_EXTENSION_SPECIFIC;
00814   memset(&SSTAT,0,sizeof(SSTAT));
00815   iError = ControlService(hService,dwControl,&SSTAT);
00816 
00817   CloseServiceHandle(hService);
00818   CloseServiceHandle(hManager);
00819   if( iError == 0 )iError = GetLastError(); else iError = 0;
00820   if( iError )return COMMAND_ERROR_EXTENSION_SPECIFIC;
00821   return COMMAND_ERROR_SUCCESS;
00822   }
00823 
00824 #define CONTROL_NT_SERVICE(X) ControlNtService(pSt,ppModuleInternal,pParameters,X)
00825 
00844 besFUNCTION(nt_stopservice)
00845   return CONTROL_NT_SERVICE(SERVICE_CONTROL_STOP);
00846 besEND
00847 
00865 besFUNCTION(nt_pauseservice)
00866   return CONTROL_NT_SERVICE(SERVICE_CONTROL_PAUSE);
00867 besEND
00868 
00886 besFUNCTION(nt_continueservice)
00887   return CONTROL_NT_SERVICE(SERVICE_CONTROL_CONTINUE);
00888 besEND
00889 
00918 static int lnw(char *,char *);
00919 static int CreateJunction( char *LinkDirectory, char *LinkTarget );
00920 
00921 besFUNCTION(nt_hardlink)
00922   char *pszFileName,*pszNewName;
00923   int iError;
00924 
00925   iError = besGETARGS "zz", &pszFileName,&pszNewName besGETARGE;
00926   if( iError )return iError;
00927 
00928   iError = (GetFileAttributes(pszFileName) & FILE_ATTRIBUTE_DIRECTORY)  ?
00929     CreateJunction(pszNewName,pszFileName)
00930   :
00931     lnw(pszFileName,pszNewName);
00932   
00933   if( iError )return COMMAND_ERROR_EXTENSION_SPECIFIC;
00934   return COMMAND_ERROR_SUCCESS;
00935 besEND
00936 
00937 
00938 void enableprivs(){
00939   HANDLE hToken;
00940   byte buf[sizeof(TOKEN_PRIVILEGES) * 2];
00941   TOKEN_PRIVILEGES *tkp = ( (TOKEN_PRIVILEGES *) buf );
00942 
00943   if ( ! OpenProcessToken( GetCurrentProcess(),
00944       TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) )
00945       return;
00946 
00947   // enable SeBackupPrivilege, SeRestorePrivilege
00948 
00949   if ( !LookupPrivilegeValue( NULL, SE_BACKUP_NAME, &tkp->Privileges[0].Luid ) )
00950       return;
00951 
00952   if ( !LookupPrivilegeValue( NULL, SE_RESTORE_NAME, &tkp->Privileges[1].Luid ) )
00953       return;
00954 
00955   tkp->PrivilegeCount = 2;
00956   tkp->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
00957   tkp->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED;
00958 
00959   AdjustTokenPrivileges( hToken, FALSE, tkp, sizeof( *tkp ),
00960       NULL, NULL );
00961   }
00962 
00963 
00964 
00965 static int lnw(char *pszSource, char *pszDestination){
00966   HANDLE fh;
00967   static char buf1[MAX_PATH];
00968   static wchar_t buf2[MAX_PATH * 2];
00969   char *p;
00970   void *ctx = NULL;
00971   WIN32_STREAM_ID wsi;
00972   DWORD numwritten;
00973   BOOL bSourceIsReadOnly;
00974   DWORD attrib;
00975 
00976   enableprivs(); // in case we aren't admin
00977   attrib = GetFileAttributes(pszSource);
00978   if( INVALID_FILE_ATTRIBUTES == attrib ){
00979     return 1;
00980     }
00981 
00982   bSourceIsReadOnly = FALSE;
00983   if( attrib & FILE_ATTRIBUTE_READONLY ){
00984     bSourceIsReadOnly = TRUE; /* remember that we have altered the attributes, has to be restored when closing the handle */
00985     /* remove the read only bit from the flags and ... */
00986     SetFileAttributes(pszSource,attrib & ~FILE_ATTRIBUTE_READONLY);
00987     }
00988   if( attrib & FILE_ATTRIBUTE_DIRECTORY ){
00989     return 1;
00990     }
00991 
00992   fh = CreateFile( pszSource, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
00993       FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, NULL );
00994   if ( fh == INVALID_HANDLE_VALUE || fh == NULL ){
00995       if( bSourceIsReadOnly ){
00996         SetFileAttributes(pszSource,attrib);
00997         }
00998       return 1;
00999       }
01000 
01001   GetFullPathName( pszDestination, MAX_PATH, buf1, &p );
01002 
01003   wsi.dwStreamId = BACKUP_LINK;
01004   wsi.dwStreamAttributes = 0;
01005   wsi.dwStreamNameSize = 0;
01006   wsi.Size.QuadPart = strlen( buf1 ) * 2 + 2;
01007   MultiByteToWideChar( CP_ACP, 0, buf1, (int)strlen( buf1 ) + 1, buf2, MAX_PATH );
01008 
01009   if( ! BackupWrite( fh, (byte *) &wsi, 20, &numwritten, FALSE, FALSE, &ctx ) ){
01010     return 1;
01011     }
01012   if( numwritten != 20 ){
01013     return 1;
01014     }
01015 
01016   if( ! BackupWrite( fh, (byte *) buf2, wsi.Size.LowPart, &numwritten, FALSE, FALSE, &ctx ) ){
01017     return 1;
01018     }
01019   if( numwritten != wsi.Size.LowPart ){
01020     return 1;
01021     }
01022 
01023   // make NT release the context
01024   if( ! BackupWrite( fh, (byte *) &buf1[0], 0, &numwritten, TRUE, FALSE, &ctx ) ){
01025     return 1;
01026     }
01027 
01028   CloseHandle( fh );
01029   if( bSourceIsReadOnly ){
01030     SetFileAttributes(pszSource,attrib);
01031     }
01032   return 0;
01033   }
01034 
01035 typedef struct _REPARSE_DATA_BUFFER {
01036     DWORD  ReparseTag;
01037     WORD   ReparseDataLength;
01038     WORD   Reserved;
01039     union {
01040         struct {
01041             WORD   SubstituteNameOffset;
01042             WORD   SubstituteNameLength;
01043             WORD   PrintNameOffset;
01044             WORD   PrintNameLength;
01045             WCHAR PathBuffer[1024];
01046         } SymbolicLinkReparseBuffer;
01047         struct {
01048             WORD   SubstituteNameOffset;
01049             WORD   SubstituteNameLength;
01050             WORD   PrintNameOffset;
01051             WORD   PrintNameLength;
01052             WCHAR PathBuffer[1024];
01053         } MountPointReparseBuffer;
01054         struct {
01055             BYTE   DataBuffer[1024];
01056         } GenericReparseBuffer;
01057     };
01058 } REPARSE_DATA_BUFFER;
01059 
01060 #define REPARSE_MOUNTPOINT_HEADER_SIZE 8
01061 
01062 #ifndef FSCTL_SET_REPARSE_POINT
01063 #  define FSCTL_SET_REPARSE_POINT    CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
01064 #  define FSCTL_GET_REPARSE_POINT    CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) 
01065 #  define FSCTL_DELETE_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 43, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) 
01066 #endif
01067 
01068 void PrintWin32Error( DWORD x){}
01069 
01070 #define toUnicode(FROM,TO)                     \
01071     MultiByteToWideChar(CP_ACP,              \
01072                         0,                     \
01073                         (char *)FROM,          \
01074                         strlen((char *)FROM)+1,\
01075                         TO,                    \
01076                         sizeof(TO))
01077 
01078 static int CreateJunction(char *LinkDirectory, char *LinkTarget){
01079   REPARSE_DATA_BUFFER   reparseBuffer;
01080   char    directoryFileName[MAX_PATH];
01081   char    targetFileName[MAX_PATH];
01082   char    targetNativeFileName[MAX_PATH];
01083   WCHAR   wtargetNativeFileName[MAX_PATH];
01084   PTCHAR    filePart;
01085   HANDLE    hFile;
01086   DWORD   returnedLength;
01087   size_t slen;
01088   REPARSE_DATA_BUFFER *reparseInfo = (REPARSE_DATA_BUFFER *) &reparseBuffer;
01089 
01090   // Get the full path referenced by the target
01091   if( !GetFullPathName( LinkTarget, MAX_PATH, targetFileName, &filePart ) ){
01092     return 1;
01093     }
01094 
01095   // Get the full path referenced by the directory
01096   if( !GetFullPathName( LinkDirectory, MAX_PATH, directoryFileName, &filePart) ){
01097     return 1;
01098     }
01099 
01100   // Make the native target name
01101   sprintf( targetNativeFileName, "\\??\\%s" , targetFileName );
01102   slen = strlen(targetNativeFileName);
01103   if ( (targetNativeFileName[slen-1] == _T('\\')) &&
01104      (targetNativeFileName[slen-2] != _T(':'))) {
01105       targetNativeFileName[slen-1] = 0;
01106      }
01107 
01108   // Create the link - ignore errors since it might already exist
01109   CreateDirectory( LinkDirectory, NULL );
01110   hFile = CreateFile( LinkDirectory, GENERIC_WRITE, 0,
01111                        NULL, OPEN_EXISTING, 
01112                        FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, NULL );
01113   if( hFile == INVALID_HANDLE_VALUE ) {
01114     return 1;
01115     }
01116 
01117   toUnicode(targetNativeFileName,wtargetNativeFileName);
01118 
01119   // Build the reparse info
01120   memset( reparseInfo, 0, sizeof( REPARSE_DATA_BUFFER ));
01121   reparseInfo->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
01122   reparseInfo->SymbolicLinkReparseBuffer.SubstituteNameLength = 
01123     wcslen(wtargetNativeFileName) * sizeof(WCHAR);
01124   reparseInfo->Reserved = 0;
01125   reparseInfo->SymbolicLinkReparseBuffer.PrintNameLength = 0;
01126   reparseInfo->SymbolicLinkReparseBuffer.PrintNameOffset = 
01127     reparseInfo->SymbolicLinkReparseBuffer.SubstituteNameLength 
01128     + sizeof(WCHAR);
01129   memcpy(reparseInfo->SymbolicLinkReparseBuffer.PathBuffer, wtargetNativeFileName, 
01130     sizeof(WCHAR) 
01131     + reparseInfo->SymbolicLinkReparseBuffer.SubstituteNameLength);
01132   reparseInfo->ReparseDataLength = 
01133     reparseInfo->SymbolicLinkReparseBuffer.SubstituteNameLength + 12;
01134 
01135   // Set the link
01136   if( !DeviceIoControl(hFile, FSCTL_SET_REPARSE_POINT, reparseInfo, 
01137        reparseInfo->ReparseDataLength 
01138        + REPARSE_MOUNTPOINT_HEADER_SIZE,
01139        NULL, 0, &returnedLength, NULL)) { 
01140 
01141     CloseHandle( hFile );
01142     RemoveDirectory( LinkDirectory );
01143     return 1;
01144     }
01145   return 0;
01146   }
01147 
01148 

Generated on Sun Mar 12 23:56:29 2006 for ScriptBasic by  doxygen 1.4.6-NO