/**************************************************************************** PROGRAM: OWNTREE PURPOSE: Allows ownership of all files in a tree to be changed FUNCTIONS: FudgeFileName() - fills out a filename and shifts it to upper case InputDlgProc() - handler for input dialog box messages Main() - calls initialization, starts 1st dialog, processes messages COMMENTS: ****************************************************************************/ #include "owntree.h" #include #include #define DIRLEN 200 #define DBG_WAIT 0 BOOL DoOwnTree(VOID); LPTSTR FudgeFileName(LPTSTR); BOOL CALLBACK InputDlgProc(HWND,UINT,UINT,LONG); LPTSTR MyLoadString(UINT); PVOID MyAlloc(size_t); PVOID MyRealloc(PVOID,size_t); LPTSTR MyStringConvert(LPSTR); BOOL CALLBACK ScanningDlgProc(HWND,UINT,UINT,LONG); BOOL ScanTree(HWND,LPTSTR); HANDLE hModule; /* handle of this run */ HANDLE hMainWnd; /* handle of main window */ BOOL UserCancelled; /* user cancel flag */ TCHAR OwnPath[DIRLEN+1]; /* path to change ownership */ /**************************************************************************** FUNCTION: Main(INT,PCHAR) PURPOSE: Calls initialization functions. Processes messages. COMMENTS: ****************************************************************************/ int _CRTAPI1 main( IN INT argc, IN PCHAR argv[] ) { MSG msg; /* message from windows */ LPTSTR Argv; hModule = GetModuleHandle(NULL); /* Parse command line */ if(argc >= 2){ Argv = MyStringConvert(argv[1]); lstrcpy(OwnPath,Argv); } else { GetCurrentDirectory(DIRLEN,OwnPath); } FudgeFileName(OwnPath); /* Initiate first dialog box */ CreateDialog(hModule,MAKEINTRESOURCE(OWNTREEINPUTDLG),NULL,InputDlgProc); /* Message processing loop */ while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } /* Cleanup and terminate */ free(Argv); return(msg.wParam); } /**************************************************************************** FUNCTION: InputDlgProc(HWND, unsigned, WORD, LONG) PURPOSE: Processes messages for the OwnTree input dialog box. MESSAGES: WM_INITDIALOG - initialize dialog box WM_COMMAND - process input from user COMMENTS: ****************************************************************************/ BOOL CALLBACK InputDlgProc( HWND hDlg, /* handle of this dialog box */ UINT message, /* type of message */ UINT wParam, /* message-specific information */ LONG lParam /* message-specific information */ ) { UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: SetDlgItemText(hDlg,ID_OWNTREE_PATH_ENTRY,OwnPath); SendDlgItemMessage(hDlg,ID_OWNTREE_PATH_ENTRY,EM_SETSEL, 0,MAKELONG(0,0x7fff)); SetFocus(GetDlgItem(hDlg,ID_OWNTREE_PATH_ENTRY)); return(FALSE); case WM_COMMAND: if(LOWORD(wParam) == IDOK) { GetDlgItemText(hDlg,ID_OWNTREE_PATH_ENTRY,OwnPath,DIRLEN); FudgeFileName(OwnPath); DestroyWindow(hDlg); DoOwnTree(); return(TRUE); } else if(LOWORD(wParam) == IDCANCEL) { DestroyWindow(hDlg); PostQuitMessage(0); return(TRUE); } } return(FALSE); } /**************************************************************************** FUNCTION: DoOwnTree(VOID) PURPOSE: Initiate tree ownership. COMMENTS: ****************************************************************************/ BOOL DoOwnTree( VOID ) { HWND hWnd; LPTSTR cUserMsg; LPTSTR cFullMsg; TCHAR cRootPath[4]; TCHAR cFSName[11]; BOOL bRetval; memcpy(cRootPath,OwnPath,3*sizeof(TCHAR)); cRootPath[3] = TEXT('\0'); *cUserMsg = TEXT('\0'); bRetval = TRUE; if(cRootPath[1]!=TEXT(':')) { cUserMsg = MyLoadString(IDS_INVALIDPATH); bRetval = FALSE; } if(GetVolumeInformation(cRootPath,NULL,0, NULL,NULL,NULL,cFSName,10) == FALSE) { cUserMsg = MyLoadString(IDS_FSERROR); bRetval = FALSE; } if(lstrcmp(cFSName,TEXT("NTFS")) != 0) { cUserMsg = MyLoadString(IDS_FSWRONGTYPE); bRetval = FALSE; } if(!bRetval) { MessageBox(NULL,cUserMsg,NULL,MB_ICONHAND|MB_SYSTEMMODAL|MB_OK); free(cUserMsg); } else { UserCancelled = FALSE; hWnd = CreateDialog(hModule,MAKEINTRESOURCE(OWNTREESCANNINGDLG), NULL,ScanningDlgProc); SendMessage(hWnd,WM_USER,0,0); } PostQuitMessage(0); return(TRUE); } /**************************************************************************** FUNCTION: ScanningDlgProc(HWND, unsigned, WORD, LONG) PURPOSE: Processes messages for the OwnTree dir scan dialog box. MESSAGES: COMMENTS: ****************************************************************************/ BOOL CALLBACK ScanningDlgProc( HWND hDlg, /* handle of this dialog box */ UINT message, /* type of message */ UINT wParam, /* message-specific information */ LONG lParam /* message-specific information */ ) { UNREFERENCED_PARAMETER(lParam); switch(message) { case WM_INITDIALOG: return(TRUE); case WM_USER: ScanTree(hDlg,OwnPath); DestroyWindow(hDlg); return(TRUE); case WM_COMMAND: if(LOWORD(wParam) == IDCANCEL) { UserCancelled = TRUE; return(TRUE); } break; } return(FALSE); } /**************************************************************************** FUNCTION: ProcessPendingMessages(VOID) PURPOSE: Checks for messages and dispatches them. COMMENTS: ****************************************************************************/ VOID ProcessPendingMessages( VOID ) { MSG msg; while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { DispatchMessage(&msg); } } /**************************************************************************** FUNCTION: VOID TakeOwnerShip(LPTSTR,HWND) PURPOSE: Takes ownership of the specified file or directory. COMMENTS: ****************************************************************************/ VOID TakeOwnerShip( LPTSTR cFName, HWND hWnd ) { static SECURITY_DESCRIPTOR sdSecurityDesc; static INT CallFlag = 0; BOOL bRet; INT iRet; TCHAR cMsg[512]; HANDLE hTokHandle; DWORD dwLength; PTOKEN_OWNER pTokInfo; if( CallFlag == 0 ) { CallFlag = 1; bRet = InitializeSecurityDescriptor( &sdSecurityDesc, SECURITY_DESCRIPTOR_REVISION ); if( FALSE == bRet ) { iRet = MessageBox( hWnd, TEXT("Unable to initialize security descriptor!"), TEXT("OwnTree: Fatal Error"), MB_ICONSTOP | MB_OK ); UserCancelled = TRUE; } if( TRUE == bRet ) { // Get token of this process bRet = OpenProcessToken( GetCurrentProcess(), TOKEN_ALL_ACCESS, &hTokHandle ); if( FALSE == bRet ) { iRet = MessageBox( hWnd, TEXT("Unable to open process token!"), TEXT("OwnTree: Fatal Error"), MB_ICONSTOP | MB_OK ); UserCancelled = TRUE; } } if( TRUE == bRet ) { // Get token info of this process to get user's SID GetTokenInformation( hTokHandle, TokenOwner, NULL, 0, &dwLength ); if( dwLength > 0 ) { pTokInfo = MyAlloc( dwLength ); bRet = GetTokenInformation( hTokHandle, TokenOwner, (LPVOID)pTokInfo, dwLength, &dwLength ); } else { bRet = FALSE; } if( FALSE == bRet ) { iRet = MessageBox( hWnd, TEXT("Unable to retrieve process token!"), TEXT("OwnTree: Fatal Error"), MB_ICONSTOP | MB_OK ); UserCancelled = TRUE; } } if( TRUE == bRet ) { // Change owner bRet = SetSecurityDescriptorOwner( &sdSecurityDesc, pTokInfo->Owner, FALSE ); if( FALSE == bRet ) { iRet = MessageBox( hWnd, TEXT("Unable to set owner in security descriptor!"), TEXT("OwnTree: Fatal Error"), MB_ICONSTOP | MB_OK ); UserCancelled = TRUE; } } if( UserCancelled == TRUE ) { return; } } bRet = SetFileSecurity( cFName, OWNER_SECURITY_INFORMATION, &sdSecurityDesc ); if( FALSE == bRet ) { wsprintf( cMsg, TEXT("Unable to set file security: %s!"), cFName ); iRet = MessageBox( hWnd, cMsg, TEXT("OwnTree: Error"), MB_ICONSTOP | MB_OKCANCEL ); if( iRet == IDCANCEL ) { UserCancelled = TRUE; } } } /**************************************************************************** FUNCTION: ScanTree(HWND,LPTSTR) PURPOSE: Scans tree and changes ownerships of all files. Also maintains the current file display in the dialog box. COMMENTS: Returns FALSE on any error or user cancel. Returns TRUE on success. ****************************************************************************/ BOOL ScanTree( HWND hDlg, /* handle of scanning dialog box */ LPTSTR cScanPath /* path to scan in this pass */ ) { BOOL retval; HANDLE hFile; WIN32_FIND_DATA FindData; TCHAR cFullPath[DIRLEN+4+1]; LPTSTR cCancelQuery; LPTSTR cCancelCaption; LPTSTR cUserMsg; LPTSTR cFullMsg; INT iMBval; retval = TRUE; lstrcpy(cFullPath,cScanPath); if(cFullPath[lstrlen(cFullPath)-1] != TEXT('\\')) { lstrcat(cFullPath,TEXT("\\")); } lstrcat(cFullPath,TEXT("*.*")); hFile = FindFirstFile(cFullPath,&FindData); if(hFile == INVALID_HANDLE_VALUE) { cUserMsg = MyLoadString(IDS_OPENERROR); cFullMsg = MyAlloc((lstrlen(cUserMsg)+ lstrlen(cScanPath)+10)*sizeof(TCHAR)); wsprintf(cFullMsg,TEXT("%s\n%s"),cUserMsg,cScanPath); MessageBox(hDlg,cFullMsg,NULL,MB_ICONHAND|MB_OK); free(cUserMsg); free(cFullMsg); return(FALSE); } do { if(lstrcmp(FindData.cFileName,TEXT("."))==0 || lstrcmp(FindData.cFileName,TEXT(".."))==0) { continue; } lstrcpy(cFullPath,cScanPath); if(cFullPath[lstrlen(cFullPath)-1] != TEXT('\\')) { lstrcat(cFullPath,TEXT("\\")); } lstrcat(cFullPath,FindData.cFileName); if(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { retval = ScanTree(hDlg,cFullPath); if(!retval) { break; } } else { FudgeFileName(cFullPath); SetDlgItemText(hDlg,ID_OWNTREE_CURR_FILE,cFullPath); Sleep(DBG_WAIT); TakeOwnerShip(cFullPath,hDlg); } ProcessPendingMessages(); if(UserCancelled) { cCancelQuery = MyLoadString(IDS_CANCELQUERY); cCancelCaption = MyLoadString(IDS_CANCELCAPTION); iMBval = MessageBox(hDlg,cCancelQuery,cCancelCaption, MB_ICONHAND|MB_YESNO); free(cCancelQuery); free(cCancelCaption); if(iMBval == IDYES) { return(FALSE); } else { UserCancelled = FALSE; } } } while(FindNextFile(hFile,&FindData)); FindClose(hFile); if(retval) { FudgeFileName(cScanPath); SetDlgItemText(hDlg,ID_OWNTREE_CURR_FILE,cScanPath); Sleep(DBG_WAIT); TakeOwnerShip(cScanPath,hDlg); } return(retval); } /**************************************************************************** FUNCTION: LPTSTR MyLoadString(UINT) PURPOSE: Allocates buffer and loads string. Returns ptr to buffer. COMMENTS: ****************************************************************************/ LPTSTR MyLoadString( UINT wIndex /* string id to load */ ) { TCHAR cRawBuff[BIGBUFFLEN+1]; LPTSTR cActBuff; INT nLength; nLength = LoadString(hModule,wIndex,cRawBuff,BIGBUFFLEN); if(nLength) { cActBuff=MyAlloc((nLength+1)*sizeof(TCHAR)); if(cActBuff) { lstrcpy(cActBuff,cRawBuff); return(cActBuff); } } return(NULL); } /**************************************************************************** FUNCTION: PVOID MyAlloc(size_t) PURPOSE: Allocates memory and uses MessageBox on error. COMMENTS: ****************************************************************************/ PVOID MyAlloc( size_t szSize ) { PVOID retval; LPTSTR cStr; INT nLoadFlag; retval = (VOID *)malloc(szSize); if(retval) { return(retval); } else { cStr = MyLoadString(IDS_MEMERROR); if(!cStr) { nLoadFlag = FALSE; cStr = TEXT("Memory Error"); } else { nLoadFlag = TRUE; } MessageBox(NULL,cStr,NULL,MB_ICONHAND|MB_SYSTEMMODAL|MB_OK); if(nLoadFlag) { free(cStr); } exit(0); } } /**************************************************************************** FUNCTION: PVOID MyRealloc(PVOID,size_t) PURPOSE: Allocates memory and uses MessageBox on error. COMMENTS: ****************************************************************************/ PVOID MyRealloc( PVOID pPtr, size_t szSize ) { PVOID retval; LPTSTR cStr; INT nLoadFlag; retval = realloc(pPtr,szSize); if(retval) { return(retval); } else { cStr = MyLoadString(IDS_MEMERROR); if(!cStr) { nLoadFlag = FALSE; cStr = TEXT("Memory Error"); } else { nLoadFlag = TRUE; } MessageBox(NULL,cStr,NULL,MB_ICONHAND|MB_SYSTEMMODAL|MB_OK); if(nLoadFlag) { free(cStr); } exit(0); } } /**************************************************************************** FUNCTION: LPTSTR FudgeFileName(LPTSTR) PURPOSE: Shifts filename to upper case and fills out pathname. COMMENTS: Returns a pointer to the input buffer. ****************************************************************************/ LPTSTR FudgeFileName( LPTSTR cIn ) { LPTSTR cOut; DWORD nLength; nLength = GetFullPathName(cIn,0,NULL,NULL); cOut = MyAlloc((nLength+1)*sizeof(TCHAR)); GetFullPathName(cIn,nLength,cOut,NULL); CharUpperBuff(cOut,nLength); lstrcpy(cIn,cOut); free(cOut); return(cIn); } /**************************************************************************** FUNCTION: LPTSTR MyStringConvert(LPSTR) PURPOSE: Converts string from ANSI to UNICODE. COMMENTS: Returns a pointer to a buffer with the converted string. ****************************************************************************/ LPTSTR MyStringConvert( LPSTR cIn ) { LPTSTR cOut; INT cLength; cLength = strlen(cIn); cOut = MyAlloc((lstrlenA(cIn)+1)*sizeof(TCHAR)); #ifdef UNICODE mbstowcs(cOut,cIn,9999); #else lstrcpyA(cOut,cIn); #endif return(cOut); }